Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle HTTP 403 with Spring Security 3.0.x

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 doesn't have the authorities tries to log on.

When it occurs, the users is redirected to the "welcome" page, since his username/password are valid, and he receive a cute white page with this : "Error 403: Access is denied"

So, I've been looking on the net trying to find how this behavior can be handled. So far I've come to the conclusion, please correct me if I'm wrong, that it is managed by the ExceptionTranslationFilter. But I don't quite understand how to make any good use of this information.

I've tryied to edit my SecurityContext.xml to add a access-denied-handler tag to my http tag, but it doesn't work. Do I need to add more than this tag to make it work? Is there any other possibilities to make my application more user-friendly?

Edit : I would like to redirect to a page, let's says 403.html, for example.

Sincerly,
Thanks

like image 515
ALOToverflow Avatar asked Nov 15 '10 16:11

ALOToverflow


People also ask

How do I fix 403 Forbidden in Java?

Double Check the Address. The most common reason for a 403 error is a mistyped URL. First, ensure that the address you are trying to access is for a web page or file, not a directory. For example, a regular URL would end in .com, .


2 Answers

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
                }
            });
        }
    };
}

}

like image 62
Aubergine Avatar answered Sep 20 '22 12:09

Aubergine


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.

like image 34
Kristen D. Avatar answered Sep 22 '22 12:09

Kristen D.