Spring Security自定义登录端点认证失败返回200而非401问题咨询
问题原因
AuthenticationManager#authenticate方法在传入错误的用户名密码时,会直接抛出BadCredentialsException类型的AuthenticationException异常,不会返回null,你原有代码里的认证失败判断逻辑永远不会被触发。- 你开启了Spring Security默认的
formLogin配置,该配置会注册默认的认证失败处理器,捕获到认证异常后会重定向到默认登录页面,所以返回200状态码和登录表单内容。 - 你自定义的登录接口路径是
/login,但你的Security配置里只放行/users/login路径,同时Spring Security默认的form登录处理器默认监听POST /login请求,和你自定义的接口产生了路径冲突。
修复方案
1. 修改Spring Security配置
禁用默认表单登录,同时把你自定义的登录接口加入放行列表,修改后的configure(HttpSecurity http)方法代码如下:
@Override protected void configure(HttpSecurity http) throws Exception { http.cors() .and() .authorizeRequests() .antMatchers(HttpMethod.GET).hasAuthority(UserRole.USER.name()) .antMatchers(HttpMethod.POST, "/users").permitAll() // 放行自定义登录接口路径 .antMatchers(HttpMethod.POST, "/login").permitAll() .antMatchers(HttpMethod.POST).hasAuthority(UserRole.USER.name()) // 禁用默认表单登录,避免路径冲突和默认异常处理干扰 .and() .formLogin().disable() .logout().invalidateHttpSession(true) .clearAuthentication(true).permitAll() .and() .csrf().disable(); }
2. 修改自定义登录接口代码
添加异常捕获逻辑处理认证失败的场景,删掉原有无效的空值判断:
@PostMapping("/login") public ResponseEntity<?> login(@RequestBody LoginUserRequest userRequest) { try { Authentication authentication = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(userRequest.getUsername(), userRequest.getPassword())); SecurityContextHolder.getContext().setAuthentication(authentication); return new ResponseEntity<>(HttpStatus.OK); } catch (AuthenticationException e) { // 捕获所有认证相关异常,直接返回401 return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); } }
内容的提问来源于stack exchange,提问作者Kamil
相关产品推荐
相关产品推荐

