Я хочу иметь возможность включать некоторую информацию о сотрудниках в мой объект org.springframework.security.core.userdetails.User
, поэтому я расширил класс User
и добавил данные о сотрудниках.Все это работало хорошо, но затем я хотел ограничить данные из класса Employee
только тем, что было необходимо для аспекта пользователя / авторизации.Чтобы сделать это, я внес изменения в свою реализацию обработчика успеха аутентификации.
Итак, вот часть моей конфигурации веб-безопасности:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
public UserDetailsService userDetailsService() {
return new UserDetailsServiceImpl();
};
@Autowired
private AuthSuccessHandler authSuccessHandler;
@Autowired
private AuthLogoutSuccessHandler authLogoutSuccessHandler;
@Autowired
private AuthFailureHandler authFailureHandler;
@Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.formLogin()
.loginProcessingUrl("/api/dologin")
.usernameParameter("username").passwordParameter("password")
.successHandler(authSuccessHandler).failureHandler(authFailureHandler)
.and()
...
}
}
В обработчике успеха аутентификации я теперьhave:
@Component
public class AuthSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
private final ObjectMapper mapper;
AuthSuccessHandler(@Qualifier("mappingJackson2HttpMessageConverter") MappingJackson2HttpMessageConverter messageConverter) {
this.mapper = messageConverter.getObjectMapper().setConfig(messageConverter.getObjectMapper().getSerializationConfig().withView(View.LoginView.class));
// old mapper config: this.mapper = messageConverter.getObjectMapper();
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_OK);
PrintWriter writer = response.getWriter();
mapper.writeValue(writer, authentication.getPrincipal());
writer.flush();
}
}
Немного потрудившись (пришлось выполнить новую реализацию GrantedAuthority
и т. д.), после успешного входа в систему я смог получить только те данные, которые хотел видеть в JSON..
Недостатком является то, что теперь для любых других конечных точек REST мне нужно указать какой-то JsonView для возврата любых данных.Это не обязательно должен быть LoginView, но он должен что-то иметь, или я получаю {}
в качестве JSON для любой конечной точки.Как только я указываю что-либо (@JsonView(View.Anything.class
) в контроллере (и, конечно, также в доменных объектах), тогда данные появляются, как и ожидалось.
Хуже того, когда я пытаюсьполучить информацию java.security.Principal
У меня есть RestController с этим:
@RequestMapping("/api/user-principal")
public Principal user(Principal user) {
return user;
}
С этой конкретной конечной точкой даже добавление аннотации @JsonView не помогает, предположительно потому, что Principal
является интерфейсом, и поэтому нет свойств, которые имеют правильное представление,Я мог бы создать свою собственную реализацию Principal, а затем указать, какие свойства я хочу вернуть, но это не выглядит ожидаемым поведением.
Почему изменение конфигурации сопоставления в обработчике успеха аутентификации оказывает влияниегде-либо еще?Какой самый лучший и простой способ справиться с этим?