Код: Выделить всё
@Component
@RequiredArgsConstructor
public class JwtAuthFilter extends OncePerRequestFilter {
private static final String BEARER_PREFIX = "Bearer ";
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final int TOKEN_START_INDEX = 7;
private final JwtService jwtService;
private final UserDetailsService jpaUserDetailsService;
@Override
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain filterChain) throws ServletException, IOException {
String authHeader = request.getHeader(AUTHORIZATION_HEADER);
if (hasBearerHeader(authHeader)) {
String token = extractToken(authHeader);
String username = jwtService.extractUsername(token);
if (username != null && !isUserAuthenticated()) {
UserDetails userDetails = jpaUserDetailsService.loadUserByUsername(username);
if (jwtService.isTokenValid(token, userDetails)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
}
}
}
filterChain.doFilter(request, response);
}
private boolean hasBearerHeader(final String authHeader) {
return StringUtils.hasText(authHeader) && authHeader.startsWith(BEARER_PREFIX);
}
private String extractToken(String authHeader) {
return Optional.of(authHeader)
.filter(s -> s.length() > TOKEN_START_INDEX)
.map(s -> s.substring(TOKEN_START_INDEX))
.orElseThrow(() -> new BadCredentialsException("Invalid Authorization header: Bearer token is missing or invalid."));
}
private boolean isUserAuthenticated() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication != null && authentication.isAuthenticated();
}
}
Код: Выделить всё
@Service
public class JwtService {
private static final int TOKEN_VALIDITY_HOURS = 1;
private static final int SECONDS_PER_HOUR = 3600;
private static final int TOKEN_VALIDITY_SECONDS = TOKEN_VALIDITY_HOURS * SECONDS_PER_HOUR;
private static final String ALGORITHM = "HmacSHA256";
@Value("${secret.key}")
private String secretKey;
public String generateToken(final UserDetails userDetails) {
return generateToken(new HashMap(), userDetails);
}
public String generateToken(final Map claims, final UserDetails userDetails) {
Instant currentTime = Instant.now();
Instant expirationTime = currentTime.plusSeconds(TOKEN_VALIDITY_SECONDS);
return Jwts
.builder()
.claims(claims)
.subject(userDetails.getUsername())
.issuedAt(Date.from(currentTime))
.expiration(Date.from(expirationTime))
.signWith(getSecretKey(), Jwts.SIG.HS256)
.compact();
}
public boolean isTokenValid(final String token, final UserDetails userDetails) {
String usernameFromToken = extractUsername(token);
return usernameFromToken.equals(userDetails.getUsername()) && !isTokenExpired(token);
}
private boolean isTokenExpired(final String token) {
return extractExpiration(token).before(new Date());
}
public String extractUsername(final String token) {
return extractClaim(token, Claims::getSubject);
}
public Date extractExpiration(final String token) {
return extractClaim(token, Claims::getExpiration);
}
private T extractClaim(final String token, final Function extractor) {
Claims claims = Jwts.parser()
.verifyWith(getSecretKey())
.build()
.parseSignedClaims(token)
.getPayload();
return extractor.apply(claims);
}
private SecretKey getSecretKey() {
byte[] decodedKey = Base64.getDecoder().decode(secretKey);
return new SecretKeySpec(decodedKey, 0, decodedKey.length, ALGORITHM);
}
}
Я ценю любые подробные объяснения и рекомендации о том, как эффективно обрабатывать аутентификацию JWT в Spring Security.
Подробнее здесь: https://stackoverflow.com/questions/785 ... t-authenti
Мобильная версия