上一篇我们已经搭建了一个简单的前后端不分离的认证框架

但是在集成过程中,出现了一些问题

1.跨域Cookie

2.重定向页面无法定位到网关

3.想要进行一些后置加工处理操作

4.不想要每次验证都需要请求远端身份提供商

常见的解决方案是自定义一个资源服务器,然后让后端请求这个自定义的资源服务器

或者是修改Spring Security框架,增加后置流程,

上述两个解决方案都并不简单,但是迫于一些时间压力,在我尝试集成OIDC的时候,我选择了第二种解决方案

即修改Spring Security框架的流程,将相关认证化为自己的流程框架

首先我们明确了Spring Security的书写流程

首先在Spring Security框架中

提供了不同的EndPoint供我们自己去自定义一些实现

比如说,我在内网进行集成SSO,访问所有的接口都需要proxy

那么我们就可以

.tokenEndpoint()

.accessTokenResponseClient(responseClient)

自定义一个responseClient

图片

传入一个RestTemplate

方便自定义网络交互

那么我们自定义的第一步,就是先书写一个存放Token的地方,方便存入Token

由于OIDC 的 OAuth2AccessToken 和 Spring Security传统的 OAuth2AccessToken 数据类型不一致,故考虑自定义实现一个TokenStore

由于用户权限较多,故考虑使用Redis,实现自定义的TokenStore

那么这一步,具体代码由于不能脱敏,故不贴上,但是还是围绕原本的RedisTokenStore进行书写

图片

实现对应的从Token -> ReFresh_Token

Token -> Auth

ReFresh -> Token 等互转及存储接口即可

实现完成之后,我们在Spring Security框架中暴露的authizedClientRepository注入自定义的clientRepository

clientRepository 包含了实现的mySelfTokenStore

然后在clientRepository中实现了saveAuthorizedClient

将传入的Authtication 自定义加工一下,带着对应的token,存入tokenStore

这样,就存储完成了Token到Redis中

之后就可以返回给页面了

由于默认返回,是直接返回当前服务约定的一个uri

也就是说,我的服务在8081端口上,我约定返回/token,那么其返回的就是

localhost:8081/token

而我的gateway部署在88端口上,这样直接交给框架是不现实的

故考虑利用login成功后,框架提供的successHandler()来进行处理

其中我们可以从ThreadLocal中取出Token

从request中获取x-forwarded-host这个header

利用respon的sendRedirect来重定向到localhost:88/token?token=xxxxxx

方便前端获取到token并存储

接下来我们就需要考虑用户使用过程中的整体流程

首先是一个Filter,用于校验用户是否登录,并将用户的相关信息,存入SecurityContextHolder

之后在接口上利用@PreAuthorize进行权限校验,对于如何实现@PreAuthorize中的权限校验,可以参考如下的文章

https://blog.csdn.net/weixin_47345400/article/details/108666451

之后别忘了在SpringSecurityConfig中声明全部接口的permit()

完成这个操作之后,就已经完成了用户使用过程中的token交互

之后就是Token自身的声明周期

涉及的接口有checkToken / freshToken / logout

1.checkToken相对简单

只需要根据token是否存在,返回boolean信息

2.logout

则是分别删除accessToken / authentication / refreshToken信息

3.freshToken则需要网络交互

根据传入的token,利用上一章说的access_token接口,尝试获取新的接口

然后再一次请求user_info,获取到用户信息

并删除redis相关信息

再次存入,返回前端新的token

这样就基本完成这一次的书写

整体流程总结如下图

图片

发表评论

邮箱地址不会被公开。 必填项已用*标注