前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >spring oauth2 authorization server 配置源码解析

spring oauth2 authorization server 配置源码解析

作者头像
路过君
发布2024-01-06 10:35:47
3070
发布2024-01-06 10:35:47
举报

版本

1.2.1

源码

  • OAuth2 授权服务器配置 org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration
代码语言:javascript
复制
@Configuration(proxyBeanMethods = false)
public class OAuth2AuthorizationServerConfiguration {
	// 默认授权服务器安全过滤器链
	@Bean
	@Order(Ordered.HIGHEST_PRECEDENCE) // 最高优先级
	public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
		applyDefaultSecurity(http);
		return http.build();
	}
	// 应用默认安全配置
	public static void applyDefaultSecurity(HttpSecurity http) throws Exception {
		// 授权服务器配置器
		OAuth2AuthorizationServerConfigurer authorizationServerConfigurer =
				new OAuth2AuthorizationServerConfigurer();
		// 授权服务器端点请求匹配器
		RequestMatcher endpointsMatcher = authorizationServerConfigurer
				.getEndpointsMatcher();
		http
			// 仅对授权服务器端点请求进行安全配置
			.securityMatcher(endpointsMatcher)
			.authorizeHttpRequests(authorize ->
				authorize.anyRequest().authenticated()
			)
			// 对授权服务器端点关闭csrf保护
			.csrf(csrf -> csrf.ignoringRequestMatchers(endpointsMatcher))
			.apply(authorizationServerConfigurer);
	}
	// 默认JWT解码器
	public static JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {
		// 添加支持的算法
		Set<JWSAlgorithm> jwsAlgs = new HashSet<>();
		jwsAlgs.addAll(JWSAlgorithm.Family.RSA);
		jwsAlgs.addAll(JWSAlgorithm.Family.EC);
		jwsAlgs.addAll(JWSAlgorithm.Family.HMAC_SHA);
		// JWT处理器,负责处理签名/加密/明文的jwt
		ConfigurableJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();
		JWSKeySelector<SecurityContext> jwsKeySelector =
				new JWSVerificationKeySelector<>(jwsAlgs, jwkSource);
		jwtProcessor.setJWSKeySelector(jwsKeySelector);
		// 覆盖Nimbus默认的JWT声明校验器,不对声明进行校验
		jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {
		});
		return new NimbusJwtDecoder(jwtProcessor);
	}
	@Bean
	RegisterMissingBeanPostProcessor registerMissingBeanPostProcessor() {
		RegisterMissingBeanPostProcessor postProcessor = new RegisterMissingBeanPostProcessor();
		postProcessor.addBeanDefinition(AuthorizationServerSettings.class, () -> AuthorizationServerSettings.builder().build());
		return postProcessor;
	}
}
  • OAuth2 授权服务器配置器 org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer
代码语言:javascript
复制
public final class OAuth2AuthorizationServerConfigurer
		extends AbstractHttpConfigurer<OAuth2AuthorizationServerConfigurer, HttpSecurity> {
	// 所有授权服务器端点配置器
	private final Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> configurers = createConfigurers();
	// 匹配所有授权服务器端点对应的请求,以及JwkSet端点请求
	private RequestMatcher endpointsMatcher;
	
	...
	
	// 启用OpenID Connect 1.0支持(默认关闭)
	public OAuth2AuthorizationServerConfigurer oidc(Customizer<OidcConfigurer> oidcCustomizer) {
		OidcConfigurer oidcConfigurer = getConfigurer(OidcConfigurer.class);
		if (oidcConfigurer == null) {
			addConfigurer(OidcConfigurer.class, new OidcConfigurer(this::postProcess));
			oidcConfigurer = getConfigurer(OidcConfigurer.class);
		}
		oidcCustomizer.customize(oidcConfigurer);
		return this;
	}
	
	...
	// 配置器初始化
	@Override
	public void init(HttpSecurity httpSecurity) {
		// 获取授权服务器设置(各端点url)
		AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
		// 校验issuerUri
		validateAuthorizationServerSettings(authorizationServerSettings);
		// 处理OpenID Connect认证请求
		if (isOidcEnabled()) {
			// 如果启用OpenID Connect 1.0
			// 添加 OpenID Connect 会话跟踪能力
			initSessionRegistry(httpSecurity);
			SessionRegistry sessionRegistry = httpSecurity.getSharedObject(SessionRegistry.class);
			// 授权端点设置会话认证策略
			OAuth2AuthorizationEndpointConfigurer authorizationEndpointConfigurer =
					getConfigurer(OAuth2AuthorizationEndpointConfigurer.class);
			authorizationEndpointConfigurer.setSessionAuthenticationStrategy((authentication, request, response) -> {
				// 如果认证请求是使用授权码模式的OAuth2认证请求,且scope包含openid,则将会话注册到会话注册表
				if (authentication instanceof OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication) {
					if (authorizationCodeRequestAuthentication.getScopes().contains(OidcScopes.OPENID)) {
						if (sessionRegistry.getSessionInformation(request.getSession().getId()) == null) {
							sessionRegistry.registerNewSession(
									request.getSession().getId(),
									((Authentication) authorizationCodeRequestAuthentication.getPrincipal()).getPrincipal());
						}
					}
				}
			});
		} else {
			// 如果OpenID Connect 没有启用.
			// 添加认证校验器,拒绝scope包含openid的认证请求
			OAuth2AuthorizationEndpointConfigurer authorizationEndpointConfigurer =
					getConfigurer(OAuth2AuthorizationEndpointConfigurer.class);
			authorizationEndpointConfigurer.addAuthorizationCodeRequestAuthenticationValidator((authenticationContext) -> {
				OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthentication =
						authenticationContext.getAuthentication();
				if (authorizationCodeRequestAuthentication.getScopes().contains(OidcScopes.OPENID)) {
					OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.INVALID_SCOPE,
							"OpenID Connect 1.0 authentication requests are restricted.",
							"https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1");
					throw new OAuth2AuthorizationCodeRequestAuthenticationException(
							error, authorizationCodeRequestAuthentication);
				}
			});
		}
		// 构造授权端点请求匹配器
		List<RequestMatcher> requestMatchers = new ArrayList<>();
		// 添加每个端点对应的匹配规则
		this.configurers.values().forEach(configurer -> {
			configurer.init(httpSecurity);
			requestMatchers.add(configurer.getRequestMatcher());
		});
		// 添加JwkSet端点请求匹配规则
		requestMatchers.add(new AntPathRequestMatcher(
				authorizationServerSettings.getJwkSetEndpoint(), HttpMethod.GET.name()));
		this.endpointsMatcher = new OrRequestMatcher(requestMatchers);
		// 当令牌获取/内省/撤回/设备认证端点发生访问拒绝异常或者认证异常时返回401未授权响应
		ExceptionHandlingConfigurer<HttpSecurity> exceptionHandling = httpSecurity.getConfigurer(ExceptionHandlingConfigurer.class);
		if (exceptionHandling != null) {
			exceptionHandling.defaultAuthenticationEntryPointFor(
					new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
					new OrRequestMatcher(
							getRequestMatcher(OAuth2TokenEndpointConfigurer.class),
							getRequestMatcher(OAuth2TokenIntrospectionEndpointConfigurer.class),
							getRequestMatcher(OAuth2TokenRevocationEndpointConfigurer.class),
							getRequestMatcher(OAuth2DeviceAuthorizationEndpointConfigurer.class))
			);
		}
	}
	// 执行安全配置
	@Override
	public void configure(HttpSecurity httpSecurity) {
		// 应用各端点配置器
		this.configurers.values().forEach(configurer -> configurer.configure(httpSecurity));
		// 获取授权服务器设置
		AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);
		// 添加授权服务器上下文过滤器,负责将上下文设置到AuthorizationServerContextHolder
		AuthorizationServerContextFilter authorizationServerContextFilter = new AuthorizationServerContextFilter(authorizationServerSettings);
		httpSecurity.addFilterAfter(postProcess(authorizationServerContextFilter), SecurityContextHolderFilter.class);
		// 添加JwkSet端点过滤器
		JWKSource<com.nimbusds.jose.proc.SecurityContext> jwkSource = OAuth2ConfigurerUtils.getJwkSource(httpSecurity);
		if (jwkSource != null) {
			NimbusJwkSetEndpointFilter jwkSetEndpointFilter = new NimbusJwkSetEndpointFilter(
					jwkSource, authorizationServerSettings.getJwkSetEndpoint());
			httpSecurity.addFilterBefore(postProcess(jwkSetEndpointFilter), AbstractPreAuthenticatedProcessingFilter.class);
		}
	}
	// 创建OAuth2服务器端点配置器
	private Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> createConfigurers() {
		Map<Class<? extends AbstractOAuth2Configurer>, AbstractOAuth2Configurer> configurers = new LinkedHashMap<>();
		// 客户端认证
		configurers.put(OAuth2ClientAuthenticationConfigurer.class, new OAuth2ClientAuthenticationConfigurer(this::postProcess));
		// 授权服务器元数据端点
		configurers.put(OAuth2AuthorizationServerMetadataEndpointConfigurer.class, new OAuth2AuthorizationServerMetadataEndpointConfigurer(this::postProcess));
		// 授权端点
		configurers.put(OAuth2AuthorizationEndpointConfigurer.class, new OAuth2AuthorizationEndpointConfigurer(this::postProcess));
		// 令牌获取端点
		configurers.put(OAuth2TokenEndpointConfigurer.class, new OAuth2TokenEndpointConfigurer(this::postProcess));
		// 令牌内省端点
		configurers.put(OAuth2TokenIntrospectionEndpointConfigurer.class, new OAuth2TokenIntrospectionEndpointConfigurer(this::postProcess));
		// 令牌撤回端点
		configurers.put(OAuth2TokenRevocationEndpointConfigurer.class, new OAuth2TokenRevocationEndpointConfigurer(this::postProcess));
		// 设备授权端点
		configurers.put(OAuth2DeviceAuthorizationEndpointConfigurer.class, new OAuth2DeviceAuthorizationEndpointConfigurer(this::postProcess));
		// 设备校验端点
		configurers.put(OAuth2DeviceVerificationEndpointConfigurer.class, new OAuth2DeviceVerificationEndpointConfigurer(this::postProcess));
		return configurers;
	}
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-01-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 版本
  • 源码
相关产品与服务
主机安全
主机安全(Cloud Workload Protection,CWP)基于腾讯安全积累的海量威胁数据,利用机器学习为用户提供资产管理、木马文件查杀、黑客入侵防御、漏洞风险预警及安全基线等安全防护服务,帮助企业构建服务器安全防护体系。现支持用户非腾讯云服务器统一进行安全防护,轻松共享腾讯云端安全情报,让私有数据中心拥有云上同等级别的安全体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档