当前位置:首页 > 编程笔记 > 正文
已解决

Spring Security—OAuth2 客户端认证和授权

来自网友在路上 157857提问 提问时间:2023-10-24 09:59:49阅读次数: 57

最佳答案 问答题库578位专家为你答疑解惑

一、认证—JWT Bearer

关于 JWT Bearer 客户端认证的进一步详情,请参考OAuth 2.0客户端认证和授权许可的 JSON Web Token (JWT)简介。

JWT Bearer 客户端认证的默认实现是 NimbusJwtClientAuthenticationParametersConverter,它是一个 Converter,通过在 client_assertion 参数中添加签名的JSON Web Token(JWS)来定制令牌请求参数。

用于签署 JWS 的 java.security.PrivateKey 或 javax.crypto.SecretKey 由与 NimbusJwtClientAuthenticationParametersConverter 相关的 com.nimbusds.jose.jwk.JWK 解析器提供。

1、使用private_key_jwt进行认证

给出以下Spring Boot 2.x属性,用于OAuth 2.0客户端注册。

spring:security:oauth2:client:registration:okta:client-id: okta-client-idclient-authentication-method: private_key_jwtauthorization-grant-type: authorization_code...

下面的例子显示了如何配置 DefaultAuthorizationCodeTokenResponseClient。

  • Java
Function<ClientRegistration, JWK> jwkResolver = (clientRegistration) -> {if (clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.PRIVATE_KEY_JWT)) {// Assuming RSA key typeRSAPublicKey publicKey = ...RSAPrivateKey privateKey = ...return new RSAKey.Builder(publicKey).privateKey(privateKey).keyID(UUID.randomUUID().toString()).build();}return null;
};OAuth2AuthorizationCodeGrantRequestEntityConverter requestEntityConverter =new OAuth2AuthorizationCodeGrantRequestEntityConverter();
requestEntityConverter.addParametersConverter(new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver));DefaultAuthorizationCodeTokenResponseClient tokenResponseClient =new DefaultAuthorizationCodeTokenResponseClient();
tokenResponseClient.setRequestEntityConverter(requestEntityConverter);

2、使用 client_secret_jwt 进行认证

给出以下Spring Boot 2.x属性,用于OAuth 2.0客户端注册。

spring:security:oauth2:client:registration:okta:client-id: okta-client-idclient-secret: okta-client-secretclient-authentication-method: client_secret_jwtauthorization-grant-type: client_credentials...

下面的例子显示了如何配置 DefaultClientCredentialsTokenResponseClient。

  • Java
Function<ClientRegistration, JWK> jwkResolver = (clientRegistration) -> {if (clientRegistration.getClientAuthenticationMethod().equals(ClientAuthenticationMethod.CLIENT_SECRET_JWT)) {SecretKeySpec secretKey = new SecretKeySpec(clientRegistration.getClientSecret().getBytes(StandardCharsets.UTF_8),"HmacSHA256");return new OctetSequenceKey.Builder(secretKey).keyID(UUID.randomUUID().toString()).build();}return null;
};OAuth2ClientCredentialsGrantRequestEntityConverter requestEntityConverter =new OAuth2ClientCredentialsGrantRequestEntityConverter();
requestEntityConverter.addParametersConverter(new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver));DefaultClientCredentialsTokenResponseClient tokenResponseClient =new DefaultClientCredentialsTokenResponseClient();
tokenResponseClient.setRequestEntityConverter(requestEntityConverter);

3、自定义JWT断言(JWT assertion)

NimbusJwtClientAuthenticationParametersConverter 产生的JWT默认包含 iss、sub、aud、jti、iat 和 exp 等 claim。你可以通过提供一个 Consumer<NimbusJwtClientAuthenticationParametersConverter.JwtClientAuthenticationContext<T>> 给 `setJwtClientAssertionCustomizer()`来定制头信息和/或claim。下面的例子显示了如何定制JWT的 claim。

  • Java
Function<ClientRegistration, JWK> jwkResolver = ...NimbusJwtClientAuthenticationParametersConverter<OAuth2ClientCredentialsGrantRequest> converter =new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver);
converter.setJwtClientAssertionCustomizer((context) -> {context.getHeaders().header("custom-header", "header-value");context.getClaims().claim("custom-claim", "claim-value");
});

二、授权—解析授权客户端

@RegisteredOAuth2AuthorizedClient 注解提供了将方法参数解析为 OAuth2AuthorizedClient 类型的参数值的能力。与使用 OAuth2AuthorizedClientManager 或 OAuth2AuthorizedClientService 来访问 OAuth2AuthorizedClient 相比,这是一个方便的选择。下面的例子展示了如何使用 @RegisteredOAuth2AuthorizedClient。

  • Java
@Controller
public class OAuth2ClientController {@GetMapping("/")public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {OAuth2AccessToken accessToken = authorizedClient.getAccessToken();...return "index";}
}

@RegisteredOAuth2AuthorizedClient 注解由 OAuth2AuthorizedClientArgumentResolver 处理,它直接使用 OAuth2AuthorizedClientManager,因此继承其能力。

1、为Servlet环境整合WebClient

OAuth 2.0客户端支持通过使用 ExchangeFilterFunction 与 WebClient 整合。

ServletOAuth2AuthorizedClientExchangeFilterFunction 提供了一种机制,通过使用 OAuth2AuthorizedClient 并包括相关的 OAuth2AccessToken 作为承载令牌来请求受保护的资源。它直接使用 OAuth2AuthorizedClientManager,因此,它继承了以下功能。

  • 如果客户还没有得到授权,就会请求一个 OAuth2AccessToken。
    • authorization_code: 触发 Authorization 请求重定向,启动流程。
    • client_credentials: 访问令牌是直接从令牌端点获得的。
    • password: 访问令牌是直接从令牌端点获得的。
  • 如果 OAuth2AccessToken 已经过期,如果有 OAuth2AuthorizedClientProvider 可以执行授权,它将被刷新(或更新)。

下面的代码显示了一个如何配置支持OAuth 2.0客户端的 WebClient 的例子。

  • Java
@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);return WebClient.builder().apply(oauth2Client.oauth2Configuration()).build();
}

2、提供授权客户端

ServletOAuth2AuthorizedClientExchangeFilterFunction 通过从 ClientRequest.attributes()(请求属性)中解析 OAuth2AuthorizedClient,来确定(对一个请求)要使用的客户端。

下面的代码显示了如何设置一个 OAuth2AuthorizedClient 作为请求属性。

  • Java
@GetMapping("/")
public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {String resourceUri = ...String body = webClient.get().uri(resourceUri).attributes(oauth2AuthorizedClient(authorizedClient))   .retrieve().bodyToMono(String.class).block();...return "index";
}

oauth2AuthorizedClient() is a static method in ServletOAuth2AuthorizedClientExchangeFilterFunction.

下面的代码显示了如何设置 ClientRegistration.getRegistrationId() 作为请求属性。

  • Java
@GetMapping("/")
public String index() {String resourceUri = ...String body = webClient.get().uri(resourceUri).attributes(clientRegistrationId("okta"))   .retrieve().bodyToMono(String.class).block();...return "index";
}

clientRegistrationId() is a static method in ServletOAuth2AuthorizedClientExchangeFilterFunction.

3、默认授权客户端

如果 OAuth2AuthorizedClient 或 ClientRegistration.getRegistrationId() 都没有作为请求属性(request attribute)提供,ServletOAuth2AuthorizedClientExchangeFilterFunction 可以根据其配置决定使用默认客户端。

如果配置了 setDefaultOAuth2AuthorizedClient(true),并且用户已经通过 HttpSecurity.oauth2Login() 进行了认证,则使用与当前 OAuth2AuthenticationToken 关联的 OAuth2AccessToken。

下面的代码显示了具体的配置。

  • Java
@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);oauth2Client.setDefaultOAuth2AuthorizedClient(true);return WebClient.builder().apply(oauth2Client.oauth2Configuration()).build();
}

对这个功能要谨慎,因为所有的HTTP请求都会收到访问令牌。

另外,如果 setDefaultClientRegistrationId("okta") 配置了一个有效的 ClientRegistration,则会使用与 OAuth2AuthorizedClient 相关的 OAuth2AccessToken。

下面的代码显示了具体的配置。

  • Java
@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);oauth2Client.setDefaultClientRegistrationId("okta");return WebClient.builder().apply(oauth2Client.oauth2Configuration()).build();
}

对这个功能要谨慎,因为所有的HTTP请求都会收到访问令牌。

查看全文

99%的人还看了

猜你感兴趣

版权申明

本文"Spring Security—OAuth2 客户端认证和授权":http://eshow365.cn/6-23200-0.html 内容来自互联网,请自行判断内容的正确性。如有侵权请联系我们,立即删除!