我在验证用户凭据时遇到问题 . 当我第一次提供正确的凭据时,一切正常,但首先提供无效的凭据,然后给出正确的凭据,我得到无效的凭据错误 . 我使用Postman Basic Auth .
我的配置类:
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserService userService;
@Autowired
private CustomAuthenticationEntryPoint authenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable().authorizeRequests()
.antMatchers(HttpMethod.POST ,"/login").permitAll()
.antMatchers("/admin").hasAuthority("ADMIN")
.anyRequest().authenticated().and().exceptionHandling().authenticationEntryPoint(authenticationEntryPoint).and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS).and()
.logout()
.deleteCookies("remove")
.invalidateHttpSession(true);
http.rememberMe().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(this.userService)
.and().eraseCredentials(true);
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
和我的控制器类
@PostMapping
public ResponseEntity loginButtonClicked(HttpServletRequest request) {
HttpSession session = request.getSession();
final String authorization = request.getHeader("Authorization");
String[] authorizationData=null;
if (authorization != null && authorization.startsWith("Basic")) {
// Authorization: Basic base64credentials
String base64Credentials = authorization.substring("Basic" .length()).trim();
String credentials = new String(Base64.getDecoder().decode(base64Credentials),
Charset.forName("UTF-8"));
// credentials = username:password
authorizationData = credentials.split(":", 2);
UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(authorizationData[0], authorizationData[1],Arrays.asList(new SimpleGrantedAuthority("USER")));
User user = userService.findUserEntityByLogin(authorizationData[0]);
if(user != null && user.getFromWhenAcceptLoginAttempts() != null && (user.getFromWhenAcceptLoginAttempts()).isBefore(LocalDateTime.now())){
// Authenticate the user
Authentication authentication = authenticationManager.authenticate(authRequest);
SecurityContext securityContext = SecurityContextHolder.getContext();
securityContext.setAuthentication(authentication);
// Create a new session and add the security context.
session = request.getSession();
session.setAttribute("SPRING_SECURITY_CONTEXT", securityContext);
return new ResponseEntity(new LoginResponseObject(200,"ACCESS GRANTED. YOU HAVE BEEN AUTHENTICATED"), HttpStatus.OK);
}else{
session.getId();
SecurityContextHolder.clearContext();
if(session != null) {
session.invalidate();
}
return new ResponseEntity(new ErrorObject(403,"TOO MANY LOGIN REQUESTS","YOU HAVE ENTERED TOO MANY WRONG CREDENTIALS. YOUR ACCOUNT HAS BEEN BLOCKED FOR 15 MINUTES.", "/login"), HttpStatus.FORBIDDEN);
}
}else{
session.getId();
SecurityContextHolder.clearContext();
if(session != null) {
session.invalidate();
}
return new ResponseEntity(new ErrorObject(401,"INVALID DATA","YOU HAVE ENTERED WRONG USERNAME/PASSWORD CREDENTIALS", "/login"), HttpStatus.UNAUTHORIZED);
}
}
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public ObjectMapper objectMapper(){
return new ObjectMapper();
}
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
2 回答
问题是由于sessionCreationPolicy,请求存储在缓存中 .
要避免此问题,您可以在http安全配置中添加
.requestCache().requestCache(new NullRequestCache())
以覆盖默认请求缓存配置,但要小心,因为这可能会产生另一个副作用(这取决于您的应用程序) .如果您不需要会话,可以选择其他会话策略:
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.另一种方法是在Spring的BasicAuthenticationFilter中进行中继 . 此过滤器为您执行所有身份验证逻辑 . 要启用它,您只需在http安全配置中添加
.httpBasic()
.您可能希望在身份验证成功/失败时添加自定义逻辑 . 在这种情况下,您只需创建一个扩展
BasicAuthenticationFilter
类的自定义过滤器(CustomBasicAuthenticationFilter
)并覆盖方法onSuccessfulAuthentication()
和onUnsuccessfulAuthentication()
. 您无需添加.httpBasic()
,但需要在正确的位置插入自定义过滤器:.addFilterAfter(new CustomBasicAuthenticationFilter(authenticationManager), LogoutFilter.class)
.任何这三种解决方案都可以避免您的问题 .
尝试在
SpringSecurityConfig
类中编写.deleteCookies("JSESSONID")
.