How to handle HTTP 403 with Spring Security 3.0.x

前端 未结 5 1332
温柔的废话
温柔的废话 2021-02-04 09:44

I\'m facing a little issue with Spring Security 3.0.x (3.0.2 in particular at the moment). The whole application I\'m working on is working perfectly except when someone who doe

相关标签:
5条回答
  • 2021-02-04 10:12

    I still don't get why you had to implement your own access handler... I have currently faced same task:

     <security:access-denied-handler error-page="/accessDenied"/> - works like charm.
    

    Don't forget to specify handler in your Controller:

     @RequestMapping(value = "/accessDenied")
          public String accessDenied() {
    
                return "accessDenied"; // logical view name
           }
    

    Update for Spring Boot(2014 Oct):

    @Configuration
    @EnableWebSecurity
    public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.exceptionHandling().accessDeniedHandler(customHandler) OR .accessDeniedPage("/somePage.html").and
                .formLogin()
                    .failureHandler(ajaxAuthenticationFailureHandler)} 
    

    Nowadays we don't really return views for such task since angular js kicks in so you can use your failure/success handler and return tailored JSON responses. For us it was sufficient to use failure handler but you get to choose where you want your control to kick in. We generally don't use view resolvers as there are UI tiles frameworks(such as angular partials) able to construct pieces into single page for you. Html pieces are stored on the server and served simply as static resources.

    Lets play with Embedded Tomcat to achieve similar behavior to web.xml !

    @Configuration
    @EnableAutoConfiguration
    public class ApplicationWebXml extends SpringBootServletInitializer {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(Application.class);
    
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.profiles(addDefaultProfile())
                .showBanner(false)
                .sources(Application.class);
    }
    
    //required for container customizer to work, the numerous tutorials didn't work for me, so I simply tried overriding the default one
    @Bean
    public EmbeddedServletContainerFactory servletContainer() {
        TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
        return tomcat;
    }
    
    @Bean
    public EmbeddedServletContainerCustomizer containerCustomizer(
    
    ) {
        return new EmbeddedServletContainerCustomizer() {
            @Override
            public void customize(ConfigurableEmbeddedServletContainer container) {
                TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container;
                 containerFactory.setSessionTimeout(1); // just for your interest, remove as necessary
    
                containerFactory.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN,"/views/accessDenied.html"),
                        new ErrorPage(HttpStatus.NOT_FOUND,"/views/notFound.html"));
                containerFactory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
                    @Override
                    public void customize(Connector connector) {
                        connector.setPort(8082);// just for your interest, remove as necessary
                    }
                });
            }
        };
    }
    

    }

    0 讨论(0)
  • 2021-02-04 10:26

    A cleaner way to handle error redirects is to use the <error-page> and <error-code> tags in your web.xml. See below for an example:

    <!-- Custom 403 Error Page -->
    <!--
                NOTE: Security will throw this error when a user has been authenticated successfully
                but lacks the permissions to perform the requested action.
        -->
        <error-page>
            <error-code>403</error-code>
            <location>/403.jsp</location>
        </error-page>
    

    This block of code will redirect to the specified location whenever it encounters the specified error code.

    This eliminates the need for authorization code inside your application logic.

    0 讨论(0)
  • 2021-02-04 10:31

    You have checked the tag in an application and to me it seems to work.

    <sec:access-denied-handler error-page="/handle403Url" />
    

    where handle403Url I want to call to handle this error (for example to show an error).

    Don't forget that you have to allow this url in the filters so it can be reached by this user authority, so in the start of the flters you have to add something like this:

    <sec:intercept-url pattern="/handle403Url" filters="none" />
    
    0 讨论(0)
  • 2021-02-04 10:34

    I've found how to do this. By implementing the AccessDeniedHandler interface and the corresponding handle method I can, easily, control the way the Http 403 error is handled.

    This way, you can add various items in the session and then intercept them on your jsp.

    The xml file then looks like this :

    <sec:http>
        <!-- lots of urls here -->
        <sec:access-denied-handler ref="accessDeniedHandler" />
        <sec:anonymous/>
    </sec:http>
    
    <bean id="accessDeniedHandler" class="foo.bar.CustomAccessDeniedHandler">
        <property name="accessDeniedUrl" value="403.html" />
    </bean>
    

    The java class :

    package foo.bar;
    public class CustomAccessDeniedHandler implements org.springframework.security.web.access.AccessDeniedHandler {
    private String accessDeniedUrl;
    
        public CustomAccessDeniedHandler() {
        }
    
        public CustomAccessDeniedHandler(String accessDeniedUrl) {
            this.accessDeniedUrl = accessDeniedUrl;
        }
    
        public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
            response.sendRedirect(accessDeniedUrl);
            request.getSession().setAttribute("CustomSessionAttribute", "value here");
        }
    
        public String getAccessDeniedUrl() {
            return accessDeniedUrl;
        }
    
        public void setAccessDeniedUrl(String accessDeniedUrl) {
            this.accessDeniedUrl = accessDeniedUrl;
        }
    }
    

    And a jsp example :

    <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
     <c:if test="${!empty CustomSessionAttribute}">
        <br/>
        ACCESS IS DENIED
        <br/>
     </c:if>
    <!-- other stuff down here -->
    
    0 讨论(0)
  • 2021-02-04 10:36

    The way to make this work is to define a handler in your entry point:

    public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
        @Override
        public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException {
    
            if (authException != null) {
                // you can check for the spefic exception here and redirect like this
                response.sendRedirect("403.html");
            }
        }
    }
    

    You can define this as your entry point by setting this as you entry point in the xml config file:

    <http entry-point-ref="customAuthenticationEntryPoint">
    
      ...
    
    </http>
    
    0 讨论(0)
提交回复
热议问题