我的数据库中有数据,但是当我点击 LOGIN api 时,AuthenticationManager.authenticate() 方法失败 ,当我调试它时,在 DaoAuthProvider...class.retriveUser() 内部有 UserDeatil 对象(IMAGE-1),但是当它将对象返回到 AuthProvider 类(IMAGE-2)时,之后我得到 401
我调试了更多并得到了这个 无法完成请求:org.springframework.security.authentication.LockedException:用户帐户已锁定
就在 IMAGE-1 之后,我有了 USER 对象,但仍然让我陷入 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);
}
}
如何让它发挥作用?
从你的屏幕截图中不清楚,但是,很可能你有
UserDetailsService
加载 UserDetials
,在 isAccountNonLocked()
方法中返回 false。 加载 UserDetails 后立即会出现一个检查,表明帐户未锁定。如果是,那么您将得到 LockedException
。