Я реализую аутентификацию JWT в Spring Security. У меня есть предопределенные роли, например. обычный пользователь, админ и т. д.
У меня есть следующая полезная нагрузка токена:
{
"sub": "nick",
"iat": "<some_date>",
"exp": "<some_date+1h>",
"scopes": [
"ROLE_USER",
"ROLE_ADMIN"
]
}
Большинство реализаций, которые я видел до сих пор, извлекают данные пользователя из базы данных на основе идентификатора / имени пользователя / электронной почты, а затем используют эти данные для создания аутентификации (например, путем аутентификации UsernamePasswordAuthenticationToken). Для меня это на самом деле предпочтительный путь, потому что у меня всегда есть актуальные привилегии и ограничения (например, был ли пользователь забанен), а временные затраты не так велики по сравнению с преимуществами.
Мне просто любопытно, как я могу реализовать авторизацию с помощью Spring Security только на основе ролей, включенных во входящий запрос (в его токене заголовка авторизации). Я просто хочу иметь доступ к идентификатору пользователя в контроллере после того, как запрос будет правильно маршрутизирован. Будет ли достаточно проверки токена, основанной только на проверке срока действия и валидности ролей?
Поскольку информация о ролях пользователя является частью вашего токена (в заявлении scopes), можно создать объект аутентификации на основе одного токена без дальнейшего доступа к базе данных.
В следующем примере метод createAuthentication() преобразует токен в объект Spring Security Authentication.
public class JWTFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String jwt = // resolveToken(httpServletRequest);
this.createAuthentication(jwt).ifPresent(authentication -> {
SecurityContextHolder.getContext().setAuthentication(authentication);
});
filterChain.doFilter(servletRequest, servletResponse);
}
public Optional<Authentication> createAuthentication(String token) {
Jws<Claims> jwsClaims = validateToken(token);
if (jwsClaims == null) {
return Optional.empty();
}
Claims claims = jwsClaims.getBody();
String scopesString = claims.get("scopes").toString();
String[] authStrings = scopesString.split(",");
Collection<? extends GrantedAuthority> authorities =
Arrays.stream(authStrings)
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
String subject = claims.getSubject();
org.springframework.security.core.userdetails.User principal = new User(subject, "", authorities);
return Optional.of(new UsernamePasswordAuthenticationToken(principal, token, authorities));
}
private Jws<Claims> validateToken(String authToken) {
try {
Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(authToken);
return claims;
} catch ...
}
}
Не могли бы вы опубликовать то, что у вас есть в классах конфигурации?