npr*_*ebe 4 spring-security oauth-2.0 jwt spring-boot keycloak
我有一个 JWT,可以在特定声明下找到角色。该声明处于嵌套结构中。如何告诉 JwtAuthenticationConverter 查找特定路径下的角色?
作为授权服务器,我使用 Keycloak。可以为角色添加映射器。但我现在想排除这种可能性,因为目标是找到特定声明下的角色。
这是我解码的 JWT。角色“user-role”应位于声明下:“resource_access”->“user”->“roles”:
"resource_access": {
"admin": {
"roles": [
"admin-role"
]
},
"user": {
"roles": [
"user-role"
]
},
"account": {
"roles": [
"manage-account",
"manage-account-links",
"view-profile"
]
}
},
Run Code Online (Sandbox Code Playgroud)
这是我的 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;
}
}
Run Code Online (Sandbox Code Playgroud)
我希望有一个人可以帮助我。谢谢 :)
感谢您的帮助。解决方案是实现自定义转换器。
这是我的解决方案:
我的自定义转换器:
@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());
}
}
Run Code Online (Sandbox Code Playgroud)
我的安全配置:
@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));
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
10850 次 |
最近记录: |