Так что я пытаюсь сделать логин отдыхающим, и все идет хорошо, ожидая одного.После успешного входа в систему и пользователь имеет доступ к ссылкам, которые не должны иметь.Я предполагаю, что есть что-то плохое в методе "configure" в классе extends WebSecurityConfigurerAdapter, потому что hasAuthority не работает должным образом.Пожалуйста, ребята, просмотрите мой код и скажите, как он должен выглядеть.
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class Security extends WebSecurityConfigurerAdapter {
private final Provider provider;
private final EntryPoint entryPoint;
private final CorsFilter corsFilter;
@Autowired
public Security(Provider provider, EntryPoint entryPoint, CorsFilter corsFilter) {
this.provider = provider;
this.entryPoint = entryPoint;
this.corsFilter = corsFilter;
}
@Bean
public BCryptPasswordEncoder passwordEncoder() {
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
return bCryptPasswordEncoder;
}
@Bean
public AuthenticationManager authenticationManager() {
return new ProviderManager(Collections.singletonList(provider));
}
public AuthenticationTokenFilter authenticationTokenFilter() {
AuthenticationTokenFilter filter = new AuthenticationTokenFilter();
filter.setAuthenticationManager(authenticationManager());
filter.setAuthenticationSuccessHandler(new SuccessHandler());
return filter;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
String roleAdmin = "Admin";
http.authorizeRequests()
.antMatchers("/api/**").authenticated()
.antMatchers(HttpMethod.GET, "/api/office").hasAnyAuthority()
.antMatchers(HttpMethod.GET, "/user").hasAnyAuthority()
.antMatchers(HttpMethod.GET, "/userDetails/**").hasAnyAuthority()
.antMatchers("/api/office/admin").hasAuthority(roleAdmin)
.antMatchers("/api/office/user").hasAuthority(roleAdmin)
.antMatchers("/api/office/roleadmin").hasRole(roleAdmin)
.antMatchers("/api/office/roleuser").hasRole(roleAdmin)
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.exceptionHandling().authenticationEntryPoint(entryPoint)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.addFilterBefore(corsFilter, ChannelProcessingFilter.class)
.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class)
.headers()
.cacheControl();
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/login");
}
}
Класс CorsFilter
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter {
public CorsFilter() {
super();
}
@Override
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
// without this header jquery.ajax calls returns 401 even after successful login and session being successfully stored.
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Origin, Content-Type, Version");
response.setHeader("Access-Control-Expose-Headers", "X-Requested-With, Authorization, Origin, Content-Type");
final HttpServletRequest request = (HttpServletRequest) servletRequest;
if (!request.getMethod().equals("OPTIONS")) {
filterChain.doFilter(servletRequest, servletResponse);
}
}
Дополнительный класс фильтра токенов
public class AuthenticationTokenFilter extends AbstractAuthenticationProcessingFilter {
public AuthenticationTokenFilter() {
super("/api/**");
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
String header = request.getHeader(SecurityClaims.HEADER);
if (header == null || !header.startsWith(SecurityClaims.TOKEN_PREFIX)) {
throw new RuntimeException(SecurityClaims.TOKEN_MISSING);
}
String authenticationToken = header.substring(SecurityClaims.SUB_PREFIX);
AuthenticationToken token = new AuthenticationToken(authenticationToken);
return getAuthenticationManager().authenticate(token);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}
}
Контроллер для теста
@CrossOrigin
@RestController
@RequestMapping("/api/office")
public class OfficeController {
private final OfficeService officeService;
@Autowired
public OfficeController(OfficeService officeService) {
this.officeService = officeService;
}
@GetMapping("/admin")
public @ResponseBody
String adminek() {
return "for authority admin";
}
@GetMapping("/user")
public @ResponseBody
String userek() {
return "for authority user";
}
@GetMapping("/roleadmin")
public @ResponseBody
String roleadmin() {
return "for role admin";
}
@GetMapping("/roleuser")
public @ResponseBody
String roleuser() {
return "for role user";
}
}
Точка входа
@Component
public class EntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, SecurityClaims.MESSAGE);
}
}