token的传递方式分为参数传递和请求头(header)中传递两种
客户端发送请求(带有token),后台GateWay担任Security_OAuth2的资源服务器,对请求进行拦截,如下
springSecurityFilterChain 是springSecurity的filter
@Bean
SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
//认证处理器
ReactiveAuthenticationManager customAuthenticationManager = new CustomAuthenticationManager(tokenStore);
JsonAuthenticationEntryPoint entryPoint = new JsonAuthenticationEntryPoint();
//token转换器
todo token的可能在参数accessToken中,也可能在head的Authorization#bearer中
ServerBearerTokenAuthenticationConverter tokenAuthenticationConverter = new ServerBearerTokenAuthenticationConverter();
tokenAuthenticationConverter.setAllowUriQueryParameter(true);
//oauth2认证过滤器
AuthenticationWebFilter oauth2Filter = new AuthenticationWebFilter(customAuthenticationManager);
oauth2Filter.setServerAuthenticationConverter(tokenAuthenticationConverter);
...
#8行 调用了token转化器,这个converter就是处理不同方式传递来的token,进行解析
ServerBearerTokenAuthenticationConverter
private String token(ServerHttpRequest request) {
String authorizationHeaderToken = resolveFromAuthorizationHeader(request.getHeaders());
String parameterToken = (String)request.getQueryParams().getFirst("access_token");
if (authorizationHeaderToken != null) {
if (parameterToken != null) {
BearerTokenError error = BearerTokenErrors.invalidRequest("Found multiple bearer tokens in the request");
throw new OAuth2AuthenticationException(error);
} else {
return authorizationHeaderToken;
}
} else {
return parameterToken != null && this.isParameterTokenSupportedForRequest(request) ? parameterToken : null;
}
}
#3行 从参数中获取access_token,进行判断(在第12行)
#2行 是调用方法从Header里解析Authorizatio#bearer属性
resolveFromAuthorizationHeader
private static String resolveFromAuthorizationHeader(HttpHeaders headers) {
String authorization = headers.getFirst("Authorization");
if (StringUtils.startsWithIgnoreCase(authorization, "bearer")) {
Matcher matcher = authorizationPattern.matcher(authorization);
if (!matcher.matches()) {
BearerTokenError error = invalidTokenError();
throw new OAuth2AuthenticationException(error);
} else {
return matcher.group("token");
}
} else {
return null;
}
}
#3行 startsWithIgnoreCase忽略大小写,我们有时候在请求里写的就是BEARER,也是能识别的