我正在做一个小项目,包括使用react的web和使用spring data rest的rest api,它们都打包在一个jar中。web和api都受到Spring Security的保护,表单登录的默认配置,以及在仓库方法上使用@ PreAuthorize(“hasRole('ADMIN')”)这样的@PreAuthorize注解。登录后,如果用户有权限,一切都很好;但如果不是,则请求将等待很长时间(几分钟),并返回HTTP状态26。
Sping Boot 版本为2.7.0
我尝试过使用spring-session-jdbc和X-Auth-Token头,但还是一样。
安全配置:
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests().anyRequest().authenticated()
.and()
.csrf().disable()
.cors(Customizer.withDefaults())
.formLogin();
return http.build();
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.addAllowedHeader("*");
configuration.addAllowedMethod("*");
configuration.addAllowedOrigin("*");
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/api/**", configuration);
return source;
}
}
存储库端点:
public interface UserRepository extends JpaRepository<User, String> {
@PreAuthorize("hasRole('ADMIN')")
<S extends User> S save(User u);
@PreAuthorize("hasRole('USER')")
List<User> findByNameContains(String name);
测试请求和响应报头:
curl -X POST -H 'Content-Type: application/json; charset=utf8;' -i 'http://xxxxxxxxxxxx:8080/api/users' --data '{
"username": "john.m",
"name": "John Murdoch"
}'
# response header
Status Code: 26
access-control-allow-origin: *
cache-control: no-cache, no-store, max-age=0, must-revalidate
connection: keep-alive
date: Mon, 10 Oct 2022 00:58:34 GMT
expires: 0
keep-alive: timeout=60
pragma: no-cache
vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
x-content-type-options: nosniff
x-frame-options: DENY
x-xss-protection: 1; mode=block
我发现了这个问题,我配置了一个全局异常处理程序来处理AccessDeniedException,但是忘记了原因,它导致了这个问题。删除该配置后,响应变得正常403。
@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({ AccessDeniedException.class })
public ResponseEntity<Object> handleAccessDeniedException(Exception ex, WebRequest request) {
return new ResponseEntity<Object>(
ex.getLocalizedMessage(),
new HttpHeaders(),
HttpStatus.FORBIDDEN.ordinal());
}
...
}
1条答案
按热度按时间r3i60tvu1#
HttpStatus是一个枚举,而您使用的是HttpStatus.FORBIDDEN.ordinal()。Enum中的ordinal方法返回枚举声明中的位置。删除ordinal(),它应该可以工作。
下面您可以看到HttpStatus枚举中的代码,它是枚举声明中的第26项。