【问题标题】:Getting wrong exception response (403)得到错误的异常响应 (403)
【发布时间】:2021-06-12 07:18:39
【问题描述】:

我有一个登录控制器,如果凭据错误 - 应该返回 BadCredentialsException 和 json 中的消息,但我得到的是 403 响应。

我的代码:

控制器 -

@PostMapping("/login")
public ResponseEntity<AuthenticationResponse> login(@Valid @RequestBody AuthenticationRequest data) {
    try {

        System.out.println(data);
        String email = data.getEmail();
        Authentication authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(email, data.getPassword()));
        SecurityContextHolder.getContext().setAuthentication(authentication);
        String token = jwtTokenProvider.createToken(email);
        AuthenticationResponse response = new AuthenticationResponse(email, token);
        return ok(response);
    } catch (AuthenticationException ex) {
        throw new BadCredentialsException(messageSource.getMessage("authController.invalidCredentials", null, null));
    }
}

安全配置 -

http
                .httpBasic().disable()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/**")
                .permitAll()
                .and()
                .apply(new JwtConfigurer(jwtTokenProvider))
                .and()
                .cors().and().csrf()
                .disable();

令牌创建 -

    public String createToken(String username) {
        Claims claims = Jwts.claims().setSubject(username);

        Date now = new Date();
        Date validity = new Date(now.getTime() + validityInMilliseconds);

        return Jwts.builder()
                .setClaims(claims)
                .setIssuedAt(now)
                .setExpiration(validity)
                .signWith(HS256, secretKey)
                .compact();
    }

我得到的当前 Json 是 -

    {
        "timestamp": "2021-03-14T23:34:49.038+00:00",
        "status": 403,
        "error": "Forbidden",
        "message": "",
        "path": "/auth/login/"
    }

目标是在 json 中获取消息,即凭据有问题。非常感谢您的帮助:)

【问题讨论】:

    标签: java spring spring-boot


    【解决方案1】:

    因为默认的Authentication入口点是org.springframework.security.web.authentication.Http403ForbiddenEntryPoint

    您可以像这样覆盖默认身份验证入口点:

    public static class Message {
        private String message;
    
        public Message(String message) {
            this.message = message;
        }
    
        public String getMessage() {
            return message;
        }
    }
    
    private static final ObjectMapper objectMapper = new ObjectMapper();
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // set your authentication entry point
        http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); // you could replace your custom HTTP status
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
    
            PrintWriter out = response.getWriter();
            out.print(objectMapper.writeValueAsString(new Message(authException.getMessage())));
            out.flush();
        });
    
        http
                .httpBasic().disable()
                .csrf().disable()
    
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/**")
                .permitAll()
                .and()
                .apply(new JwtConfigurer(jwtTokenProvider))
                .and()
                .cors().and().csrf()
                .disable();
    }
    

    您还可以检查异常类型:

        if (authException instanceof BadCredentialsException) {
            // Do somthing
        }
    

    【讨论】:

    • 但是你能解释一下为什么默认情况下这不起作用吗?为什么我们需要进行这些配置更改.. 再次感谢 :)
    • 您可以查看 WebSecurityConfiguration 以获取更多信息。 WebSecurityConfiguration 使用 WebSecurity 构建器创建一个过滤器链来执行安全性。您的WebSecurityConfigurerAdapterWebSecurity 的定制化。继续WebSecurityConfigurerAdapter#getHttp,它通过调用http.exceptionHandling();ExceptionHandlingConfigurer在方法applyDefaultConfiguration上创建一个异常处理(ExceptionHandlingConfigurer),创建过滤器ExceptionTranslationFilter处理AuthenticationException
    • 查看ExceptionHandlingConfigurer#configure,您可以看到它使用默认入口点Http403ForbiddenEntryPoint 创建ExceptionTranslationFilterExceptionTranslationFilter 通过方法 handleSpringSecurityException 处理 AuthenticationExceptionBadCredentialsExceptionAuthenticationException。这就是为什么如果您没有为 ExceptionTranslationFilter 设置入口点,您会得到 403 的原因。
    • 您可以使用调试器更好地理解。
    【解决方案2】:

    试试这个:

    安全配置

                http
                .httpBasic().disable()
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                .antMatchers("/auth/login")
                .permitAll()
                .and()
                .apply(new JwtConfigurer(jwtTokenProvider))
                .and()
                .cors().and().csrf()
                .disable()
                .anyRequest().authenticated()
                .and().apply(securityConfigurerAdapter());;
    

    【讨论】:

    • 嘿,对不起,你的例子没有成功。也许你可以指定你的答案?那个 securityConfigurerAdapter 是什么?
    • 你的 http 请求 url "/auth/login" 没有被 SecurityConfig 过滤,所以你应该更新代码。
    猜你喜欢
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    相关资源
    最近更新 更多