Spring - How to protect RESTful private resources?

2019-04-02 06:28发布

问题:

I've some RESTful services, implemented with Spring MVC, exposing a set of resources. I already use authentication, based on HTTPBasicAuthentication and HTTPS. Some of the resources must be accessible only to some users.

For example, I want that all sub-resources in the URI /users/{userid}/photos are accessible only to the user userid. Actually in my application they are accessible to all authenticated users. How can I protect them from other users except userid? And what if I want to allow access to this resources only to a subset of users (like, for example, userid's friends)?

回答1:

you could do something like this on your method:

    @ResponseBody
    @RequestMapping(value = "/users/{userid}/photos", method = RequestMethod.GET)
    @Secured(value = {"userid"})
    public ResponseEntity<ModelMap> getPhotos(....) throws Exception {

you can add more users if you want in the future by just doing

    @Secured(value = {"ROLE_ADMIN", "userid"})


回答2:

I would strongly suggest to use Spring Security. Using Spring security you can restrict access to a specific URL endpoints to principals owning specific roles.

See spring security intercept url roles

You can also use JSR-250 annotations: see http://forum.springsource.org/showthread.php?126395-How-to-secure-Spring-MVC-controllers-using-Spring-Security-annotations

--

I do not think you need to restrict the URL /resource/{user} to that specific user. You should deduct the user name from the security context and not let someone inject a specific use name by forging the URL...



回答3:

You can use custom security expression.

<security:intercept-url pattern="/users/{userid}/photos" access="getUserIdUrlPathParameter() == principal.userId"/>

See this post for how to do it.



回答4:

I solved it by using @PreAuthorize("authentication.name == #userId"), instead of @Secured(value = {"userid"}) or @Secured(value = {"#userid"}) like suggested, that were not working.

Note it's necessary to add <security:global-method-security pre-post-annotations="enabled"/> to the servlet context configuration file.