(四十三)权限管理(分析、实现权限加载过程)

权限管理


分析

项目为什么需要做权限功能?

把系统的资源保护起来,给合理的人访问和使用

权限控制表应该如何设计?

首先需要根据需求分析,以员工为例

  • 员工 —>员工表
  • 员工角色表—>员工是什么角色(身份职位)
  • 角色表 ---->存员工职位
  • 角色权限表 ---->该角色有什么权限
  • 权限表 ----->管理分配权限


权限限制

要做资源的权限限制,就是要对系统中动态资源(控制器)的处理方法做出限制,包含了CRUD等操作. 即控制器中的处理方法就是一个个权限,所以数据库中的权限表的数据来源于所有控制器的处理方法.

权限表达式的值需要有唯一性,所以约束其格式:控制器类名首字母小写除去 Controller 加上方法名 .比如:employee:list


数据录入

如何把所有控制器中的每个处理方法转换成数据库中权限表达式的数据

  • 手动: 数据太多,首先排除
  • 自动:
    1. 可以自定义注解,在控制器的处理方法贴上该注解,并在注解上设置权限名称与权限表达式
    2. 通过第三方程序扫描贴了注解的方法,从而获取注解里面的数据
    3. 贴了注解的方法,还可以进行权限限制,贴了就代表要限制,没有就是所有人都可以访问


权限加载流程图

在这里插入图片描述


后台实现

利用mybatis映射工具生成Permission实体类,mapper,mapper.xml等文件

自定义相应方法

  • 实体类Permission
@Data
public class Permission {
    private Long id;
    private String name;
    private String expression;
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Permission that = (Permission) o;
        return expression.equals(that.expression);
    }
    @Override
    public int hashCode() {
        return expression.hashCode();
    }
}


- 实体类JSONResult

@Data
public class JSONResult {
    private boolean success;
    private String msg;
    public JSONResult(boolean success, String msg) {
        this.success=success;
        this.msg=msg;}}


- 自定义注解RequirePermission

贴在控制器对应方法的头上

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RequirePermission {
    String name();
    String expression();}


- PermissionMapper

public interface PermissionMapper {
    int deleteByPrimaryKey(Long id);
    int insert(Permission record);
    Permission selectByPrimaryKey(Long id);
    List<Permission> selectAll();
    int updateByPrimaryKey(Permission record);
    List<Permission> selectForList(QueryObject qo);
    //自定义方法
    //批量插入
    void batchInsert(@Param("permissions") Set<Permission> permissions);
    //角色权限表关系
    List<Permission> selectRoleById(Long roleId);
   //查询员工对应的权限
    List<String> selectExpressionByEmployeeId(Long employeeId);
}


- 权限实现类PermissionServiceImpl

@Service
public class PermissionServiceImpl implements IPermissionService {
    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    @Transactional
    public void insert(Permission permission) {
         permissionMapper.insert(permission);
    }
    @Override
    public void delete(Long id) {
        permissionMapper.deleteByPrimaryKey(id); }

    @Override
    @Transactional
    public void update(Permission permission) {
      permissionMapper.updateByPrimaryKey(permission);}

    @Override
    public Permission get(Long id) {
        Permission permission = permissionMapper.selectByPrimaryKey(id);
        return permission;
    }

    @Override
    public List<Permission> selectAll() {
        List<Permission> permissions = permissionMapper.selectAll();
        return permissions; }


    @Override
  public List<Permission> selectForList(QueryObject qo) {
        List<Permission> permissions = permissionMapper.selectForList(qo);
        return permissions;
    }

    @Override
    public PageInfo<Permission> query(QueryObject qo) {
        //告诉插件我们是第几页,每页条数
   PageHelper.startPage(qo.getCurrentPage(),qo.getPageSize());
        List<Permission> permissions = permissionMapper.selectForList(qo);
        return new PageInfo<>(permissions);}

    //自定义方法
    
    @Override
    public void batchSave(Set<Permission> permissions) {
        permissionMapper.batchInsert(permissions);
    }

    @Override
    public List<Permission> queryByRoleId(Long roleId) {
        return permissionMapper.queryByRoleId(roleId);
    }
    @Override
    public List<String> queryExpressionByEmployeeId(Long employeeId) {
        return permissionMapper.selectExpressionByEmployeeId(employeeId);
    }
}


- PermissionMapper.xml

//批量添加的sql
<insert id="batchInsert">
        insert into permission(name, expression)
                VALUES
        <foreach collection="permissions" item="permission" separator=",">
            (#{permission.name}, #{permission.expression})
        </foreach>
    </insert>


- 权限控制器PermissionController

@Controller
@RequestMapping("/permission")
public class PermissionController {
    @Autowired
    private ApplicationContext ctx;

    @Autowired
    private IPermissionService permissionService;

    //处理分页查询页面请求
    @RequestMapping("/list")
    public String list(QueryObject qo, Model model) {
        PageInfo<Permission> pageInfo = permissionService.query(qo);
        model.addAttribute("pageInfo", pageInfo);
        return "permission/list";
    }


    //响应JSON格式数据 {"success":true,"msg":"加载成功"}
    @RequestMapping("/load")
    @ResponseBody
    public JSONResult load() {
        try {
            //查询数据库中所有的权限
            List<Permission> permissionAll = permissionService.selectAll();
            
            //定义一个存权限Set集合
            Set<Permission> permissions = new LinkedHashSet<>();

            //如何知道所有控制器的处理方法,转成数据库权限表中的一条条数据
            Map<String, Object> map = ctx.getBeansWithAnnotation(Controller.class);
            //获取所有控制器对象
            Collection<Object> controllers = map.values();
            for (Object controller : controllers) {
                //获取控制器对象本类中的方法
                Method[] methods = controller.getClass().getDeclaredMethods();
                for (Method method : methods) {
                    //获取方法的注解
                    RequirePermission annotation = method.getAnnotation(RequirePermission.class);
                    if (annotation != null) {
                        Permission permission = new Permission();
                        permission.setName(annotation.name());
                        permission.setExpression(annotation.expression());

                        //存到set之前判断一下,看这个权限是否在数据库中已存在,若不存在才存到set,之后插入
                        if (!permissionAll.contains(permission)) {
                            permissions.add(permission);
                        }
                    }
                }
            }

            if (permissions.size() > 0) {
                //循环把所有要保存的权限数据封装好,存到set集合中
                System.out.println(permissions.size());
                permissionService.batchSave(permissions);
            }
            return new JSONResult(true, "加载成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new JSONResult(false, "加载失败");
        }

    }
   
}

前端实现

在这里插入图片描述

使用SweetAlert2,替代 JavaScript 的弹出框

引用插件

<link rel="stylesheet" href="/js/plugins/sweetalert2/sweetalert2.min.css">
<script src="/js/plugins/sweetalert2/sweetalert2.min.js"></script>

使用插件,看官方文档实例,拷贝修改即可,样式

Swal.fire({
    title: 'Are you sure?',
    text: "You won't be able to revert this!",
    icon: 'warning',
    showCancelButton: true,
    confirmButtonColor: '#3085d6',
    cancelButtonColor: '#d33',
    confirmButtonText: 'Yes, delete it!',
    cancelButtonText: 'No, cancel!'
}).then((result) => {
    if(result.value) {
        // 点了确定做什么,由开发者决定
    }
});

使用样式:

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值