I have some rest api like this:
/users/{user_id}
/users/{user_id}/orders
/users/{user_id}/orders/{order_id}
How I must secure them? every user must see only her/his data, But admin can see all of them.
How & What I must implement in Spring Security that User by Id == 1 can't see data of user by Id == 2 and vice versa, expect users by role admin that can see all?
Do I check before every method User Id in session is equail with user_id param passed to api? is there a better way?
p.s: I use JWT by spring security.
The HttpServletRequest.getUserPrincipal() will return the result of SecurityContextHolder.getContext().getAuthentication() . This means it is an Authentication which is typically an instance of UsernamePasswordAuthenticationToken when using username and password based authentication.
For adding a Spring Boot Security to your Spring Boot application, we need to add the Spring Boot Starter Security dependency in our build configuration file. Maven users can add the following dependency in the pom. xml file. Gradle users can add the following dependency in the build.
In any @Controller
, @RestController
annotated bean you can use Principal
directly as a method argument.
@RequestMapping("/users/{user_id}")
public String getUserInfo(@PathVariable("user_id") Long userId, Principal principal){
// test if userId is current principal or principal is an ADMIN
....
}
If you don't want the security checks in your Controller
s you could use Spring EL expressions.
You probably already use some build-in expressions like hasRole([role])
.
And you can write your own expressions.
bean
@Component("userSecurity")
public class UserSecurity {
public boolean hasUserId(Authentication authentication, Long userId) {
// do your check(s) here
}
}
http
.authorizeRequests()
.antMatchers("/user/{userId}/**")
.access("@userSecurity.hasUserId(authentication,#userId)")
...
The nice thing is that you can also combine expressions like:
hasRole('admin') or @userSecurity.hasUserId(authentication,#userId)
You can also use @PreAuthorize on the service interface. If you have a custom userdetails object then you can do it easily. In one of my projects I did it like this:
@PreAuthorize(value = "hasAuthority('ADMIN')"
+ "or authentication.principal.equals(#post.member) ")
void deletePost(Post post);
BTW this is in a service interface. You have to make sure to add the right annotations to get preauthorize to work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With