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())));
}

posted on 2022-04-11 22:38  路过君  阅读(127)  评论(0)    收藏  举报

导航