当我使用Spring Method Security @PreAuthorize("hasRole('MODERATOR')")
如果用户尝试访问需要“MODERATOR”角色的控制器,则返回资源,一切正常(如果用户实际上具有该角色)。但是,如果用户没有此角色,则服务器返回404 - Not Found。这很奇怪,因为我希望服务器会返回其他东西,也许403 Forbidden?知道为什么会这样吗?这是我的安全配置:
@EnableWebSecurity
@Order(2)
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserDetailsService userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurity(UserDetailsService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
super();
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()))
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Bean
CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.applyPermitDefaultValues();
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
}
和我的控制员:
@GetMapping
@PreAuthorize("hasRole('MODERATOR')")
public List<ApplicationUser> getAllUsers(HttpServletRequest request) {
try (final ConnectionResource connectionResource = connectionFactory.create(); final UserDAO dao = new UserDAO()) {
dao.setEm(connectionResource.em);
return dao.getAllUsers();
} catch (Exception ex) {
Logger.getLogger(UserController.class.getName()).log(Level.SEVERE, "unable to get all users", ex);
return null;
}
}
谢谢!
答案 0 :(得分:2)
可以在注释@EnableGlobalMethodSecurity(prePostEnabled=true)
的帮助下启用全局方法安全性。此和@Preauthorize
的组合将为您的控制器创建一个新的代理,并将释放请求映射(在您的情况下为GetMapping),这将导致404异常。
要处理此问题,您可以使用@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
答案 1 :(得分:1)
我们需要为使用@PreAuthorize注释启用全局方法安全性。例如https://dzone.com/articles/securing-spring-data-rest-with-preauthorize
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true)
@Order(2)
public class WebSecurity extends WebSecurityConfigurerAdapter {
..............
}
答案 2 :(得分:0)
以下是我执行此操作的代码: -
@Override
protected void configure(HttpSecurity http) throws Exception{
http.authorizeRequests()
.antMatchers(HttpMethod.POST,"/api/2.0/login/**").permitAll()
.anyRequest().authenticated()
.and().exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint())
.and()
.addFilterBefore()
}
@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return new RestAuthenticationEntryPoint();
}
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{
private static Logger logger = Logger.getLogger(RestAuthenticationEntryPoint.class);
public RestAuthenticationEntryPoint() {
super();
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException, ServletException {
logger.info("Inside Rest Authentication entry Points");
String error="{ \"status\":\"FAILURE\",\"error\":{\"code\":\"401\",\"message\":\""+authException.getMessage()+"\"} }";
HttpServletResponse httpResponse = (HttpServletResponse) response;
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResponse.setContentType("application/json");
if(authException instanceof BadCredentialsException){
httpResponse.getOutputStream().println("{ \"Bad credential\": \"" + authException.getMessage() + "\" }");
}
if(authException instanceof AuthenticationCredentialsNotFoundException){
logger.info("Inside AuthenticationCredentialsNotFoundException");
error="{ \"status\":\"FAILURE\",\"error\":{\"code\":\""+SecurityExceptions.TOKEN_EXPIRED+"\",\"message\":\""+SecurityExceptions.TOKEN_EXPIRED_MESSAGE+"\"} }";
}
httpResponse.getOutputStream().println(error);
}
}