Nodejs SSO 中间件实现原理

2021/4/15 12:28:22

本文主要是介绍Nodejs SSO 中间件实现原理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

一、 什么是单点登录(SSO)

假设用户 X 需同时登录站点 A 和站点 B,这两个站点之间其实是有关联性的,但是如果用户认证数据不通用,那将需要注册或登录两次。单点登录系统(Single Sign On,简称 SSO)就是为了解决这种场景的问题,建立一种用户认证中心,只要经过这个中心注册或登录了某一站点服务的用户,总是能够认证登录这个中心所授权的其他所有服务。

  • 登录相比于单系统登录,SSO 需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso 认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。
  • 注销在一个子系统中注销,所有子系统的会话都将被销毁。

二、 什么是 CAS

CAS (Central Authentication Service) 是耶鲁 Yale 大学发起的一个 java 开源项目,旨在为 Web 应用系统提供一种可靠的单点登录解决方案( Web SSO ),github 地址。CAS 作为一种单点登录框架,后端可配置不同的用户数据库,支持自定义验证或加密逻辑,并提供不同的协议用于与业务 server(cas-client)间的通信。CAS 的源码是由 java 写的,因此对于 java 的 web 项目天生友好。当然只要实现 CAS 相关协议的 client,无论是哪种语言实现的,都能集成到 CAS 认证框架中。CAS 的部署请参考这里从结构上看, CAS 包含两个部分: CAS Server 和 CAS Client 。

  • CAS ServerCAS Server 需要独立部署,主要负责对用户的认证工作, 它会处理用户名 / 密码等凭证 (Credentials)
  • CAS ClientCAS Client 部署在客户端, 负责处理 对本地 Web 应用(客户端)受保护资源的访问请求,并且当需要对请求方进行身份认证时,重定向到 CAS Server 进行认证 。CAS Client 负责部署在客户端(Web 应用),原则上, CAS Client 的部署意味着,当有对本地 Web 应用的受保护资源的访问请求,并且需要对请求方进行身份认证, Web 应用不再接受任何的用户名密码等类似的 Credentials ,而是重定向到 CAS Server 进行认证。通常单点登陆都会涉及到对已有系统的改造。所以,client 端的侵入性就变的很重要。侵入性越小,越容易部署和测试。CAS 框架的优点之一就在于它的 client 端对应用系统的侵入性比较小。对于 Java 的 Web 项目来说,你只需要在 web.xml 里面添加一个 filter,拷贝 CAS client 的 jar 包到应用系统,然后改造登陆认证过程即可。

三、 node 项目集成 CAS

首先介绍一下项目架构,项目前端采用 Vue 开发,服务端采用 node + express 开发。项目最终上线部署时,前端打包后放在服务端的 /public 目录下,即采用 express 静态服务功能。开始我还是固有的思维,考虑在前端实现单点登录的集承,用户登录不都是在前端做的吗,调用服务端接口,CAS 也提供了一些列的 Restful Api,然而当我去实现的时候却相当麻烦,还会有跨域的问题。然后想到了可否直接在服务端控制访问权限?于是网上搜索一番,终于找到了 connect-cas2 node 中间件,其实它就是 CAS Client 的 node 实现,正好符合我的项目场景。connect-cas2 的使用也比较简单,具体请看官方文档,直接抄文档示例就可以了。以下是主要代码:

var express = require('express')
var ConnectCas = require('connect-cas2')
var bodyParser = require('body-parser')
var session = require('express-session')
var cookieParser = require('cookie-parser')
var MemoryStore = require('session-memory-store')(session)

var app = express()

app.use(cookieParser())
app.use(
  session({
    name: 'NSESSIONID',
    secret: 'Hello I am a long long long secret',
    resave: true,
    saveUninitialized: true,
    store: new MemoryStore()
  })
)

var casClient = new ConnectCas({
  debug: true,
  ignore: [/\\/ignore/],
  match: [],
  servicePrefix: '<http://localhost:3000>',
  serverPath: '<http://your-cas-server.com>',
  paths: {
    validate: 'cas/validate',
    serviceValidate: 'cas/serviceValidate',
    login: 'cas/login',
    logout: 'cas/logout',
    proxy: '',
    proxyCallback: ''
  }
})

app.use(casClient.core())
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

app.get('/logout', casClient.logout())

app.get('/', function(req, res) {
  if (!req.session.cas.user) {
    return next()
  }
  const username = req.session.cas.user
  return res.send(
    '<p>You are logged in. Your username is ' +
      username +
      '. <a href="/logout">Log Out</a></p>'
  )
})

app.get('/api', function(req, res) {
  return res.send('hi')
})

app.listen(3000)

参考

  • 单点登录原理与简单实现
  • 基于 CAS 单点登录的前后端分离架构说明
  • 单点登录终极方案之 CAS 应用及原理
  • 单点登录(一)-单点登录 SSO 的介绍和 CAS+选型
  • connect-cas2 文档
  • 基于 node.js 的 sso(单点登录-客户端校验)


这篇关于Nodejs SSO 中间件实现原理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程