如何为特定声明结构配置 JwtAuthenticationConverter?
How configure the JwtAuthenticationConverter for a specific claim structure?
我有一个 JWT,可以在其中找到特定声明下的角色。此声明位于嵌套结构中。
我怎样才能告诉 JwtAuthenticationConverter 在特定路径下找到角色?
作为授权服务器,我使用 Keycloak。可以为角色添加映射器。但我想暂时排除这种可能性,因为目标是找到特定索赔下的角色。
这是我解码后的 JWT。角色“用户角色”应位于声明下:“resource_access”->“用户”->“角色”:
"resource_access": {
"admin": {
"roles": [
"admin-role"
]
},
"user": {
"roles": [
"user-role"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
这是我对 JwtAuthenticationConverter 的配置:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter());
}
private static JwtAuthenticationConverter jwtAuthenticationConverter()
{
var jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("resource_access.user.roles");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
var jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
}
希望有人能帮助我。谢谢:)
感谢您的帮助。解决方案是实现自定义转换器。
这是我的解决方案:
我的自定义转换器:
@AllArgsConstructor
public class KeycloakJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken>
{
@NotEmpty
private List<String> clientIds;
@Override
public AbstractAuthenticationToken convert(Jwt source)
{
return new JwtAuthenticationToken(source, Stream.concat(new JwtGrantedAuthoritiesConverter().convert(source)
.stream(), extractResourceRoles(source).stream())
.collect(toSet()));
}
private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt)
{
var resourceAccess = new HashMap<>(jwt.getClaim("resource_access"));
var resourceRoles = new ArrayList<>();
clientIds.stream().forEach(id ->
{
if (resourceAccess.containsKey(id))
{
var resource = (Map<String, List<String>>) resourceAccess.get(id);
resource.get("roles").forEach(role -> resourceRoles.add(id + "_" + role));
}
});
return resourceRoles.isEmpty() ? emptySet() : resourceRoles.stream().map(r -> new SimpleGrantedAuthority("ROLE_" + r)).collect(toSet());
}
}
我的安全配置:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Value("${spring.security.jwt.role.locations}")
private List<String> rolesLocation;
@Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new KeycloakJwtAuthenticationConverter(rolesLocation));
}
}
我有一个 JWT,可以在其中找到特定声明下的角色。此声明位于嵌套结构中。 我怎样才能告诉 JwtAuthenticationConverter 在特定路径下找到角色?
作为授权服务器,我使用 Keycloak。可以为角色添加映射器。但我想暂时排除这种可能性,因为目标是找到特定索赔下的角色。
这是我解码后的 JWT。角色“用户角色”应位于声明下:“resource_access”->“用户”->“角色”:
"resource_access": {
"admin": {
"roles": [
"admin-role"
]
},
"user": {
"roles": [
"user-role"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
这是我对 JwtAuthenticationConverter 的配置:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter());
}
private static JwtAuthenticationConverter jwtAuthenticationConverter()
{
var jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("resource_access.user.roles");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
var jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
}
希望有人能帮助我。谢谢:)
感谢您的帮助。解决方案是实现自定义转换器。
这是我的解决方案:
我的自定义转换器:
@AllArgsConstructor
public class KeycloakJwtAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken>
{
@NotEmpty
private List<String> clientIds;
@Override
public AbstractAuthenticationToken convert(Jwt source)
{
return new JwtAuthenticationToken(source, Stream.concat(new JwtGrantedAuthoritiesConverter().convert(source)
.stream(), extractResourceRoles(source).stream())
.collect(toSet()));
}
private Collection<? extends GrantedAuthority> extractResourceRoles(Jwt jwt)
{
var resourceAccess = new HashMap<>(jwt.getClaim("resource_access"));
var resourceRoles = new ArrayList<>();
clientIds.stream().forEach(id ->
{
if (resourceAccess.containsKey(id))
{
var resource = (Map<String, List<String>>) resourceAccess.get(id);
resource.get("roles").forEach(role -> resourceRoles.add(id + "_" + role));
}
});
return resourceRoles.isEmpty() ? emptySet() : resourceRoles.stream().map(r -> new SimpleGrantedAuthority("ROLE_" + r)).collect(toSet());
}
}
我的安全配置:
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Value("${spring.security.jwt.role.locations}")
private List<String> rolesLocation;
@Override
public void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(new KeycloakJwtAuthenticationConverter(rolesLocation));
}
}