我使用 Keycloak 和基于 Spring OAuth2 授权服务器的服务具有以下流程:
访问令牌包含来自授权服务器的有关主体的一些信息(例如,姓名和电子邮件),位于
preferred_username
声明中:
"preferred_username":"given_name='markus',email='[email protected]'"
但是我需要将这些数据放在单独的声明中,如下所示:
"given_name="markus",
"email"="[email protected]",
如何将授权授予类型请求中的这些数据从授权服务器传递到 Keycloak,以便 Keycloak 能够将这些数据放入/传递访问令牌的单独声明中?
在授权服务器服务中,我有以下内容:
校长班
@Getter
@Setter
@AllArgsConstructor
public class User {
private String givenName;
private String email;
@Override
public String toString() {
return "given_name='" + givenName + '\'' +
",email='" + email + '\'';
}
}
由
toString()
生成的值以某种方式出现在Keycloak中访问令牌的preferred_username
声明中。
授权提供商
@Service
public class CustomAuthenticationProvider<T extends CustomAuthBean, A extends UsernamePasswordAuthenticationToken> implements AuthenticationProvider {
User user = this.getUserDetails();
return new UsernamePasswordAuthenticationToken(user, "", getAuthorities());
}
配置
@Configuration
public class SecurityConfig {
@Bean
@Order(1)
SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http) throws Exception {
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(withDefaults());
http
.exceptionHandling((exceptions) -> exceptions
.defaultAuthenticationEntryPointFor(
new LoginUrlAuthenticationEntryPoint("/login"),
new MediaTypeRequestMatcher(MediaType.TEXT_HTML)
)
)
.oauth2ResourceServer((resourceServer) -> resourceServer
.jwt(withDefaults()));
return http.build();
}
}
如果需要更多信息,请告诉我。预先感谢您。
Keycloak 中的
preferred_username
对应于从身份提供者(在本例中为 Spring 授权服务器)检索到的 ID 令牌中的 sub
声明。
Spring 授权服务器使用
org.springframework.security.oauth2.server.authorization.token.JwtGenerator
生成 ID 令牌
在这种情况下,因为您的
Principal
类没有实现 UserDetails
或 AuthenticatedPrincipal
或 Principal
,所以名称会落在 toString
上。
参见
org.springframework.security.authentication.AbstractAuthenticationToken
@Override
public String getName() {
if (this.getPrincipal() instanceof UserDetails userDetails) {
return userDetails.getUsername();
}
if (this.getPrincipal() instanceof AuthenticatedPrincipal authenticatedPrincipal) {
return authenticatedPrincipal.getName();
}
if (this.getPrincipal() instanceof Principal principal) {
return principal.getName();
}
return (this.getPrincipal() == null) ? "" : this.getPrincipal().toString();
}