Java REST项目中如何用Apache Shiro实现查看全量资料仅编辑自身资料
Absolutely! Apache Shiro's permission system is tailor-made for this kind of granular, user-specific access control. Let me break down exactly how to make this work for your Java REST project.
1. Define Clear Permission Rules
First, structure your permissions using Shiro's recommended resource:action:target wildcard format—it's flexible and easy to enforce:
- View all user profiles:
user:view:*(the*wildcard means "all targets") - Edit own profile:
user:edit:{userId}(replace{userId}with the actual unique ID of the logged-in user, like1001)
2. Assign Permissions in Your Custom Realm
In your custom AuthorizingRealm, override the doGetAuthorizationInfo method to grant the correct permissions to each authenticated user:
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // Fetch the logged-in user's ID from the principal String currentUserId = (String) principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authInfo = new SimpleAuthorizationInfo(); // Give every authenticated user permission to view all profiles authInfo.addStringPermission("user:view:*"); // Grant permission to edit only their own profile authInfo.addStringPermission("user:edit:" + currentUserId); return authInfo; }
3. Enforce Permissions in Your REST Endpoints
Now add permission checks to your controller methods to enforce the rules:
For Viewing User Profiles
Any authenticated user should be able to access this, so check for the user:view:* permission:
@GetMapping("/users/{userId}") public ResponseEntity<User> getUserDetails(@PathVariable String userId) { Subject currentUser = SecurityUtils.getSubject(); if (!currentUser.isPermitted("user:view:*")) { throw new UnauthorizedException("You don't have permission to view user profiles"); } // Your business logic to fetch user details User user = userService.getUserById(userId); return ResponseEntity.ok(user); }
For Editing User Profiles
Here, we need to verify the user has permission to edit the specific target user (which should only be themselves):
@PutMapping("/users/{userId}") public ResponseEntity<User> updateUserProfile(@PathVariable String userId, @RequestBody User updatedUser) { Subject currentUser = SecurityUtils.getSubject(); if (!currentUser.isPermitted("user:edit:" + userId)) { throw new UnauthorizedException("You can only edit your own profile"); } // Your business logic to update the profile User savedUser = userService.updateUser(updatedUser); return ResponseEntity.ok(savedUser); }
4. Optional: Simplify with Annotations (Spring + Shiro)
If you're using Spring, you can replace manual permission checks with Shiro's annotations for cleaner code:
- Add
@RequiresPermissions("user:view:*")to your view endpoints - Add
@RequiresPermissions("user:edit:{userId}")to your edit endpoints (you'll need to configure Shiro to resolve path variables in annotations, but this cuts down on boilerplate)
Example with annotations:
@GetMapping("/users/{userId}") @RequiresPermissions("user:view:*") public ResponseEntity<User> getUserDetails(@PathVariable String userId) { User user = userService.getUserById(userId); return ResponseEntity.ok(user); } @PutMapping("/users/{userId}") @RequiresPermissions("user:edit:{userId}") public ResponseEntity<User> updateUserProfile(@PathVariable String userId, @RequestBody User updatedUser) { User savedUser = userService.updateUser(updatedUser); return ResponseEntity.ok(savedUser); }
Why Use Permissions Instead of Roles?
Roles work great for grouping users (e.g., "admin" vs "regular user"), but this requirement is user-specific—each regular user needs a unique permission to edit their own profile. Shiro's permission system lets you enforce this granular control without creating a separate role for every single user.
内容的提问来源于stack exchange,提问作者Chenxi

