Spring Boot JWT,AuthenticationManager.authenticate() 在登录过程中不起作用

问题描述 投票:0回答:1

我的数据库中有数据,但是当我点击 LOGIN api 时,AuthenticationManager.authenticate() 方法失败 ,当我调试它时,在 DaoAuthProvider...class.retriveUser() 内部有 UserDeatil 对象(IMAGE-1),但是当它将对象返回到 AuthProvider 类(IMAGE-2)时,之后我得到 401

我调试了更多并得到了这个 无法完成请求:org.springframework.security.authentication.LockedException:用户帐户已锁定

就在 IMAGE-1 之后,我有了 USER 对象,但仍然让我陷入 IMAGE-2

IMAGE-1 IMAGE-2

@Component
public class JwtTokenFilter extends OncePerRequestFilter {
    private static final Logger logger = LoggerFactory.getLogger(JwtTokenFilter.class);
    @Autowired
    private UserDetailsServiceImpl userDetailService;

    @Autowired
    private JwtUtils jwtUtils;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        /**
         * 1. get JWT from cookie
         * 2. generate JWT in cookie
         * 4. get username from token - email
         * 5. validate JWT
         */

        try {
            String jwt = jwtUtils.getJwtFromCookie(request);
            if (jwt != null && jwtUtils.validateJWT(jwt)) {
                String email = jwtUtils.getEmailFromJWT(jwt);

                UserDetails userDetails = getUserDeatilsfromEmail(email);
                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }else{
                System.out.println("check");
            }
        } catch (Exception e) {
            logger.error("unable to process jwt due to exception : " + e.getMessage());
        }
        filterChain.doFilter(request, response);
    }

    private UserDetails getUserDeatilsfromEmail(String email) {
        return userDetailService.loadUserByUsername(email);
    }


}
@Component
@Slf4j
public class JwtUtils
{
    @Value(value = "${receiptScanner.app.jwt-cookie}")
    private String jwtCookie;

    @Value(value = "${receiptScanner.app.jwt-secret}")
    private String jwtSecret;

    @Value(value = "${receiptScanner.app.jwt-expiration}")
    private int jwtExpiration;

//    @Value(value = "${receiptScanner.app.jwt-refresh-expiration}")
//    private int jwtRefreshExpirationDateInMS;

    Date date = new Date();
    long t = date.getTime();
    Date expirationTime = new Date(t + jwtExpiration);

    /**
     * Used to get email/username from jwt
     *
     * @param jwt
     * @return
     */
    protected String getEmailFromJWT(String jwt) {
        return Jwts.parser().setSigningKey(key())
                .parseClaimsJwt(jwt).getBody().getSubject();
    }

    private Key key() {
        return Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtSecret));
    }

    /**
     * Used to validate JWT
     *
     * @param jwt
     * @return
     */
    protected boolean validateJWT(String jwt) {
        try {
            log.info("JWT token : " + jwt);

            Jwts.parser().setSigningKey(key()).parseClaimsJwt(jwt);
            return true;
        } catch (MalformedJwtException e) {
            log.error("Invalid JWT token: {}", e.getMessage());
        } catch (ExpiredJwtException e) {
            log.error("JWT token is expired: {}", e.getMessage());
        } catch (UnsupportedJwtException e) {
            log.error("JWT token is unsupported: {}", e.getMessage());
        } catch (IllegalArgumentException e) {
            log.error("JWT claims string is empty: {}", e.getMessage());
        }
        return false;
    }

    /**
     * Get JWT from cookie
     *
     * @param request
     * @return
     */
    protected String getJwtFromCookie(HttpServletRequest request) {
        Cookie cookie = WebUtils.getCookie(request, jwtCookie);
        if (cookie == null) return null;
        return cookie.getValue();
    }


    /**
     * 1. clean cookie when signOut
     * 2. generate jwt when logIn
     */

    /**
     * Used to clean cookie to perform signOut
     *
     * @return
     */
    public ResponseCookie getCleanJwtCookie() {
        return ResponseCookie.from(jwtCookie, null).build();
    }

    /**
     * Used to generate JWT from email
     *
     * @param email
     * @return
     */
    public String generateJwtfromUsername(String email) {
        return Jwts.builder()
                .setSubject(email)
                .setIssuedAt(new Date(System.currentTimeMillis()))
                .setExpiration(new Date(System.currentTimeMillis() + jwtExpiration))
                .signWith( key(), SignatureAlgorithm.HS256)
                .compact();
    }


//    private String generateRefreshToken(String subject) {
//        return Jwts.builder()
//                .setSubject(subject)
//                .setIssuedAt(new Date(System.currentTimeMillis()))
//                .setExpiration(new Date(System.currentTimeMillis() + jwtRefreshExpirationDateInMS))
//                .signWith(SignatureAlgorithm.HS512, jwtSecret)
//                .compact();
//    }

    /**
     * Used to set cookie with jwt when sign in
     *
     * @param userDetails
     * @return
     */
    public ResponseCookie generateJwtCookie(UserDetailsImpl userDetails) {
        String jwt = generateJwtfromUsername(userDetails.getUsername());
        return ResponseCookie.from(jwtCookie, jwt).maxAge(24 * 60 * 60).httpOnly(true).build();
    }

    public String getJwt(HttpServletRequest request) {
        String bearerToken = request.getHeader("Authorization");
        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
            return bearerToken.substring(7, bearerToken.length());
        }
        return null;
    }
}
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    UserRepository userRepository;

    @Override
    @Transactional
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        AppUser user = userRepository.findByUsername(username)
                .orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));

        return UserDetailsImpl.build(user);
    }
}
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class WebSecurityConfig {
    private static final Logger logger = LoggerFactory.getLogger(WebSecurityConfig.class);

    @Autowired
    private JwtTokenFilter jwtTokenFilter;

    @Autowired
    private UserDetailsServiceImpl userDetailsService;



    /**
     * Setting up bean of Password Encoder
     *
     * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * Bean of Authentication manager
     *
     * @param authenticationConfiguration
     * @return
     * @throws Exception
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    /**
     * We are using Dao-Auth-Provider for authentication
     *
     * @return
     */
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
        authenticationProvider.setPasswordEncoder(passwordEncoder());
        authenticationProvider.setUserDetailsService(userDetailsService);
        return authenticationProvider;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        /**
         * 1. cors - enable
         * 2. csrf - disable
         * 3. exception handling for unauthorized requests
         * 4. Application - stateless
         * 5. Mappings allowed
         * 6. Add JWT token filter on first place
         */

        http = http.csrf(csrf -> csrf.disable());

        http = http.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        http = http.exceptionHandling(exception -> exception.authenticationEntryPoint(((request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))));

        http = http.authorizeHttpRequests(request -> request.requestMatchers("/v1/auth/**").permitAll()
                .requestMatchers("/h2-console/**").permitAll()
                .anyRequest().authenticated());

        http = http.headers(headers -> headers.frameOptions(frameOption -> frameOption.sameOrigin()));

        http = http.authenticationProvider(authenticationProvider());

        http = http.addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();

    }
}

@RestController
@CrossOrigin(origins = "*", maxAge = 3600)
@RequestMapping("/v1/auth")
@Slf4j
public class UserController {

    /**
     * 1. add user // register
     * 2. delete user
     * 3. get user by emailId // login
     */
    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private UserService userService;

    @GetMapping(value = "/login")
    public ResponseEntity<?> getUser(@RequestBody LoginRequest loginRequest) {
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));

        SecurityContextHolder.getContext().setAuthentication(authentication);

        UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();

        ResponseCookie cookie = jwtUtils.generateJwtCookie(userDetails);

        return ResponseEntity.ok().header(HttpHeaders.SET_COOKIE, cookie.toString()).body(userDetails);
    }
}

如何让它发挥作用?

spring spring-boot spring-security jwt
1个回答
0
投票

从你的屏幕截图中不清楚,但是,很可能你有

UserDetailsService
加载
UserDetials
,在
isAccountNonLocked()
方法中返回 false。 加载 UserDetails 后立即会出现一个检查,表明帐户未锁定。如果是,那么您将得到
LockedException

© www.soinside.com 2019 - 2024. All rights reserved.