一、数据准备
1.1 创建permission 表
创建一张permission表
CREATE TABLE `permission` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`url` varchar(255) DEFAULT NULL,
`role_id` int(11) DEFAULT NULL,
`permission` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
初始化两条数据
INSERT INTO
chapter03.permission(id,url,role_id,permission) VALUES (1, ‘/admin’, 1, ‘c,r,u,d’);
INSERT INTOchapter03.permission(id,url,role_id,permission) VALUES (2, ‘/admin’, 2, ‘r’);
1.2 创建 entity、Mapper、Service
(1)、创建permission实体
package com.sl.entity;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
/**
* @author shuliangzhao
* @Title: Permission
* @ProjectName spring-boot-learn
* @Description: TODO
* @date 2019/8/6 19:22
*/
public class Permission implements Serializable {
private Integer id;
private String url;
private Integer roleId;
private String permission;
private List<String> permissions;
public List<String> getPermissions() {
return Arrays.asList(this.permission.trim().split(","));
}
public void setPermissions(List<String> permissions) {
this.permissions = permissions;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public Integer getRoleId() {
return roleId;
}
public void setRoleId(Integer roleId) {
this.roleId = roleId;
}
public String getPermission() {
return permission;
}
public void setPermission(String permission) {
this.permission = permission;
}
}
这里需要注意的时相比于数据库,多了一个 permissions 属性,该字段将 permission 按逗号分割为了 list。
(2)、创建permissionMapper
@Mapper
public interface PermissionMapper {
@Select("SELECT * FROM permission where role_id = #{id}")
List<Permission> selectListById(Integer id);
}
(3)、创建permissionService
@Service
public class PermissionService {
@Autowired
private PermissionMapper permissionMapper;
public List<Permission> selectListById(Integer id) {
return permissionMapper.selectListById(id);
}
}
1.3 修改接口
@Controller
public class LoginController {
...
@RequestMapping("/admin")
@ResponseBody
@PreAuthorize("hasPermission('/admin','r')")
public String printAdminR() {
return "如果你看见这句话,说明你访问/admin路径具有r权限";
}
@RequestMapping("/admin/c")
@ResponseBody
@PreAuthorize("hasPermission('/admin','c')")
public String printAdminC() {
return "如果你看见这句话,说明你访问/admin路径具有c权限";
}
}
让我们修改下我们要访问的接口,@PreAuthorize("hasPermission('/admin','r')")是关键,参数1指明了访问该接口需要的url,参数2指明了访问该接口需要的权限。
二、PermissionEvaluator
@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
@Autowired
private PermissionService permissionService;
@Autowired
private RoleService roleService;
@Autowired
private UserService userService;
@Override
public boolean hasPermission(Authentication authentication, Object targetUrl, Object permission) {
// 获得loadUserByUsername()方法的结果
/*String userName = (String) authentication.getPrincipal();
User user = userService.selectByName(userName);*/
// 获得loadUserByUsername()中注入的角色
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
// 遍历用户所有角色
for (GrantedAuthority authority:authorities) {
String roleName = authority.getAuthority();
Integer rId = roleService.selectByName(roleName).getId();
// 得到角色所有的权限
List<Permission> permissions = permissionService.selectListById(rId);
// permissions
for (Permission per:permissions) {
//获取权限集
List<String> permissions1 = per.getPermissions();
if (targetUrl.equals(per.getUrl()) && permissions1.contains(permission)) {
return true;
}
}
}
return false;
}
@Override
public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
return false;
}
}
在 hasPermission() 方法中,参数 1 代表用户的权限身份,参数 2 参数 3 分别和 @PreAuthorize(“hasPermission(’/admin’,‘r’)”) 中的参数对应,即访问 url 和权限。
思路如下:
- 通过 Authentication 取出登录用户的所有 Role
- 遍历每一个 Role,获取到每个Role的所有 Permission
- 遍历每一个 Permission,只要有一个 Permission 的 url 和传入的url相同,且该 Permission 中包含传入的权限,返回 true
- 如果遍历都结束,还没有找到,返回false
下面就是在 WebSecurityConfig 中注册 CustomPermissionEvaluator
@Bean
public DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setPermissionEvaluator(customPermissionEvaluator);
return defaultWebSecurityExpressionHandler;
}
本文详细介绍了如何在Spring Boot项目中实现基于URL的权限管理,包括数据库表设计、实体类、Mapper、Service的创建,以及如何使用PermissionEvaluator进行权限验证。
3916

被折叠的 条评论
为什么被折叠?



