Spring 使用 Keycloak 的安全 OAuth2 - 访问用户信息
Spring Security OAuth2 with Keycloak - Accessing User Information
我有一个 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
。
如何获取用户信息?
我改了这个
@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()
都会发生登录
我有一个 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
。
如何获取用户信息?
我改了这个
@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()