带有 Keycloak 的 Spring Security OAuth2 - 访问用户信息
Posted
技术标签:
【中文标题】带有 Keycloak 的 Spring Security OAuth2 - 访问用户信息【英文标题】:Spring Security OAuth2 with Keycloak - Accessing User Information 【发布时间】: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 Information
https://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调用您的架构(客户端)。
This section of the reference docs 会详细解释。
【参考方案1】:
我改变了这个
@EnableWebSecurity
public class SecurityConfig
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception
http
.authorizeRequests().anyRequest().permitAll()
.and()
.oauth2Login().disable()
.oauth2Client();
return http.build();
到
.oauth2Login()
.and()
.oauth2Client();
现在principal
充满了信息。
但是现在有什么不同? OAuth2
按预期与.oauth2Login().disable()
一起使用,行为是相同的,我被重定向到 Keycloak 的登录页面,登录发生在有或没有 .disable()
的情况下
【讨论】:
以上是关于带有 Keycloak 的 Spring Security OAuth2 - 访问用户信息的主要内容,如果未能解决你的问题,请参考以下文章
带有 Keycloak 的 Spring 应用程序返回 401 错误
带有 Spring Boot KeycloakSecurityContext 的 Keycloak 始终为空
带有 keycloak 设置的 Spring Security (HttpSecurity)
带有 keycloak 的 Spring Cloud 微服务
带有 Keycloak 的 Spring Security OAuth2 - 访问用户信息
在 Spring Boot 和 Spring Security 中,不活动、过期的令牌会导致带有 Keycloak 的 IllegalStateException