http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
package com.eazybytes.filter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import javax.crypto.SecretKey;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import com.eazybytes.constants.SecurityConstants;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class JWTTokenGeneratorFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (null != authentication) {
SecretKey key = Keys.hmacShaKeyFor(SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8));
String jwt = Jwts.builder().setIssuer("Eazy Bank").setSubject("JWT Token")
.claim("username", authentication.getName())
.claim("authorities", populateAuthorities(authentication.getAuthorities()))
.setIssuedAt(new Date())
.setExpiration(new Date((new Date()).getTime() + 30000000))
.signWith(key).compact();
response.setHeader(SecurityConstants.JWT_HEADER, jwt);
}
filterChain.doFilter(request, response);
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return !request.getServletPath().equals("/user");
}
private String populateAuthorities(Collection<? extends GrantedAuthority> collection) {
Set<String> authoritiesSet = new HashSet<>();
for(GrantedAuthority authority : collection) {
authoritiesSet.add(authority.getAuthority());
}
return String.join(",", authoritiesSet);
}
}
package com.eazybytes.constants;
public interface SecurityConstants {
public static final String JWT_KEY = "jxgEQeXHuPq8VdbyYFNkANdudQ53YUn4";
public static final String JWT_HEADER = "Authorization";
}
security config class에 해당 filter가 돌 수 있도록 다음과 같이 설정한다.
추가로 filter를 생성해준다.
package com.eazybytes.filter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import javax.crypto.SecretKey;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import com.eazybytes.constants.SecurityConstants;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class JWTTokenValidatorFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String jwt = request.getHeader(SecurityConstants.JWT_HEADER);
if(null != jwt) {
try {
SecretKey key = Keys.hmacShaKeyFor(
SecurityConstants.JWT_KEY.getBytes(StandardCharsets.UTF_8));
Claims claims = Jwts.parserBuilder()
.setSigningKey(key)
.build()
.parseClaimsJws(jwt)
.getBody();
String username = String.valueOf(claims.get("username"));
String authorities = (String) claims.get("authorities");
Authentication auth = new UsernamePasswordAuthenticationToken(username, null,
AuthorityUtils.commaSeparatedStringToAuthorityList(authorities));
SecurityContextHolder.getContext().setAuthentication(auth);
} catch(Exception e) {
throw new BadCredentialsException("Invalid Token received!");
}
}
}
@Override
protected boolean shouldNotFilter(HttpServletRequest request) {
return request.getServletPath().equals("/user");
}
}