spring security5.x Oauth2 获取当前客户端授权信息

2021-12-07 16:09:30 浏览数 (1)

使用方法参数注解@RegisteredOAuth2AuthorizedClient,可以实现解析访问令牌

  • 如果有刷新令牌的情况,会自动刷新超期的令牌
  • 如果没有存在访问令牌,会自动请求访问令牌
  • 授权码模式会重定向到授权服务器,并返回原始请求
  • 客户端凭据模式会简单请求并保存令牌
  • 如果用户通过oauth2Login认证,则client-id参数可选

源码

  • OAuth2AuthorizedClient参数解析器 org.springframework.security.oauth2.client.web.method.annotation.OAuth2AuthorizedClientArgumentResolver
代码语言:javascript复制
// 解析参数
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
代码语言:javascript复制
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;
}

0 人点赞