Внедрение токена JWT в Spring Boot - PullRequest
0 голосов
/ 30 января 2020

Я реализовал решение для аутентификации с помощью токена JWT при весенней загрузке после этого https://www.djamware.com/post/5c819d0180aca754f7a9d1ee/securing-restful-api-with-spring-boot-security-and-data-mongodb, которое отлично работает, за исключением двух вещей, оно не перенаправляет на страницу, с которой был сделан запрос, перед перенаправлением на страницу входа и SuccessHandler не работает. Из проведенных тестов мне кажется, что проблема в том, что нет успешной аутентификации, но я не знаю, как ее решить. Код следующий

securityconfig

    @Configuration
    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {

        @Autowired
        JwtTokenProvider jwtTokenProvider;

        @Autowired
        CustomAuthenticationSuccessHandler authenticationSuccess;

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            UserDetailsService userDetailsService = mongoUserDetails();
            auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());

        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                    .and().authorizeRequests()
                    .antMatchers("/", "/search_posts", "/wall/**", "/resources/**", "/css/**", "/js/**", "/webjars/**", "/api/auth/login").permitAll()
                    .antMatchers("/exams/**").hasAuthority(Role.STUDENT.toString())
                    .anyRequest().authenticated()                
                    .and().formLogin().loginPage("/login").permitAll()
                    .successHandler(authenticationSuccess)
                    .and().csrf().disable();



         // Apply JWT
            http.apply(new JwtConfigurer(jwtTokenProvider));
            //filtro para poner JWT en la cabecera del request
            http.addFilterBefore(new RequestWrapperFilter(), UsernamePasswordAuthenticationFilter.class);       
            //http.addFilterBefore(new JWTAuthenticationFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
            http.httpBasic().disable();




                    //.apply(new JwtConfigurer(jwtTokenProvider));
        }//.and()//.exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
    @Bean
    public PasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Bean
    public AuthenticationEntryPoint unauthorizedEntryPoint() {
        return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
                "Unauthorized");
    }

    @Bean
    public UserDetailsService mongoUserDetails() {
        return new CustomUserDetailsService();
    }

}

jwttoken filter

    public class JwtTokenFilter extends GenericFilterBean {

    private JwtTokenProvider jwtTokenProvider;

    public JwtTokenFilter(JwtTokenProvider jwtTokenProvider) {
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
        throws IOException, ServletException {

        String token = jwtTokenProvider.resolveToken((HttpServletRequest) req);
        if (token != null && jwtTokenProvider.validateToken(token)) {
            Authentication auth = token != null ? jwtTokenProvider.getAuthentication(token) : null;
            SecurityContext sc = SecurityContextHolder.getContext();
            sc.setAuthentication(auth);
        }
        filterChain.doFilter(req, res);
    }
}

jwttoken provider

    @Component
    public class JwtTokenProvider {
    @Value("${security.jwt.token.secret-key:secret}")
    private String secretKey = Constants.SECRET;

    @Value("${security.jwt.token.expire-length:3600000}")
    private long validityInMilliseconds = 10800000; // 3h

    @Autowired
    private CustomUserDetailsService userDetailsService;

    @PostConstruct
    protected void init() {
        secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
    }

    public String createToken(String username, Set<Role> roles) {
        Claims claims = Jwts.claims().setSubject(username);
        claims.put("roles", roles);
        Date now = new Date();
        Date validity = new Date(now.getTime() + validityInMilliseconds);
        return Jwts.builder()//
            .setClaims(claims)//
            .setIssuedAt(now)//
            .setExpiration(validity)//
            .signWith(SignatureAlgorithm.HS256, secretKey)//
            .compact();
    }

    public Authentication getAuthentication(String token) {
        UserDetails userDetails = this.userDetailsService.loadUserByUsername(getUsername(token));
        return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
    }

    public String getUsername(String token) {
        return Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token).getBody().getSubject();
    }

    public String resolveToken(HttpServletRequest req) {
         String bearerToken = req.getHeader(Constants.AUTHORIZATION);
        if (bearerToken != null && bearerToken.startsWith(Constants.BEARER)) {
            return bearerToken.substring(Constants.BEARER.length(), bearerToken.length());
        }
        return null;
    }

    public boolean validateToken(String token) {
        try {
            Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
            if (claims.getBody().getExpiration().before(new Date())) {
                return false;
            }
            return true;
        } catch (JwtException | IllegalArgumentException e) {
            throw new JwtException("Expired or invalid JWT token");
        }
    }
}

фильтр

    public class JwtConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {

    private JwtTokenProvider jwtTokenProvider;

    public JwtConfigurer(JwtTokenProvider jwtTokenProvider) {
        this.jwtTokenProvider = jwtTokenProvider;
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        JwtTokenFilter customFilter = new JwtTokenFilter(jwtTokenProvider);
        http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
    }
}

the apirest

    @RestController
    @RequestMapping("/api/auth")
    public class AuthController {

    @Autowired
    AuthenticationManager authenticationManager;

    @Autowired
    JwtTokenProvider jwtTokenProvider;

    @Autowired
    UserRepository users;

    @Autowired
    private CustomUserDetailsService userService;

    @Autowired
    AuthenticationSuccessHandler ash;

    @PostMapping("/login")
    public void login(@ModelAttribute("user") Users user, HttpServletRequest req, HttpServletResponse response) throws IOException, ServletException {      

        try {
            //set authentication
            Authentication auth = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));
            SecurityContext sc = SecurityContextHolder.getContext();
            sc.setAuthentication(auth);

            //create a token
            String token = jwtTokenProvider.createToken(user.getUsername(), this.users.findByUsername(user.getUsername()).getRoles());
            //create and set a cookie
            Cookie cookie = new Cookie(Constants.TOKEN, token);
            cookie.setMaxAge(3 * 60 * 60); // expires in 3 hours
            cookie.setHttpOnly(true);
            cookie.setPath("/");
            //add cookie to response
            response.addCookie(cookie);

            //call to onauthenticationsuccess
            //ash.onAuthenticationSuccess(req, response, auth);
        }
        catch (AuthenticationException e) {
            throw new BadCredentialsException("Invalid email/password supplied");
        }
    }   

Пожалуйста, я немного растерялся и не могу найти решение проблемы, правда ли, что Spring перенаправляет вас на запрашиваемую страницу перед страницей входа ? Есть ли способ перенаправить на предыдущую страницу перед входом в систему? спасибо

...