Reputation: 111
I am working on spring boot application and JSP. I want to display custom styled 404 error page when a user hits some different URLs like https://www.example.com/about/random-unauthorized-url so, https://www.example.com/about is a valid URL but https://www.example.com/about/random-unauthorized-url is not a valid URL. So I want when this thing happens, 404 page should get displayed instead of redirection on home page. Current scenario is when I supply some invalid URLs with domain name, it gets redirected to index or home page, which I don't want. So I tried using some properties in application.yml file as below:
server:
port: 1207
error:
whitelabel:
enabled: false
spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration
Below is custom security configuration
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
.httpBasic().disable()
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers(WebUrl.index).permitAll()
.antMatchers(WebUrl.about).permitAll()
.antMatchers(WebUrl.pageNotFound).permitAll()
.antMatchers("/error").permitAll().anyRequest().authenticated().and()
.apply(new JwtConfigurer(jwtTokenProvider));
http.exceptionHandling().authenticationEntryPoint(unauthenticatedRequestHandler());
http.exceptionHandling().accessDeniedPage("/403");
http.exceptionHandling().authenticationEntryPoint(unauthenticatedRequestHandler());
}
@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return (request, response, authException) -> response.sendRedirect("/login");
}
@Bean
UnauthenticatedRequestHandler unauthenticatedRequestHandler() {
return new UnauthenticatedRequestHandler();
}
}
This is to handle unauthenticated requests
public class UnauthenticatedRequestHandler implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
System.out.println("Request coming here....!!! "+request.getServletPath());
if(request.getServletPath().startsWith("/admin/")) {
response.sendRedirect("/admin/login");
}else {
response.sendRedirect("/");
}
}
}
and created custom error handling controller also
@Controller
public class CustomErrorController implements ErrorController{
@Override
public String getErrorPath() {
return WebUrl.pageNotFound;
}
@RequestMapping(value= {WebUrl.pageNotFound},method= {RequestMethod.GET,RequestMethod.POST})
public ModelAndView handleError(HttpServletRequest request) {
ModelAndView modelAndView = null;
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if(status != null) {
Integer statusCode = Integer.valueOf(status.toString());
if(statusCode == HttpStatus.NOT_FOUND.value()) {
modelAndView = new ModelAndView(WebUrl.pageNotFound);
}
}
return modelAndView;
}
}
Below is the structure of view:
src/main/webapp/views/page-not-found.jsp
Unfortunately, above solutions did not worked for me or maybe I mixed things. Please help me on this to solve.
Upvotes: 3
Views: 3355
Reputation: 158
Write @RequestMapping("/error") for handleError method.
Look at below code:
@Controller
public class CustomErrorController implements ErrorController {
@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
//Log here !!!
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
int statusCode = Integer.parseInt(status.toString());
if (statusCode == HttpStatus.NOT_FOUND.value()) {
return "404";
} else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return "500";
} else if (statusCode == HttpStatus.FORBIDDEN.value()) {
return "403";
}
}
return "generalError";
}
@Override
public String getErrorPath() {
return "/error";
}
}
and look at 404.html file location in project structure.
Upvotes: 0
Reputation: 53411
The Spring Boot documentation provides a section talking about custom error pages. It states:
If you want to display a custom HTML error page for a given status code, you can add a file to an /error directory. Error pages can either be static HTML (that is, added under any of the static resource directories) or be built by using templates. The name of the file should be the exact status code or a series mask.
For example, to map
404
to a static HTML file, your directory structure would be as follows:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- public/
+- error/
| +- 404.html
+- <other public assets>
To map all
5xx
errors by using a FreeMarker template, your directory structure would be as follows:
src/
+- main/
+- java/
| + <source code>
+- resources/
+- templates/
+- error/
| +- 5xx.ftlh
+- <other templates>
It provides further advice about using ErrorViewResolver
, @ExceptionHandler
s or @ControllerAdvice
, but for your use case I think providing a custom 404.jsp
file could do the trick.
In fact, I must say sorry, because I realized you are possibly not using Spring in this way, but with a webapp
related structure.
If that is the case, one direct approach you could follow is the aforementioned based on @ExceptionHandler
and @ControllerAdvice
. Please, try creating a custom exception handler similar to this:
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;
@ControllerAdvice
public class CustomExceptionHandler {
@ExceptionHandler(NoHandlerFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public ModelAndView handleNoHandlerFoundException (NoHandlerFoundException e) {
// Consider logging the error
return new ModelAndView("page-not-found.jsp");
}
}
For this code to work properly, you need to configure Spring to raise NoHandlerFoundException
when no handler is found.
You can do this for example by setting the configuration property spring.mvc.throw-exception-if-no-handler-found to true
:
spring.mvc.throw-exception-if-no-handler-found=true
Upvotes: 1
Reputation: 106
Did you try implementing the spring ErrorController ? Using this, you can have specific error pages for specific response status codes like '403' and '404'.
https://www.baeldung.com/spring-boot-custom-error-page
Upvotes: 0