У меня есть REST API и я хочу защитить его с помощью Spring Security. Я следовал за учебником здесь: https://github.com/Zuehlke/springboot-sec-tutor
Весь мой проект можно найти здесь: https://github.com/YanickSchraner/wodss-tippspiel_backend
Проблема, с которой я сталкиваюсь, заключается в том, что @AuthenticationPrincipal возвращает Null даже после успешного выполнения POST-запроса входа в систему. Я предполагаю, что из-за этого аннотация @PreAuthorized тоже не работает.
Вот мой Конфигурация Безопасности:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private RESTAuthenticationSuccessHandler restAuthenticationSuccessHandler;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private AuthenticationManager authenticationManager;
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception{
return super.authenticationManager();
}
@Bean
public RESTAuthenticationFilter restAuthenticationFilter() {
RESTAuthenticationFilter restAuthenticationFilter = new RESTAuthenticationFilter(objectMapper);
restAuthenticationFilter.setAuthenticationManager(authenticationManager);
restAuthenticationFilter.setAuthenticationSuccessHandler(restAuthenticationSuccessHandler);
return restAuthenticationFilter;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and().anonymous().disable()
.csrf().disable() // CSRF protection is done with custom HTTP header (OWASP suggestion)
.addFilterBefore(new XRequestedWithHeaderFilter(), CsrfFilter.class)
.addFilterBefore(new EnforceCorsFilter(), CsrfFilter.class)
.addFilterBefore(restAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.logout().logoutSuccessHandler((request, response, authentication) -> response.setStatus(HttpServletResponse.SC_OK))
.and()
.headers()
.frameOptions().sameOrigin()
.contentSecurityPolicy("default-src 'self'; script-src 'self' 'unsafe-inline'; report-uri /csp")
.and()
.httpStrictTransportSecurity()
.maxAgeInSeconds(63072000);
http
.logout()
.logoutUrl("/logout")
.invalidateHttpSession(true)
.deleteCookies("BettingGame_SchranerOhmeZumbrunn_JSESSIONID");
http
.sessionManagement()
.sessionFixation()
.newSession();
}
}
Вот мой UserDetailsServiceImpl:
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Value("${security.login.errormessage}")
private String errorMessage;
@Override
@Transactional(readOnly = true)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findUserByNameEquals(username)
.orElseThrow(() -> new UsernameNotFoundException(errorMessage));
HashSet<GrantedAuthority> authorities = new HashSet<>();
if(user.getRoles() != null){
user.getRoles().stream()
.map(Role::getName)
.map(SimpleGrantedAuthority::new)
.forEach(authorities::add);
}
return new org.springframework.security.core.userdetails.User(user.getName(),user.getPassword(), authorities);
}
}
Вот часть моего контроллера, где я получаю Null от @AuthenticationPricipal, а @PreAuthorized возвращает 403 даже после успешного входа в систему:
@RestController
@RequestMapping("/users")
//@PreAuthorize("hasRole('USER')")
public class UserController {
private final UserService service;
@RequestMapping(value = "/self",method = RequestMethod.GET)
public ResponseEntity<User> getLogedInUser(@AuthenticationPrincipal User user){
return new ResponseEntity<>(user, HttpStatus.OK);
}
@Autowired
public UserController(UserService service) {
this.service = service;
}
@GetMapping(produces = "application/json")
@PreAuthorize("hasRole('USER')")
public ResponseEntity<List<User>> getAllUsers() {
return new ResponseEntity<>(service.getAllUsers(), HttpStatus.OK);
}