spring security5.x Oauth2 获取当前客户端授权信息
使用方法参数注解@RegisteredOAuth2AuthorizedClient,可以实现解析访问令牌
- 如果有刷新令牌的情况,会自动刷新超期的令牌
- 如果没有存在访问令牌,会自动请求访问令牌
- 授权码模式会重定向到授权服务器,并返回原始请求
- 客户端凭据模式会简单请求并保存令牌
- 如果用户通过oauth2Login认证,则client-id参数可选
源码
- OAuth2AuthorizedClient参数解析器
org.springframework.security.oauth2.client.web.method.annotation.OAuth2AuthorizedClientArgumentResolver
// 解析参数
public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) {
String clientRegistrationId = this.resolveClientRegistrationId(parameter);
if (StringUtils.isEmpty(clientRegistrationId)) {
throw new IllegalArgumentException("Unable to resolve the Client Registration Identifier. "
+ "It must be provided via @RegisteredOAuth2AuthorizedClient(\"client1\") or "
+ "@RegisteredOAuth2AuthorizedClient(registrationId = \"client1\").");
}
Authentication principal = SecurityContextHolder.getContext().getAuthentication();
if (principal == null) {
principal = ANONYMOUS_AUTHENTICATION;
}
HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse servletResponse = webRequest.getNativeResponse(HttpServletResponse.class);
// @formatter:off
OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest
.withClientRegistrationId(clientRegistrationId)
.principal(principal)
.attribute(HttpServletRequest.class.getName(), servletRequest)
.attribute(HttpServletResponse.class.getName(), servletResponse)
.build();
// 从authorizedClientManager获取授权信息
return this.authorizedClientManager.authorize(authorizeRequest);
}
// 解析客户端注册ID
private String resolveClientRegistrationId(MethodParameter parameter) {
RegisteredOAuth2AuthorizedClient authorizedClientAnnotation = AnnotatedElementUtils
.findMergedAnnotation(parameter.getParameter(), RegisteredOAuth2AuthorizedClient.class);
// 获取当前会话上下文认证信息
Authentication principal = SecurityContextHolder.getContext().getAuthentication();
// 优先使用注解中的客户端注册ID
if (!StringUtils.isEmpty(authorizedClientAnnotation.registrationId())) {
return authorizedClientAnnotation.registrationId();
}
if (!StringUtils.isEmpty(authorizedClientAnnotation.value())) {
return authorizedClientAnnotation.value();
}
// 注解没有指定ID,且当前认证信息是OAuth2认证令牌,则从令牌中获取客户端注册ID
if (principal != null && OAuth2AuthenticationToken.class.isAssignableFrom(principal.getClass())) {
return ((OAuth2AuthenticationToken) principal).getAuthorizedClientRegistrationId();
}
return null;
}
- 默认OAuth2AuthorizedClient管理器
DefaultOAuth2AuthorizedClientManager
public OAuth2AuthorizedClient authorize(OAuth2AuthorizeRequest authorizeRequest) {
Assert.notNull(authorizeRequest, "authorizeRequest cannot be null");
String clientRegistrationId = authorizeRequest.getClientRegistrationId();
OAuth2AuthorizedClient authorizedClient = authorizeRequest.getAuthorizedClient();
Authentication principal = authorizeRequest.getPrincipal();
HttpServletRequest servletRequest = getHttpServletRequestOrDefault(authorizeRequest.getAttributes());
Assert.notNull(servletRequest, "servletRequest cannot be null");
HttpServletResponse servletResponse = getHttpServletResponseOrDefault(authorizeRequest.getAttributes());
Assert.notNull(servletResponse, "servletResponse cannot be null");
OAuth2AuthorizationContext.Builder contextBuilder;
if (authorizedClient != null) {
contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient);
}
else {
authorizedClient = this.authorizedClientRepository.loadAuthorizedClient(clientRegistrationId, principal,
servletRequest);
if (authorizedClient != null) {
contextBuilder = OAuth2AuthorizationContext.withAuthorizedClient(authorizedClient);
}
else {
ClientRegistration clientRegistration = this.clientRegistrationRepository
.findByRegistrationId(clientRegistrationId);
Assert.notNull(clientRegistration,
"Could not find ClientRegistration with id '" + clientRegistrationId + "'");
contextBuilder = OAuth2AuthorizationContext.withClientRegistration(clientRegistration);
}
}
OAuth2AuthorizationContext authorizationContext = contextBuilder.principal(principal)
.attributes((attributes) -> {
Map<String, Object> contextAttributes = this.contextAttributesMapper.apply(authorizeRequest);
if (!CollectionUtils.isEmpty(contextAttributes)) {
attributes.putAll(contextAttributes);
}
})
.build();
try {
authorizedClient = this.authorizedClientProvider.authorize(authorizationContext);
}
catch (OAuth2AuthorizationException ex) {
this.authorizationFailureHandler.onAuthorizationFailure(ex, principal,
createAttributes(servletRequest, servletResponse));
throw ex;
}
if (authorizedClient != null) {
this.authorizationSuccessHandler.onAuthorizationSuccess(authorizedClient, principal,
createAttributes(servletRequest, servletResponse));
}
else {
// In the case of re-authorization, the returned `authorizedClient` may be
// null if re-authorization is not supported.
// For these cases, return the provided
// `authorizationContext.authorizedClient`.
if (authorizationContext.getAuthorizedClient() != null) {
return authorizationContext.getAuthorizedClient();
}
}
return authorizedClient;
}