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())));
}
浙公网安备 33010602011771号