Nginx+Lua实现sso单点登录(请求鉴权+获取用户Session信息)

SSO 解决方案(鉴权+SESSION信息)

项目地址在 https://github.com/1170159634/ssoSolution

一、设计背景

单点登录(SingleSignOn,SSO),就是通过用户的一次性鉴别登录。当用户在身份认证服务器上登录一次以后,即可获得访问单点登录系统中其他关联系统和应用软件的权限,意味着在多个应用系统中,用户只需一次登录就可以访问所有相互信任的应用系统

但是,鉴权和 session信息应该由谁去处理,如果是后端处理,那么每个系统 只要是对外暴露,或者涉及隐私 或者 必须要求登录情况下操作的接口都需要后端处理,这样做有以下几个缺点:

1)后台服务增加压力,并且nginx到service 请求响应时间会增加

2)增加代码复杂度,因为每个对外暴露的系统都需设计 统一或者 各个组件需要的鉴权方案,容易造成信息不一致性。

3)过多引入 第三方SSO框架会让我们的异常错误不在自己可控制的范围内。同时也不会为我们带来新的单点登录的问题解决方案,不利于提高项目的健壮性及可持续发展。

这不是设计此方案的初衷,我们更希望所有的请求从开始到结束成功或者失败 应该在我们自己的可控范围内

所以该方案,不借助于第三方框架,并期望请求都先在反向代理做校验, 这样减少了后端压力及代码复杂度,同时方便将组件统一化管理,并可以满足 跨语言系统的实现。

它更适合于 跨语言的系统之间调度,或者 JAVA 老项目(servlet session获取信息),或者希望优化代码的项目中。

二、主要解决的问题

1)请求鉴权,每个请求的访问都有严格的权限控制,公开和非公开

2)全局session管理,各个系统之间仅凭 用户本地cookie就可以拿到用户信息,方便用户操作

3)组件之间鉴权,一旦跨服务,跨系统之间调度,通过组件鉴权提高 系统安全性。

三、技术选型

模块介绍采用组件
反向代理openresty
SSO服务spring boot (java实现)
常规服务 (商品,订单,用户服务)spring boot(java实现)
浏览器页面JS

四、设计方案-流程

1.系统架构

在这里插入图片描述

2.登录流程

在这里插入图片描述

3.鉴权流程

在这里插入图片描述

3.获取session信息流程

在这里插入图片描述

五、核心功能介绍:

1.sso登录

对外暴露的接口 /api/sso/login:

    #用户登录 帮助跳到指定页或登录页
    location  = /api/sso/login {  
        lua_code_cache off;
        rewrite_by_lua_file  lua/sso_login.lua;
        root /usr/local/Cellar/openresty/1.19.9.1_2/nginx/html;
        charset utf-8;

        #默认post请求不支持跳转页面
        error_page 405 =200 $uri;
    }

​ 用户在前端页面,发起登录,nginx收到请求开始处理

  • nginx先获取post请求体中的用户名和密码,如果没有获取到用户信息,nginx重新跳到登录页
  • nginx发起内部的sso服务登录http请求(api/sso/ssoLogin),将用户信息传入,等待服务返回结果
  • 服务如果没有正确返回结果,或者http状态码不为200,nginx重新跳到登录页面
  • 如果返回结果,但是登录失败,则跳到登录失败页面
  • 如果用户登录成功,lua脚本将信息加密后存入到cookie(ut为用户登录token,uit为用户信息 ),并设置过期时间为30分钟后
  • 跳到主页

2.获取用户session信息

对外暴露的接口 /api/sso/getUserInfo:

    location  = /api/sso/getUserInfo {  
        lua_code_cache off;
        content_by_lua_file  lua/sso_user_info.lua;        
        charset utf-8;
    }

所有子系统前端页面,通过axios发起获取用户session请求

  • nginx先获取请求头中的 cookie的加密数据(ut,uit信息),一旦不存在, nginx返回json’{“code”:10001,“msg”:“用户校验失败,请重新登录”}’
  • 获取完毕后,解密uit用户信息,取出其中的userId,将用户登录token和userId发起sso服务的鉴权请求(/api/sso/checkLogin)
  • 服务如果没有正确返回结果,或者http状态码不为200,nginx 返回json ‘{“code”:10001,“msg”:“用户校,验失败,请重新登录”}’
  • 如果返回结果,但是登录失败,则nginx 返回json ‘{“code”:10001,“msg”:“用户校验失败,请重新登录”}’
  • 如果返回结果显示校验成功,返回json’{“code”:10000,“msg”:“用户校验成功”,“data”: ’ … decryptData … ‘}’,其中data里的decryptData就为 第二步解密uit用户信息的数据,拿过来直接用

3.访问公开页面(类似于浏览商品,查看商品分类等等)

对外暴露的接口 /api/XXX

    location  /api/product{
        proxy_pass  http://127.0.0.1:10082;
    }

这里不做阐述,直接放行

4.访问私密页面(类似于用户订单,用户收藏,用户好友列表等等)

对外暴露的接口 /api/XXX

    location  /api/order{
        lua_code_cache off;
        access_by_lua_file lua/sso_filter.lua;
        proxy_pass  http://127.0.0.1:10081;

    }

浏览器在访问这种的请求时,lua的策略是做权限控制,如果校验通过放行,下发到后面的服务,如果校验不通过,直接让nginx返回 401 500等页面

这里注意:正则表达式可以拦截所有 以/api开头的请求,统一判断,如果请求里包含了"order" “user” "password"等关键字的请求,可以做校验,不然则放行,看个人需要。

  • nginx先获取请求头中的 cookie的加密数据(ut,uit信息),一旦不存在, nginx直接跳转到400页面
  • 获取完毕后,解密uit用户信息,取出其中的userId,将用户登录token和userId发起sso服务的鉴权请求(/api/sso/checkLogin)
  • 服务如果没有正确返回结果,或者http状态码不为200,nginx 跳转到500页面
  • 如果返回结果,但是登录失败,则nginx跳转到401页面
  • 如果返回结果显示校验成功,直接放行

六、后台服务接口文档

1.sso接口

(1)用户登录

【功能定义】

用户登录,并授予用户登录token及session信息(nginx校验用)
接口地址:http://:/sso/ssoLogin

输入:

参数名参数类型是否必填备注
user_nameString用户名
user_passwordString用户密码
target_urlString用户将要访问的资源
host_ipString用户登录地址

输出:

参数参数类型备注
codeint10000 校验成功,能够获取用户信息,
10001 校验失败,用户名或密码错误
10002 用户服务异常
10003 未知异常
10004 字段校验错误
msgstring中文描述
DataJSONObject结果详情 用户session信息,用户token,用户id
(2)获取用户session信息

【功能定义】

用于所有系统获取用户已登录后的session信息(nginx校验用)
接口地址:http://:/sso/getUserInfo

输入:

参数名参数类型是否必填备注
user_tokenString用户登录的token
user_idString用户id,和token一起校验
host_ipString用户的登录ip,可判断是否异常登录
target_urlString用户将要访问的资源

输出:

参数参数类型备注
codeint10000 校验成功,能够获取用户信息,
10001 校验失败,用户名或密码错误或者token过期
10002 用户服务异常
10003 未知异常
10004 字段校验错误
msgstring中文描述
(3)校验用户是否登录

【功能定义】

用于校验用户是否处于登录状态(nginx校验使用)
接口地址:http://:/sso/checkToken

输入:

参数名参数类型是否必填备注
user_tokenString用户登录的token
host_ipString用户的登录ip,可判断是否异常登录
target_urlString用户将要访问的资源

输出:

参数参数类型备注
codeint10000 校验成功,能够获取用户信息,
10001 校验失败,用户名或密码错误
10002 用户服务异常
10003 未知异常
10004 字段校验错误
msgstring中文描述
DataJSONObject结果详情 json格式 默认为null

2.商品,订单服务接口

没有特殊定义,作为普通服务正常调用接口即可。

注意的是:此次案例以 订单服务作为用户隐私的服务,需要校验登录权限

七、案例

后台所有服务在 sso_all_project下

用户服务:sso-client-user

商品服务:sso-client-product

订单服务:sso-client-user

sso服务:sso-server

nginx和lua配置在sso_nginx_lua_conf下,具体存放位置要基于openresty安装的版本做调整,这里只是列出具体所需文件

  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值