• 技术文章 >web前端 >js教程

    浅析node怎么实现单点登录系统

    青灯夜游青灯夜游2022-10-28 09:49:37转载213
    怎么实现单点登录系统?下面本篇文章给大家介绍一下使用node实现单点登录系统的方法,希望对大家有所帮助!

    大前端成长进阶课程:进入学习

    单点登录SSO(Single Sign On),就是把2个及以上的业务系统中的登录功能剥离出来,形成一个新的系统,做到一次登录后在任意的业务系统中都无需登录的效果。

    一. 基础知识

    1.1 同源策略

    源 = 协议 + 域名 +端口

    以http://www.a.com为例:

    同源策略是浏览器的行为,它通过确保应用下的资源只能被本应用访问,来保证安全。【相关教程推荐:nodejs视频教程

    1.2 会话机制

    由于http协议是无状态协议(客户端和服务器端数据交换完毕,会关闭连接,下次请求重新建立连接),但我们需要做记住密码等功能时,很明显需要将会话记录下来。

    常用的会话跟踪就是cookie和session,简单的理解它们就是可以存放key,value的数据结构,区别在于cookie保存在客户端,session保存在服务器端。

    二. 单点登录

    1. 同父域SSO

    同父域,如www.app1.aaa.com,www.app2.aaa.com这两个服务器都是在.aaa.com的父域名。
    默认情况下,两个服务器下页面之间的cookie是互相访问不到的。

    但是我们可以通过设置cookie的domain属性为共通的父域名,使得两个服务器下页面之间的cookie可以相互访问到。

    router.get('/createCookie', async (ctx, next) => {
      ctx.cookies.set('username', '123', {
        maxAge: 60 * 60 * 1000,
        httpOnly: false,
        path: '/',
        domain:'.a.com' //设置domain为共通的父域名
      });
      ctx.body = "create cookie ok"})router.get('/getCookie', async (ctx, next) => {
      let username=ctx.cookies.get('username')
      if (username){
        ctx.body=username  }else{
        ctx.body='no cookie'
      }})

    在这里插入图片描述

    2. 跨域SSO

    当我们的域名为www.a.com,www.b.com时,无论怎样设置domain都没用了。

    那么就要想办法将身份凭证(token)写入到所有域的cookie中

    2.1 跨域写cookie
    2.1.1 利用< script />标签跨域写cookie(jsonp)

    在http://www.a.com/index.js中直接向https://www.c.com:3000/sso直接发送网络请求,是无法跨域写入cookie的。

      <script>
        $.ajax({
          url: 'https://www.c.com:3000/sso?key=username&value=123',
          method: 'get',
        })
      </script>

    但是我们可以通过< script />标签发起跨域请求,写入cookie

    <script src="https://www.c.com:3000/sso?key=username&value=123"></script>

    或者使用jquery jsonp的方式发起跨域请求,写入cookie,这种方式的原理也是通过< script />标签能够跨域实现的。

     $.ajax({
          url: 'https://www.c.com:3000/sso?key=username&value=123',
          method: 'get',
          dataType:'jsonp'
        })

    这样通过< script />标签就实现了往www.a.com中写入了domain为www.c.com的跨域cookie.
    在这里插入图片描述
    后端

    const options = {
      key: fs.readFileSync(path.join(__dirname, './https/privatekey.pem')),
      cert: fs.readFileSync(path.join(__dirname, './https/certificate.pem')),
      secureOptions: 'TLSv1_2_method' //force TLS version 1.2}var server = https.createServer(options,app.callback());  //只能使用https协议写cookierouter.get('/sso', async (ctx, next) => {
      let {
        key, value  } = ctx.request.query
      ctx.cookies.set(key, value, {
        maxAge: 60 * 60 * 1000, //有效时间,单位毫秒
        httpOnly: false, //表示 cookie 是否仅通过 HTTP(S) 发送,, 且不提供给客户端 JavaScript (默认为 true).
        path: '/',
        sameSite: 'none', //限制第三方 Cookie
        secure: true //cookie是否仅通过 HTTPS 发送
      });
      ctx.body = 'create Cookie ok'})

    注意:

    2.1.2 p3p协议头实现IE浏览器跨域

    上面说的jsonp的方式在chrome浏览器中完美运行,但是IE浏览器对于cookie更加严格,只用上面方式无法写入cookie,解决办法就是加上p3p的响应头。

    router.get('/sso', async (ctx, next) => {
      let {
        key, value  } = ctx.request.query
      ctx.cookies.set(key, value, {
        maxAge: 60 * 60 * 1000, //有效时间,单位毫秒
        httpOnly: false,
        path: '/',
        sameSite: 'none',
        secure: true
      });
      ctx.set("P3P", "CP='CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR'") //p3p响应头
      ctx.body = 'create Cookie ok'})
    2.1.3 url参数实现跨域信息传递

    访问http://www.c.com:3000/createToken?from=http://www.a.com/createCookie

    www.c.com上生成token后将url重写,带上token,重定向到www.a.com

    router.get('/createToken', async (ctx, next) => {
      let { from } = ctx.request.query  let token = "123";
      ctx.response.redirect(`${from}?token=${token}`)})

    www.a.com上从url上获取token,存入cookie

    router.get('/createCookie', async (ctx, next) => {
      let { token } = ctx.request.query
      ctx.cookies.set('token', token, {
        maxAge: 60 * 60 * 1000, //有效时间,单位毫秒
        httpOnly: false,
        path: '/',
      });
      ctx.body = 'set cookie ok'})

    这样就实现了跨域信息的传递.与上面的方式不同,这种方法只是单纯的http请求,适用于所有浏览器,但是缺点也很明显,每次只能分享给一个服务器。
    在这里插入图片描述

    2.2 跨域读cookie
    2.2.1 利用< script />标签跨域读cookie(jsonp)

    之前2.1.1利用< script />标签在www.a.com中写入了www.c.com的cookie(username,123),现在想要www.a.com请求的时候携带上www.c.com的cookie,也就是说要跨域读cookie.

    其实也是同样的方法,在www.a.com上利用< script />跨域访问访问www.c.com,会自动的带上domain为www.c.com的cookie。
    www.a.com/index.js

    <script src="https://www.c.com:3000/readCookie"></script>

    www.c.com

    router.get('/readCookie', async (ctx, next) => {
      let username = ctx.cookies.get('username')
      console.log('cookie', username)})

    在这里插入图片描述
    可以看到读取到了存储在www.a.com里面domain为www.c.com的cookie.

    3. nodejs实现单点登录系统实战

    在这里插入图片描述
    效果如图所示:

    源码: https://github.com/wantao666/sso-nodejs

    详细设计:
    在这里插入图片描述

    更多node相关知识,请访问:nodejs 教程

    以上就是浅析node怎么实现单点登录系统的详细内容,更多请关注php中文网其它相关文章!

    声明:本文转载于:csdn,如有侵犯,请联系admin@php.cn删除

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    快捷开发Web应用及小程序:点击使用

    支持亿级表,高并发,自动生成可视化后台。

    专题推荐:nodejs node
    上一篇:浅析JavaScript中的操作符与表达式 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 一文探究Node中的的进程与子进程• 浅析Node高并发的原理• Node服务怎么进行Docker镜像化?极致优化详解• 一文详解Node.js中的事件循环• 带你使用Node读写txt和Excel文件• 看看怎么使用nodejs生成二维码
    1/1

    PHP中文网