SAS认证过程解析
1.OAuth2/SAS
先简单了解一下OAuth2的授权体系(以项目的用户密码模式为例)
+-----------------+ +---------------------+ +-----------------+
| | | | | |
| 客户端应用 | | 授权服务器 (SAS) | | 资源服务器 |
| (Web/移动端) | | | | (API/服务) |
+--------+--------+ +----------+----------+ +--------+--------+
| | |
| 1. 用户输入用户名和密码 | |
|---------------------------->| |
| | |
| | 2. 验证用户名和密码 |
| |---------------------------->|
| | |
| | 3. 颁发 Access Token (+Refresh Token) |
| |<----------------------------|
| 4. 客户端收到 Access Token | |
|<----------------------------| |
| | |
| 5. 使用 Access Token 请求资源 | |
|---------------------------->| |
| | 6. 验证 Access Token |
| |---------------------------->|
| | |
| | 7. 返回受保护资源数据 |
|<----------------------------| |
2.主流程(示例流程)

在网上示例的主流程中,表述并不清晰,我们不知道这些模块属于谁,也不知道OAuth2的标准体系应该有什么,哪些是自己包含的,哪些又是需要自己写的
3.代码结合
需要弄清楚到底需要写什么,哪些是Spring Authentication Server自带的需要实现和配置的
其实真正的调用主流程都在AuthorizationServerConfiguration里面
方法执行顺序解析
过滤器
http.securityMatcher("/oauth2/**")
表示只有匹配
/oauth2/**的请求才进入这个 FilterChain。
其他路径走别的安全配置。
http.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
这里手动往 Spring Security 的过滤器链中插入一个
ValidateCodeFilter(验证码验证过滤器)。
它是继承OncePerRequestFilter的自定义过滤器。
它的位置在UsernamePasswordAuthenticationFilter之前
ValidateCodeFilter
↓
PasswordDecoderFilter
↓
UsernamePasswordAuthenticationFilter
↓
OAuth2TokenEndpointFilter(SAS自带)
其中大概的流程
用户请求 /oauth2/token
↓
进入 SecurityFilterChain(authorizationServer)
↓
执行 ValidateCodeFilter (验证码)
↓
执行 PasswordDecoderFilter (解密密码)
↓
进入 OAuth2TokenEndpointFilter (OncePerRequestFilter)
↓
由 accessTokenRequestConverter 识别模式(如 password)
↓
调用 OAuth2ResourceOwnerPasswordAuthenticationProvider
↓
认证成功 → DmsAuthenticationSuccessEventHandler
认证失败 → DmsAuthenticationFailureEventHandler
↓
生成 Token (通过 CustomOAuth2AccessTokenGenerator)
↓
返回 access_token 响应
重点:自定义 Converter 和 Provider
OAuth2TokenEndpointFilter作为SAS框架的接口控制器,那么它的下一步会做什么呢
我们需要控制它,所以为他配置转换器
http.with(authorizationServerConfigurer.tokenEndpoint((tokenEndpoint) -> {
// 个性化认证授权端点
tokenEndpoint.accessTokenRequestConverter(accessTokenRequestConverter())
// 注入自定义的授权认证Converter
.accessTokenResponseHandler(new DmsAuthenticationSuccessEventHandler())
// 登录成功处理器
.errorResponseHandler(new DmsAuthenticationFailureEventHandler());
// 登录失败处理器
})
accessTokenRequestConverter是什么呢?它是自定义处理链的集合
如果不做自定义配置,他就无法支持诸如微信登录,短信登录
@Bean
public AuthenticationConverter accessTokenRequestConverter() {
return new DelegatingAuthenticationConverter(Arrays.asList(
new OAuth2ResourceOwnerPasswordAuthenticationConverter(),
new OAuth2RefreshTokenAuthenticationConverter(),
new OAuth2ClientCredentialsAuthenticationConverter()));
}
OAuth2ResourceOwnerPasswordAuthenticationConverter 即是我们的最普通的登录的密码模式的请求转换器
在SAS标准流程中,自己的Token对象 + Convert + Provider即可配置新的认证方式
// 注入自定义授权模式实现
addCustomOAuth2GrantAuthenticationProvider(http);
什么是Convert ?Provider又是什么?
在SAS流程中,Authentication对象是他们传递的对象主体,一般我们自己的token对象需要实现这个接口
当上方过滤器完成后的请求形成了request之后

当然在流程的provider之中,密码模式还需要实现一个DAOprovider,因为需要查库校验密码,还不能直接生成token,也就是项目中的DmsDaoAuthenticationProvider
它封装了 用户名/密码认证的公共流程:
- 调用
retrieveUser()获取用户信息 - 调用
additionalAuthenticationChecks()校验密码
3.项目设计
在认证流程中,auth模块是负主要职责的,所以大部分实现可以完全由auth掌管,但是我们既然希望token可以被管理,那么其中的AuthenticationService就可以被复用操作token,所以可以抽到公共类中。

1.首先是配置类,其中注入了所有我们定义的类,包括过滤器,指定的convert,使用的provider。
2.如果拓展短信和微信登录,直接参考password
3.DmsDaoAuthenticationProvider被谁调用?被我们password的provider调用,实现密码校验; 为什么不自己实现密码校验逻辑,因为职责分离,调用manager的认证,它能够帮我们自动调用合适的provider去校验
4.CustomOAuth2AccessTokenGenerator是为了自定义令牌的生成逻辑,它并非是access-token的生成逻辑,而是客户端可用的 token 字符串 + 对应权限上下文信息
5.token的增删改查放在哪?准备放在公共类中,因为admin需要维护,DmsRedisOAuth2AuthorizationService