版本
1.2.1
源码
- OAuth2 授权服务器配置
org.springframework.security.oauth2.server.authorization.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration
@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处理器,负责处理签名/加密/明文的jwtConfigurableJWTProcessor<SecurityContext> jwtProcessor = new DefaultJWTProcessor<>();JWSKeySelector<SecurityContext> jwsKeySelector =new JWSVerificationKeySelector<>(jwsAlgs, jwkSource);jwtProcessor.setJWSKeySelector(jwsKeySelector);// 覆盖Nimbus默认的JWT声明校验器,不对声明进行校验jwtProcessor.setJWTClaimsSetVerifier((claims, context) -> {});return new NimbusJwtDecoder(jwtProcessor);}@BeanRegisterMissingBeanPostProcessor 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
public final class OAuth2AuthorizationServerConfigurerextends 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;}...// 配置器初始化@Overridepublic void init(HttpSecurity httpSecurity) {// 获取授权服务器设置(各端点url)AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);// 校验issuerUrivalidateAuthorizationServerSettings(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)));}}// 执行安全配置@Overridepublic void configure(HttpSecurity httpSecurity) {// 应用各端点配置器this.configurers.values().forEach(configurer -> configurer.configure(httpSecurity));// 获取授权服务器设置AuthorizationServerSettings authorizationServerSettings = OAuth2ConfigurerUtils.getAuthorizationServerSettings(httpSecurity);// 添加授权服务器上下文过滤器,负责将上下文设置到AuthorizationServerContextHolderAuthorizationServerContextFilter 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;}
}