#spring #spring-boot #spring-security
#spring #spring-boot #spring-security
Вопрос:
В моем веб-приложении spring boot я обращаюсь за авторизацией к сторонней службе, а мое приложение является всего лишь поставщиком контента. Родительское приложение использует site minder для аутентификации. Мое приложение получает идентификатор пользователя в заголовке и вызывает сторонний API для настройки пользовательских данных с полномочиями.
Мое требование — обработать сценарий, когда сторонняя служба авторизации отключена. В настоящее время в этом случае я устанавливаю пользовательские параметры без ролей, и поскольку каждая конечная точка привязана к авторизации, я получаю 403, если сторонняя служба авторизации отключена.
Но я хочу отобразить другое сообщение, если пользователю не хватает авторизации и если служба авторизации отключена.
Если я обрабатываю отключение службы авторизации путем создания пользовательского исключения из UserDetailsServiceImpl -> loadUserByUsername(), тогда RequestHeaderAuthenticationFilter обнаруживает это исключение, и запрос отфильтровывается. Есть идеи, как это сделать?
SecurityConfiguration
public class WebSecurityCustomConfig extends WebSecurityConfigAdapter {
private UserDetailsService userDetails;
protected void configure(HttpSecurity http) {
http.csrf().disable().authorizeRequests().antMatchers("/*).permitAll()
.anyRequests()
.hasAnyAuthority("MODULEX","MODULEY");
http.addFilterBefore(requestHeaderAuthFilter(),
BasicAuthenticationFilter.class);
http.exceptionHandling().authenticationEntryPoint(customEntryPoint());
}
protect void configure(AuthenticationManagerBuilder builder) {
PreAuthenticaticatedAuthenticationProvider auth = new
PreAuthenticaticatedAuthenticationProvider ();
auth.setPreAuthenticatedUserDetailsService(new
UserDetailsByNameServiceWrapper<>(userDetails));
}
}
Пользовательский UserDetailsService
public class CustomUserDetailsService implements UserDetailsService {
private final AuthorizationService authService;
@Inject
public CustoUserDetailsService(AuthorizationService authService) {
this.authService = authService;
}
public UserDetails loadUserByUsername(String username) {
return new User(username, "",
authService.getAuthorities(username));
// authService is a third party jar and if their upstream service
//is down , it throws a runtime exception
}
}
Если я обработаю их ошибку следующим образом, то в итоге получу 403, но я хочу 503 в случае, если служба отключена, и 403, если у пользователя нет правильных полномочий для конечной точки, к которой он обращается.
текущая обработка исключения службы авторизации
public UserDetails loadUserByUsername(String username) {
try{
return new User(username, "",
authService.getAuthorities(username));
}
catch(AuthServiceException e) {
return new User(username, "",
Collections.emptyList());
}
}
Комментарии:
1. Если я создаю исключение из userdetailsservice вместо обработки, то оно не попадает в CustomauthenticationEntryPoint, который можно использовать для получения соответствующего ответа в случае отключения службы
2. в приведенной выше реализации пользователь без полномочий и при авторизации видит ту же ошибку, которая неверна
Ответ №1:
Реализуйте AuthenticationEntryPoint
и переопределяйте commence()
метод следующим образом.
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
И после этого создайте в своем WebSecurityCustomConfig
классе метод, который инициализирует RestAuthenticationEntryPoint
класс следующим образом.
public AuthenticationEntryPoint authenticationEntryPoint() {
RestAuthenticationEntryPoint ep = new RestAuthenticationEntryPoint();
return ep;
}
Затем измените следующую строку на http.exceptionHandling().authenticationEntryPoint(customEntryPoint());
Для
http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint());