Получение Spring Security «Образец входа JWT» для работы с ролями
Я пытаюсь переписать предыдущий пример с JWT, созданным с помощью пользовательского фильтра JWT, в упрощенную версию, основанную на новом сервере авторизации Springs, и этот пример:https://github.com/spring-projects/spring-security-samples/tree /главный/сервлет/весенняя загрузка/java/jwt/логин
В примере настраивается InMemoryUserDetailsManager с одним пользователем → пользователем, паролем и полномочиями «приложения», поэтому я предполагаю, что он предназначен для обработки ролей/полномочий?
Все работает нормально (как объяснено в примерах README), если я использую предоставленный SecurityFilterChain. Но если я изменю это:
...
http.authorizeHttpRequests((authorize) -> authorize
.anyRequest().authenticated()
)
В это
...
http.authorizeHttpRequests((authorize) -> authorize
.antMatchers("/").hasRole("app")
//.antMatchers("/").hasAuthority("app")
.anyRequest().authenticated()
)
Я получаю статус 403. Полномочия добавляются в JWT, как и ожидалось, следующим образом:
..
"scope": "app"
}
Помимо приведенных выше antMatchers, мой код точно такой же, как клон из примера Spring Security.
Что мне здесь не хватает?
2 ответа
ИспользоватьhasRole
, вам нужны полномочия, начинающиеся сROLE_
. Что вы можете сделать, так это зарегистрировать конвертер , который будет считывать роли из JWT и добавлять их какGrantedAuthority
.
public class RolesClaimConverter implements Converter<Jwt, AbstractAuthenticationToken> {
private final JwtGrantedAuthoritiesConverter wrappedConverter;
public RolesClaimConverter(JwtGrantedAuthoritiesConverter conv) {
wrappedConverter = conv;
}
@Override
public AbstractAuthenticationToken convert(@NonNull Jwt jwt) {
// get authorities from wrapped converter
var grantedAuthorities = new ArrayList<>(wrappedConverter.convert(jwt));
// get role authorities
var roles = (List<String>) jwt.getClaims().get("roles");
if (roles != null) {
for (String role : roles) {
grantedAuthorities.add(new SimpleGrantedAuthority("ROLE_" + role));
}
}
return new JwtAuthenticationToken(jwt, grantedAuthorities);
}
}
Затем зарегистрируйте конвертер в конфигурации безопасности.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.oauth2ResourceServer(resourceServer -> resourceServer
.jwt()
.jwtAuthenticationConverter(
new RolesClaimConverter(
new JwtGrantedAuthoritiesConverter()
)
)
)
// other configuration
;
return http.build();
}
Вот и все. Все, что вам нужно сделать сейчас, это передать список ролей в качестве утверждения при создании JWT, и вы можете использовать.antMatchers("/").hasRole("app")
и@PreAuthorize("hasRole('app')")
в вашем коде.
ОК, прочитайте спецификации ;-) В соответствии с https://docs.spring.io/spring-security/reference/reactive/oauth2/resource-server/jwt.htmlAuthorities получает префикс SCOPE_
Так что это частично решает проблему .antMatchers("/").hasAuthority("SCOPE_app")
Я до сих пор не понял, как использовать hasRoles?