Reputation: 1047
I'm developing a web application using Spring MVC + Spring Security, and I have the following URLs:
/*this URL should be accessible by any User, i.e. users should be able to see other users' profiles*/
/users/someUserId/profile
/* all the following URLs should be accessed only by the current authenticated user */
/users/someUserId/profile/edit
/users/someUserId/picture/edit
/users/someUserId/notifications
/users/someUserId/friends
and I need them to be secured as previously described.
My configure method goes as follows:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.regexMatchers("/users/[\\w]+/profile").authenticated()
.antMatchers("/users/[\\w]/**").access("principal.name == regexGroupMatch")
.anyRequest().authenticated()
.and()
.jee().mappableRoles("Admin", "User");
}
I want to know if it's possible to achieve something like that:
.antMatchers("/heroes/[\\w]/**").access("principal.name == regexGroupMatch")
By doing this, I'm willing only the user user1 to be able to access the URLs:
/users/user1/profile/edit
/users/user1/picture/edit
/users/user1/notifications
So, user2 must not be able to access the previously mentioned URLs, but must be able to access: /users/user1/profile/edit /users/user1/picture/edit /users/user1/notifications
As well as:
/users/user1/profile
/users/user2/profile
/users/user3/profile
etc...
Is it possible to achieve that using Spring Security?
Upvotes: 1
Views: 1989
Reputation: 22742
No, there's no functionality to extract matching groups in a regex and compare them to the username. Also, note that ant patterns don't support regex expressions at all.
It's not a good idea to rely on complicated URL patterns in any case. For something like this you're best to use method security at the controller level or on some service interface, where you can refer to method parameters by name. For example, with method security expressions enabled, you could write
@PreAuthorize("#user.name == authentication.name")
public void editUser(User user) {
....
}
Alternatively, as Misha says, you can just code the rule directly, which is preferable if things get more complicated than simple expressions.
Upvotes: 2
Reputation: 929
Spring Security will ensure that clients accessing those endpoints are authenticated, but it's up to you to make sure the endpoint only returns data that user is allowed to see. Think about it - how could Spring Security know what data in your application is permitted to be seen by each user?
You probably already have a controller method that looks like this:
@RequestMapping(value = "/users/{user}/profile/edit", method = RequestMethod.GET)
public ModelAndView edit(
HttpServletRequest request,
@PathVariable("user") String,
EditRequest edit) {
// Accept or reject the request if the user variable and authenticated
// user match up as required.
}
Here, you need to programmatically distinguish the authenticated user (retrievable from the request object), and the user stated by the context. If the user in the context is the authenticated user, you might accept the request, since users are likely permitted to modify their own profiles. Otherwise, you can throw some sort of authorization exception - or better yet, return a nice view explaining why that page is inaccessible.
Note that this can also be rewritten as a filter, since you aren't using any information in the body of the request. That filter would indeed plug into Spring Security.
Upvotes: 1