I am using following code in my controller to display a custom error page in the application:
@GetMapping(path="/error")
public ModelAndView error (Principal principal) {
ModelAndView model = new ModelAndView("error");
model.addObject("userName", principal.getName());
return model;
}
The principal is null when application is deployed as a WAR on stand-alone tomcat. When application is run with embedded tomcat, it works fine.
Comment From: wilkinsona
Thanks for the report. Can you please provide a minimal sample that reproduces the problem?
Comment From: ravi-dalal
myapp.zip Please find attached the sample code to reproduce the issue. Please follow these steps to reproduce:
- Deploy on tomcat (you can do it within Eclipse, I used Tomcat 9)
- Browse http://localhost:8080/myapp, Spring login page will prompt for login
- Login using credentials user/password
- After successful login, change url to http://localhost:8080/myapp/api/admin
- You will get null pointer exception for 'prinicipal' object
- the /api/** url can be accessed only by 'admin' user
- If you run this application as a simple Java application (using embedded Tomcat), you will see the error page when trying to access /api/admin url while logged in as 'user'.
Comment From: wilkinsona
Thanks for the sample.
When you deploy your application to a container, Spring Boot has to use a filter to forward errors to its custom error page support. This is necessary as the Servlet spec does not include an API for error page registration. By default, Spring Security's filter only runs async, error, and request dispatches. This means that it does not get involved when the error page filter forwards the request to the custom error page support. You can change this by setting the spring.security.filter.dispatcher-types property to async, error, forward, request. Doing so in your sample fixes the problem.
We should add something to the documentation about this. We can use this issue to do that.
Comment From: ravi-dalal
Yes, it resolves the issue. Thanks for your help.