Reputation: 13
I'm working on a small project including web using react and rest api using spring data rest which all packaged in a jar. The web and api are all protected by Spring Security, default configuration for form login, and using @PreAuthorize annotation like @PreAuthorize("hasRole('ADMIN')") on repository methods. After login, if the user has the permission, everything is fine; but if not, the request will wait a long time (minutes), and return http status 26.
Spring Boot version is 2.7.0
I've tried using spring-session-jdbc and X-Auth-Token header, but still the same.
Security configurations:
@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;
}
}
the repository endpoint:
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);
the test request and response header:
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
I FOUND the problem, I configured a global Exception Handler to deal with AccessDeniedException but forget why, and it cause the problem. After removing that config, response became normal 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());
}
...
}
Upvotes: 1
Views: 336
Reputation: 1590
HttpStatus is an enum and you are using HttpStatus.FORBIDDEN.ordinal(). The ordinal method in Enum returns the position in the enum declaration. Remove ordinal() and it should work.
Below you can see the code inside HttpStatus enum and it's the 26th item in the enum declaration.
Upvotes: 0