Java for Beginner
706 subscribers
614 photos
166 videos
12 files
963 links
Канал от новичков для новичков!
Изучайте Java вместе с нами!
Здесь мы обмениваемся опытом и постоянно изучаем что-то новое!

Наш YouTube канал - https://www.youtube.com/@Java_Beginner-Dev

Наш канал на RUTube - https://rutube.ru/channel/37896292/
Download Telegram
Настройка кастомных страниц ошибок в Spring Security

Spring Security позволяет заменить стандартные страницы ошибок на пользовательские. Это улучшает пользовательский опыт и делает интерфейс приложения более профессиональным.

1. Общие страницы ошибок Spring Security

По умолчанию Spring Security использует встроенные страницы ошибок:
401 Unauthorized: для неудачной аутентификации.
403 Forbidden: для попыток доступа без соответствующих прав.


Эти страницы достаточно просты и не подходят для продакшн-приложений. Их можно заменить на кастомные.

2. Подходы к настройке кастомных страниц ошибок

Использование обработчиков (handler):

Настройка обработчиков AuthenticationEntryPoint и AccessDeniedHandler для возврата кастомных страниц.

Глобальная обработка исключений:
Настройка глобального обработчика через @ControllerAdvice.

Перенаправление на HTML-страницы:
Использование механизма перенаправления на заранее подготовленные HTML-страницы.

3. Настройка кастомных страниц ошибок в Spring Security

3.1 Замена страницы для ошибки 403 (Forbidden)
Настраиваем кастомный AccessDeniedHandler:
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.stereotype.Component;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

@Override
public void handle(HttpServletRequest request, HttpServletResponse response,
AccessDeniedException accessDeniedException) throws IOException {
// Перенаправление на кастомную страницу
response.sendRedirect("/error/403");
}
}


Добавляем обработчик в конфигурацию Spring Security:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

private final CustomAccessDeniedHandler accessDeniedHandler;

public SecurityConfig(CustomAccessDeniedHandler accessDeniedHandler) {
this.accessDeniedHandler = accessDeniedHandler;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler); // Подключение кастомного обработчика

return http.build();
}
}


Создаем контроллер для обработки ошибок:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class ErrorController {

@GetMapping("/error/403")
public String error403() {
return "error/403"; // Возвращаем HTML-страницу
}
}


Добавляем страницу src/main/resources/templates/error/403.html (например, для Thymeleaf):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Access Denied</title>
</head>
<body>
<h1>403 - Access Denied</h1>
<p>Sorry, you don't have permission to access this page.</p>
</body>
</html>


#Java #Training #Spring #Security #Security_Exceptions
👍1
3.2 Замена страницы для ошибки 401 (Unauthorized)

Настраиваем кастомный AuthenticationEntryPoint:

import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendRedirect("/error/401");
}
}


Добавляем обработчик в конфигурацию Spring Security:
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(customAuthenticationEntryPoint); // Подключение кастомного обработчика

return http.build();
}


Создаем контроллер для обработки ошибок:
@Controller
public class ErrorController {

@GetMapping("/error/401")
public String error401() {
return "error/401"; // Возвращаем HTML-страницу
}
}


Создаем страницу src/main/resources/templates/error/401.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Unauthorized</title>
</head>
<body>
<h1>401 - Unauthorized</h1>
<p>Please log in to access this page.</p>
</body>
</html>


4. Обработка всех ошибок через глобальный контроллер

Если нужно обрабатывать все исключения централизованно, можно использовать @ControllerAdvice:
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalErrorController {

@ExceptionHandler(AccessDeniedException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public String handleAccessDeniedException() {
return "error/403";
}

@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public String handleAuthenticationException() {
return "error/401";
}
}


#Java #Training #Spring #Security #Security_Exceptions
👍1
5. Использование встроенного механизма Spring Boot для ошибок

Spring Boot предоставляет удобный способ настройки кастомных страниц через файл application.properties:
server.error.whitelabel.enabled=false
server.error.path=/error


Затем создаем контроллер для обработки пути /error:
@Controller
public class CustomErrorController {

@GetMapping("/error")
public String handleError() {
return "error/custom";
}
}


Добавляем страницу src/main/resources/templates/error/custom.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Error</title>
</head>
<body>
<h1>An error occurred</h1>
<p>We are sorry, something went wrong.</p>
</body>
</html>


6. Обработка JSON-ответов для API

Для REST API ошибки обычно возвращаются в формате JSON. Пример глобального обработчика для API:
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class ApiErrorController {

@ExceptionHandler(AccessDeniedException.class)
public ResponseEntity<?> handleAccessDeniedException(AccessDeniedException ex) {
return ResponseEntity.status(HttpStatus.FORBIDDEN).body(Map.of(
"error", "Forbidden",
"message", ex.getMessage()
));
}
@ExceptionHandler(AuthenticationException.class)
public ResponseEntity<?> handleAuthenticationException(AuthenticationException ex) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of(
"error", "Unauthorized",
"message", ex.getMessage()
));
}
}


#Java #Training #Spring #Security #Security_Exceptions
👍1