简体   繁体   中英

Spring Boot with Spring Security returns 404 on valid login

When I activate Spring Security trough custom bean @PreAuthorize("@mySecurity.check(#car)") valid requests (check returns true) will end up in 404, and invalid requests will end up in 200. Without the PreAuthorize all works fine.

The authorisation is done via JWT, and the granted authorities are set correctly.

When I step through the debugger, the PreAuthorize check works correctly returning true or false.

I have the following enabled:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

The Rest controller implements the Method with the following annotation

    @PreAuthorize("@mySecurity.check(#car)")
    public List<Driver> getAllVersions(String car) {

A Request without security check would look like

2019-09-30 13:34:22.306 DEBUG 26204 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : Completed 200 OK
2019-09-30 13:34:42.042 DEBUG 26204 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : GET "/api/v1/car/foobar", parameters={}
...
2019-09-30 13:34:42.049 DEBUG 26204 --- [nio-8080-exec-4] m.m.a.RequestResponseBodyMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2019-09-30 13:34:42.050 DEBUG 26204 --- [nio-8080-exec-4] m.m.a.RequestResponseBodyMethodProcessor : Writing [{
  "id": "hi",
  "name": "hi",
  "isActive": false
}]
2019-09-30 13:34:42.052 DEBUG 26204 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet        : Completed 200 OK

When activating PreAuthorize and doing a valid request, it seems to work partial.

2019-09-30 13:44:22.597 DEBUG 7400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : GET "/api/v1/car/foobar", parameters={}
...
2019-09-30 13:44:28.912 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected '*/*' given [*/*]
2019-09-30 13:44:28.938 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView  : View name '/api/v1/car/foobar2', model {configurationVersionList=[{
  "id": "bar",
  "name": "bar",
  "isActive": false
}, {
  "id": "foo",
  "name": "foo",
  "isActive": false
}]}
2019-09-30 13:44:28.946 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView  : Forwarding to [api/v1/car/foobar2]
2019-09-30 13:44:28.950 DEBUG 7400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "FORWARD" dispatch for GET "/api/v1/car/foobar2/api/v1/car/foobar2", parameters={}
2019-09-30 13:44:28.959 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped to ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]
2019-09-30 13:44:28.963 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler     : Resource not found
2019-09-30 13:44:28.963 DEBUG 7400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "FORWARD" dispatch, status 404
2019-09-30 13:44:28.970 DEBUG 7400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Completed 404 NOT_FOUND
2019-09-30 13:44:28.981 DEBUG 7400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : "ERROR" dispatch for GET "/error", parameters={}
2019-09-30 13:44:28.984 DEBUG 7400 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
2019-09-30 13:44:29.000 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
2019-09-30 13:44:29.001 DEBUG 7400 --- [nio-8080-exec-1] o.s.w.s.m.m.a.HttpEntityMethodProcessor  : Writing [{timestamp=Mon Sep 30 13:44:28 CEST 2019, status=404, error=Not Found, message=No message available, (truncated)...]
2019-09-30 13:44:29.027 DEBUG 7400 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : Exiting from "ERROR" dispatch, status 404 

If I do an not allowed Request, I receive a 200:

2019-09-30 13:45:53.514 DEBUG 7400 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : GET "/api/v1/car/%7Bfoobar%7D", parameters={}
...
2019-09-30 13:45:55.660 DEBUG 7400 --- [nio-8080-exec-3] o.s.b.a.audit.listener.AuditListener     : AuditEvent [timestamp=2019-09-30T11:45:55.660Z, principal=JohnDoe, type=AUTHORIZATION_FAILURE, data={details={... snip ...}]
2019-09-30 13:45:55.661 DEBUG 7400 --- [nio-8080-exec-3] o.s.web.servlet.DispatcherServlet        : Failed to complete request: org.springframework.security.access.AccessDeniedException: Zugriff verweigert

pom.xml

...
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.8.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
...
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web-services</artifactId>
            </dependency>
            <!-- Security  -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>

As requested:

@Component
public class MySecurity {

    public boolean check(String car) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        List<String> givenpermissions = auth.getAuthorities().stream().map(x -> (GrantedAuthority) x)
                .map(GrantedAuthority::getAuthority).filter(authority -> authority.startsWith("car-holder-"))
                .collect(Collectors.toList());
        return !givenpermissions.isEmpty();
    }


}

The endpoint should just verify the JWT (working), ensure the permissions and then return a json answer.

I've currently now Idea what the issue could be, so any approach is welcome..

SOLUTION

removed the interface

is your Controller annotated with @RestController ? if not you'll need @ResponseBody annotation on your method

@PreAuthorize("@mySecurity.check(#car)")
@ResponseBody
public List<Driver> getAllVersions(String car) {

Without this spring tries to load the actual view which is not present - 404

Or missing PathParam annotation

public List<Driver> getAllVersions(@PathParam("ParamName") String car)

I had some issues in the past with annotations on implemented interfaces instead on the class directly. PreAuthorize does some extra "magic", just an idea

try to put @ResponeBody for the method in controller class

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM