简体   繁体   中英

JSON Web Token in spring session

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM