公司内部系统单点登录求求大佬给个方案

2022-02-23 11:02:47 +08:00
 DimitriYoon

公司想把以前的项目集中起来 我用 SpringCloud alibaba 搭了一个架子,用 gateway 做的网关,Spring Security Oauth2 做一个认证模块。 现在想要在后续的开发中把其他系统也集成到这个微服务中,然后统一从认证模块登录,登录完成之后其他模块不再需要登录。

但是目前是前后端分离的模式,前端是用 nginx 跑的,如何实现我现在毫无头绪,球球大佬们解答惹!

5535 次点击
所在节点    Java
37 条回复
THESDZ
2022-02-23 11:34:00 +08:00
说个我认为最简单的

认证单独部署一个服务,账号 /用户单独一个服务。

认证服务提供 token

网关拦截和解析 token ( jwt 或者对接认证服务)获取用户唯一标识,把用户唯一标识塞在请求头里面,传给后续请求

各个应用直接写个注解 aop ,有需要就 @注解后,把用户信息塞到某个参数的对象实例里面
DimitriYoon
2022-02-23 11:44:05 +08:00
@THESDZ 不打算用 JWT ,我用的 redis 管理令牌,这样方便注销令牌,但是目前我不知道前端该如何校验用户是否登录过...而且后端和前端端口不一致
gadfly3173
2022-02-23 11:47:00 +08:00
大厂比如阿里云之类的,都是直接用 cookie-session 解决的,把 session 存 redis 就行。再搞自己的 token 之类的也只是重新实现一遍 cookie-session 干的事

gadfly3173
2022-02-23 11:50:00 +08:00
@DimitriYoon #2 你完全不需要考虑前端,最多只需要考虑个 cookie 的 domain 的设置。后端每个接口都会经过认证服务,没通过的就返回个 401 ,前端只要检测到 401 就弹到登录页就好了
brader
2022-02-23 11:54:51 +08:00
你原有的认证方式无非就是 token 模式,或者 session 模式,你把 token 或 sessionid 搬到 redis 上去,这样就是分布式的。
然后每个项目都去 redis 拿这个 token 共用,这样就全部都能认证登录了。

登录认证检查你也可以统一写在用户中心,然后有用户中心统一提供接口。

喜欢哪种模式就看你了。
DimitriYoon
2022-02-23 11:58:13 +08:00
@gadfly3173 您的意思是不需要用 token ?直接用 session ?
DimitriYoon
2022-02-23 12:02:50 +08:00
@brader 前端的话是 nginx 部署的多个站点,比如 a 模块前端的地址是 xxx.xxx.xxx.xxx:10000 ,然后 b 模块前端地址是 xxx.xxx.xxx.xxx:10001 ,那么如果我通过登录的前端地址 xxx.xxx.xxx.xxx:9999 登录了之后,10000 如何得知 9999 给的 token
gadfly3173
2022-02-23 12:12:01 +08:00
@DimitriYoon #7 cookie 不区分端口,也可以一定程度上的跨域(通过设置 domain ),所以我才推荐用 cookie 解决单点登录。如果你的 token 是前端存在 localstorage 里的话就做不到跨域单点登录了
Herry001
2022-02-23 12:13:18 +08:00
参考下 Oauth2.0?
gadfly3173
2022-02-23 12:15:31 +08:00
@Herry001 #9 Oauth2 的话还能算单点么。。?每个域名都得点一次授权登录
DimitriYoon
2022-02-23 12:16:55 +08:00
@gadfly3173 如果使用 cookie 的话,是否可以抛弃 oauth2 ,单纯用 security 做?
aofall
2022-02-23 12:28:01 +08:00
Jwt 只是令牌签发验证的一种方式而已,如果签发时不指定过期时间,签发出来的令牌存在 Redis 用于管理过期时间,和 Cookie-Session 的作用就一样了。

区别就是 Redis 管理令牌,在没有限制、数据库分区一致的情况下多个系统都是可以从 Redis 中读到这个登录令牌的,只要保证密钥一致就相当于变相的实现一个简单的单点登录(当然这样可能会有令牌管理混乱的问题,可以根据系统规模考虑一下是否要这么做)
DimitriYoon
2022-02-23 12:45:36 +08:00
@aofall 多个前端站点如何获取认证模块下发令牌呢...?
frank1256
2022-02-23 13:20:46 +08:00
基于 SpringSecurity 的 Oauth2.0 ,使用授权码模式。
有几个角色,如下
1 、授权中心,用于发放 token ,对应的注解是 @EnableAuthorizationServer
2 、用户微服务,提供用户信息和权限的 crud ,是一个资源服务器,对应 @EnableResourceServer

授权流程:
前端以 vue 为例,在登陆之前检查本地是否有 token ,没有的话使用授权码模式,跳转到授权中心的统一登录界面,授权码模式回返回到前端并且带上授权码,前端拿到授权码调用授权中心获取 token 的接口。拿到 token ,之后调用用户微服务获取用户信息和权限,渲染前端。

无需重复登录:
多个前端,跳转的都是授权中心的同一个登录界面,也就是同一个 session ,在浏览器不关闭的情况下,一个前端跳转后完成登录,第二个前端再次跳转到这里,不需要再登录。会根据后端配置,是否需要授权。如果需要授权,需要点击一次,可以配置不需要授权配置 autoapprove 字段。那么第二个前端在用户体验上,只是单纯的跳转两次后,一样会带着授权码回到第二个前端,和第一个前端一样,调用 api 获取 token 。达到不需要重复登录的目的。在 oauth_client_details 的表设计里有 autoapprove 字段,就是用于自动授权。

oauth2.0 是分应用的,不同应用的 token 是不一样的
DimitriYoon
2022-02-23 13:41:34 +08:00
@frank1256 内部系统不需要用到授权码模式呢,我只用了 password 和 refresh_token
frank1256
2022-02-23 13:45:03 +08:00
@DimitriYoon 为什么不用授权码模式呢,用 password 的,还需要有自己的登录界面,每个系统难道都要自己做一套登录界面吗,授权码模式就是为了统一登录的。password 没有什么好的方法,只能自己造轮子。refresh_token 是过期去替换的。
Casbin
2022-02-23 13:47:21 +08:00
@DimitriYoon 可以看下开源单点登录系统 Casdoor ,作为统一的认证+用户中心: https://v2ex.com/t/803669
9c04C5dO01Sw5DNL
2022-02-23 13:49:58 +08:00
oauth2 不是给三方授权的吗?一方系统用不着啊
DimitriYoon
2022-02-23 13:50:33 +08:00
@frank1256 我考虑了一下,可能还是用 redis 共享 session 的方法靠谱一点,毕竟这套系统不需要对接外部,而且用 oauth2 的话,各个系统还得额外点一下授权
9c04C5dO01Sw5DNL
2022-02-23 13:53:35 +08:00
另外 redis+token 就是 session 方案,不管你的 token 是 jwt 还是其他 token 。

jwt 所谓的无状态,是指自包含状态,每次请求时携带状态。

如果状态下沉到持久 /缓存层,jwt 所谓的无状态并没什么太大的优势。


强烈建议各位看下 redis 官方博客这篇文章: https://redis.com/blog/json-web-tokens-jwt-are-dangerous-for-user-sessions/

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/835870

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX