I have three servers in production and a global load balancer when a first request comes request is validated and jwt token is generated and a token is stored in spring session in the server but when the new request comes and it went to the different server it's got me logged out.
what should I leverage here I read a few things about storing tokens in Redis, but I don't understand the flow how exactly to use it, or what are the different. option do I have here?
In Dev, I just have one server so I cannot test it out.
Can someone refer me some practical example how exactly to solve this issue
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private LoginSuccessHandler loginSuccessHandler;
@Autowired
private JWTRequestFilter jwtRequestFilter;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return provider;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
...
http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
...
}
}
JWT Util File that contains All the function relative to JWT validation and generation
@Component
public class JWTUtil {
public static final long EXPIRATION_TIME = 60 * 60 * 24;
public static final String TOKEN_PREFIX = "Bearer ";
public static final String HEADER_STRING = "Authorization";
@Value("${jwt.secret}")
private String secret;
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parserBuilder().setSigningKey(secret.getBytes()).build().parseClaimsJws(token).getBody();
}
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
private String doGenerateToken(Map<String, Object> claims, String username) {
SecretKey key = Keys.hmacShaKeyFor(secret.getBytes());
return Jwts.builder().setClaims(claims)
.setSubject(username).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME * 1000))
.signWith(key).compact();
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
public boolean validateToken(String token, String requestUsername) {
final String username = getUsernameFromToken(token);
return (username.equals(requestUsername) && !isTokenExpired(token));
}
}
An important part of Jwt if filter file that contains which URL to filter or not
@Service
public class JWTRequestFilter extends OncePerRequestFilter {
@Autowired
private JWTUtil jwtUtil;
@Autowired
private MyUserDetailsService myUserDetailsService;
Set<String> urls = new HashSet<String>(Arrays.asList("/api/login", "/api/register", "/api/"));
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
String path = request.getRequestURI();
return urls.contains(path);
}
protected boolean shouldNotFilterErrorDispatch() {
return true;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String jwtToken = null;
String username = null;
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("Authorization")) {
jwtToken = cookie.getValue();
}
}
if (jwtToken != null) {
try {
username = jwtUtil.getUsernameFromToken(jwtToken);
} catch (IllegalArgumentException e) {
System.out.println("Unable to get JWT Token");
} catch (ExpiredJwtException e) {
System.out.println("JWT Token has expired");
}
} else {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
if (username != null) {
UserDetails userDetails = this.myUserDetailsService.loadUserByUsername(username);
if (!jwtUtil.validateToken(jwtToken, userDetails.getUsername())) {
logger.warn("JWT Token validation failed");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
doFilter(request, response, filterChain);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.