spring security oauth2.x迁移到spring security5.x 资源服务器启用url参数传递token
现象
opaque token模式使用url参数access_token传递token访问资源服务器时报错401未授权
原因
spring security 5.x默认的bear token解析器没有启用从请求参数中获取token
解决
在资源服务器安全配置中自行配置bearerTokenResolver,启用从请求参数中获取token
protected void configure(HttpSecurity http) throws Exception {
DefaultBearerTokenResolver bearerTokenResolver = new DefaultBearerTokenResolver();
bearerTokenResolver.setAllowUriQueryParameter(true);
bearerTokenResolver.setAllowFormEncodedBodyParameter(true);
http.oauth2ResourceServer()
.bearerTokenResolver(bearerTokenResolver)
.opaqueToken(Customizer.withDefaults())
}
源码
- 资源服务器配置器
org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer
// 安全配置
@Override
public void configure(H http) {
// 配置token解析器
BearerTokenResolver bearerTokenResolver = getBearerTokenResolver();
this.requestMatcher.setBearerTokenResolver(bearerTokenResolver);
...
}
// 解析器配置接口
public OAuth2ResourceServerConfigurer<H> bearerTokenResolver(BearerTokenResolver bearerTokenResolver) {
Assert.notNull(bearerTokenResolver, "bearerTokenResolver cannot be null");
this.bearerTokenResolver = bearerTokenResolver;
return this;
}
// 获取解析器
BearerTokenResolver getBearerTokenResolver() {
if (this.bearerTokenResolver == null) {
// 如果没有通过接口配置解析器则从上下文中获取解析器bean
if (this.context.getBeanNamesForType(BearerTokenResolver.class).length > 0) {
this.bearerTokenResolver = this.context.getBean(BearerTokenResolver.class);
}
else { // 如果上下文没有注册解析器bean,则创建默认解析器
this.bearerTokenResolver = new DefaultBearerTokenResolver();
}
}
return this.bearerTokenResolver;
}
- 默认token解析器
org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver
// 默认关闭表单参数(用于POST请求)
private boolean allowFormEncodedBodyParameter = false;
// 默认关闭url参数(用于GET请求)
private boolean allowUriQueryParameter = false;
// 解析请求中的token
public String resolve(HttpServletRequest request) {
// 解析header
String authorizationHeaderToken = resolveFromAuthorizationHeader(request);
// 解析请求参数
String parameterToken = resolveFromRequestParameters(request);
if (authorizationHeaderToken != null) {
if (parameterToken != null) {
BearerTokenError error = BearerTokenErrors
.invalidRequest("Found multiple bearer tokens in the request");
throw new OAuth2AuthenticationException(error);
}
return authorizationHeaderToken;
}
if (parameterToken != null && isParameterTokenSupportedForRequest(request)) {
return parameterToken;
}
return null;
}
// 判断是否允许从表单/url参数中传递token
private boolean isParameterTokenSupportedForRequest(HttpServletRequest request) {
return ((this.allowFormEncodedBodyParameter && "POST".equals(request.getMethod()))
|| (this.allowUriQueryParameter && "GET".equals(request.getMethod())));
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2020-04-11 spring 启动时自动运行
2020-04-11 spring cloud oauth2授权服务 默认tokenService配置源码
2020-04-11 spring cloud 搭建oauth2授权服务 使用redis存储令牌
2020-04-11 spring cloud oauth2授权服务 clientDetails配置源码
2020-04-11 spring 验证框架
2020-04-11 IDEA 插件整理
2020-04-11 spring security笔记 默认登陆页面源码