401 instead of 403 with Spring Boot 2

前端 未结 4 825
情歌与酒
情歌与酒 2020-12-09 17:49

With Spring Boot 1.5.6.RELEASE I was able to send HTTP Status code 401 instead of 403 as described in How let spring security response una

相关标签:
4条回答
  • 2020-12-09 18:23

    You can customize your logic with overriding the class AuthenticationEntryPoint this should be working:

    @Component public class AuthEntryPointException implements AuthenticationEntryPoint, Serializable {
    
        private static final long serialVersionUID = -8970718410437077606L;
    
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response,
            AuthenticationException authException) throws IOException {
            response.setStatus(HttpStatus.SC_UNAUTHORIZED);
            response.setContentType("application/json");
            response.getWriter().write("{\"result\":\"UNAUTHORIZED\",\"message\":\"UNAUTHORIZED or Invalid Token\"}");
        }
    }
    
    0 讨论(0)
  • 2020-12-09 18:27

    Heads up

    By default Spring Boot 2 will return 401 when spring-boot-starter-security is added as a dependency and an unauthorized request is performed.

    This may change if you place some custom configurations to modify the security mechanism behavior. If that's the case and you truly need to force the 401 status, then read the below original post.

    Original Post

    The class org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint was removed in favor of org.springframework.security.web.authentication.HttpStatusEntryPoint.

    In my case the code would go like this:

    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //...
            http.exceptionHandling()
                .authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
            //...
        }
    }
    

    Bonus

    If you need to return some information in the response body or customize the response somehow you can do something like this:

    1- Extend AuthenticationEntryPoint

    public class MyEntryPoint implements AuthenticationEntryPoint {
        private final HttpStatus httpStatus;
        private final Object responseBody;
    
        public MyEntryPoint(HttpStatus httpStatus, Object responseBody) {
            Assert.notNull(httpStatus, "httpStatus cannot be null");
            Assert.notNull(responseBody, "responseBody cannot be null");
            this.httpStatus = httpStatus;
            this.responseBody = responseBody;
        }
    
        @Override
        public final void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
            response.setStatus(httpStatus.value());
    
            try (PrintWriter writer = response.getWriter()) {
                writer.print(new ObjectMapper().writeValueAsString(responseBody));
            }
        }
    }
    

    2- Provide an instance of MyEntryPoint to the security configuration

    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            // customize your response body as needed
            Map<String, String> responseBody = new HashMap<>();
            responseBody.put("error", "unauthorized");
    
            //...
            http.exceptionHandling()
                .authenticationEntryPoint(new MyEntryPoint(HttpStatus.UNAUTHORIZED, responseBody));
            //...
        }
    }
    
    0 讨论(0)
  • 2020-12-09 18:27

    Http401AuthenticationEntryPoint was removed.

    See Spring Boot Github Repo > Issue #10715 (Remove Http401AuthenticationEntryPoint):

    Remove Http401AuthenticationEntryPoint

    rwinch commented on 20 Oct 2017
    As far as I can tell it is not being used in the Spring Boot code base, so it might be good to remove Http401AuthenticationEntryPoint.

    Depending on your requirements, you could use:

    • HttpStatusEntryPoint
    • BasicAuthenticationEntryPoint
    0 讨论(0)
  • 2020-12-09 18:38

    Just to elaborate @lealceldeiro's answer:

    Before Spring Boot 2 my Securiy Configuration class looked like this:

    @Configuration
    public class MyConfig extends WebSecurityConfigurerAdapter {
    
        @Bean
        public Http401AuthenticationEntryPoint securityException401EntryPoint() {
          return new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"");
        }
    
        @Autowired
        private Http401AuthenticationEntryPoint authEntrypoint;
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
          // some http configuration ...
    
          // Spring Boot 1.5.x style
          http.exceptionHandling().authenticationEntryPoint(authEntrypoint);
        }
    //...
    }
    

    And now in Spring Boot 2 it looks like this:

    @Configuration
    public class MyConfig extends WebSecurityConfigurerAdapter {
    
        //Bean configuration for Http401AuthenticationEntryPoint can be removed
    
        //Autowiring also removed
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
    
          // some http configuration ...
    
          // Spring Boot 2 style
          http.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
        }
    //...
    }
    

    See also this comment in Spring Boot Github Repo > PR Remove Http401AuthenticationEntryPoint.

    0 讨论(0)
提交回复
热议问题