【发布时间】:2021-11-10 07:45:43
【问题描述】:
我有一个Spring Security OAuth2 和Keycloak 设置。
在Client 应用程序端,工件如下所示:
application.yml
server.port: 8182
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: myclient-ac
client-secret: 81e3fd9f-52ce-4549-8ea9-ae53e754da89
authorization-grant-type: authorization_code
redirect-uri: http://localhost:8182/login/oauth2/code/myclient-ac
scope: openid
provider:
keycloak:
issuer-uri: http://localhost:8180/auth/realms/myrealm
#authorization-uri: http://localhost:8180/auth/realms/myrealm/protocol/openid-connect/auth
#token-uri: http://localhost:8180/auth/realms/myrealm/protocol/openid-connect/token
#user-info-uri: http://localhost:8180/auth/realms/myrealm/protocol/openid-connect/userinfo
#jwk-set-uri: http://localhost:8180/auth/realms/myrealm/protocol/openid-connect/certs
#user-name-attribute: preferred_username
SecurityConfig.java
@EnableWebSecurity
public class SecurityConfig {
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().permitAll()
.and()
.oauth2Login().disable()
.oauth2Client();
return http.build();
}
}
WebClientConfig.java
@Configuration
public class WebClientConfig {
@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.authorizationCode()
.refreshToken()
.build();
DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
}
MyRestControllerClient.java
@RestController
public class MyRestControllerClient {
private static final Logger LOGGER = LoggerFactory.getLogger(MyRestControllerClient.class);
@Autowired
private WebClient webClient;
@GetMapping("/helloworld")
public String helloworld(@RegisteredOAuth2AuthorizedClient("keycloak") OAuth2AuthorizedClient authorizedClient) {
String body = webClient
.get()
.uri("http://localhost:8181/helloworld")
.attributes(oauth2AuthorizedClient(authorizedClient))
.retrieve()
.bodyToMono(String.class)
.block();
LOGGER.info(body);
return body;
}
@GetMapping("/oidc-principal")
public OidcUser getOidcUserPrincipal(@AuthenticationPrincipal OidcUser principal) {
return principal;
}
}
访问 http://localhost:8182/helloworld 会导致重定向到登录页面Keycloak。提供username 和password,我可以成功访问我的/helloworld 端点。
我还想访问用户信息,根据4.1. Accessing User Informationhttps://www.baeldung.com/spring-security-openid-connect 可以在REST 控制器中通过
@GetMapping("/oidc-principal")
public OidcUser getOidcUserPrincipal(@AuthenticationPrincipal OidcUser principal) {
return principal;
}
将此端点添加到我的REST 控制器,并在/helloworld 端点之后访问它,导致principal 成为null。
如何获取用户信息?
【问题讨论】:
-
您的具体问题是什么?由于您已经回答了自己的帖子并编辑了 OP,所以我不清楚。
-
我认为我的答案是我的问题的解决方案。我仍然不明白 .oauth2Login().disable() 和 .oauth2Login() 的区别,因为整体行为是相同的。
-
.oauth2Login()添加了对 OpenID Connect 1.0 作为身份验证机制的支持。没有它,您实际上并没有在您的应用程序中进行身份验证,这就是为什么@AuthenticatedPrincipal不会返回有关当前登录用户的正确信息的原因。您可以单独使用.oauth2Client(),并使用其他东西登录您的应用程序,或者您可以一起使用它们并同时使用keycloak(登录)登录您的应用程序,并使用返回的访问令牌对资源服务器进行安全API调用您的架构(客户端)。
标签: spring spring-boot spring-security keycloak spring-security-oauth2