基于SpringBoot2.x+Vue2的SaaS-HRM项目(四)

三、项目设计

4.4 后台权限管理

首先要知道,权限分为几大类:

  1. 按钮
    前端通过判断权限动态加载按钮
  2. 菜单
    前端根据权限的不同,对隐藏与现实进行一定的控制
  3. 接口api
    我们无论在前端如何设置属性,都可以从html代码中将某些受到权限管理的api找到并且执行,这是不安全的,所以就要在后端利用权限验证判断是否可以有足够的权限访问api

思路:从上文可知,我们需要在设置权限的时候对权限的种类进行判断,所以就要在数据库加上相应字段,如1 2 3分别对应三种权限,但是在设计return 的json的时候,我们需要把三种权限对应的结果一并写入进去,存入一个map,通过type对应的值,取出对应权限的结果。而判断这个人权限对应的type的方法,可以用一种编码来判断。
在这里插入图片描述
在这里插入图片描述

这是用powerDesigner画出的数据库逻辑图,我们首先要创建出菜单表,页面元素表,API接口表,总体权限表和用户表与角色表的实体类,两张关联表可以写在实体类中用@JoinTable来关联两张表(用户-角色,角色-总体权限)

设置关联表的目的就不用多说了,我们要删或者添加一个人的时候,所增加的信息都是成套的。

这样就完成了权限管理中Entity的设计,然后是对应的dao,service与controller,dao也是写出菜单表,页面元素表,API接口表,总体权限表和用户表与角色表的实体类的,而controller只需要写出总体权限表,用户与角色即可。

思路:

  1. 实现功能在基本的增删改查上增加了权限分配,角色分配,角色与权限绑定的过程。其余的实现方法可参照之前。

  2. 权限分配:我们将功能实现在Permission的系列中。

Bean to Map:不管是角色,权限,还是使用者都会有一定的json信息,创建一个Bean to Map 的类,将对象以Map的形式进行转储,然后提取API,按钮,菜单对应的信息是我们这个类的最终目的。

public class BeanMapUtils {

    /**
     * 将对象属性转化为map结合
     */
    public static <T> Map<String, Object> beanToMap(T bean) {
        Map<String, Object> map = new HashMap<>();
        if (bean != null) {
            BeanMap beanMap = BeanMap.create(bean);
            for (Object key : beanMap.keySet()) {
                map.put(key+"", beanMap.get(key));
            }
        }
        return map;
    }

    /**
     * 将map集合中的数据转化为指定对象的同名属性中
     */
    public static <T> T mapToBean(Map<String, Object> map,Class<T> clazz) throws Exception {
        T bean = clazz.newInstance();
        BeanMap beanMap = BeanMap.create(bean);
        beanMap.putAll(map);
        return bean;
    }
}

保存权限(save):首先我们知道权限分为三种,API,按钮,菜单,当用户对着三者发送Request的时候,使用我们的BeanToMap进行转储。再通过传过来的type进行判断是哪种权限,对应的将信息去进行保存即可。

public void save(Map<String,Object> map) throws Exception {
        //设置主键的值
        String id = idWorker.nextId()+"";
        //1.通过map构造permission对象
        Permission perm = BeanMapUtils.mapToBean(map,Permission.class);
        perm.setId(id);
        //2.根据类型构造不同的资源对象(菜单,按钮,api)
        int type = perm.getType();
        switch (type) {
            case PermissionConstants.PERMISSION_MENU:
                PermissionMenu menu = BeanMapUtils.mapToBean(map,PermissionMenu.class);
                menu.setId(id);
                permissionMenuDao.save(menu);
                break;
            case PermissionConstants.PERMISSION_POINT:
                PermissionPoint point = BeanMapUtils.mapToBean(map,PermissionPoint.class);
                point.setId(id);
                permissionPointDao.save(point);
                break;
            case PermissionConstants.PERMISSION_API:
                PermissionApi api = BeanMapUtils.mapToBean(map,PermissionApi.class);
                api.setId(id);
                permissionApiDao.save(api);
                break;
            default:
                throw new CommonException(ResultCode.FAIL);
        }
        //3.保存
        permissionDao.save(perm);
    }

分类的思想是一致的。
更新(update):同样,根据请求头,来判断用户的信息和权限,然后根据是更新哪一种权限信息去save。
查询(findById):通过id进行单个用户的查询是相对简单的,只需要判断是因为触发哪种条件并且对应该条件进行json->map的转型即可,然后其他还有什么属性一并用getter存储即可
查询(findAll):查询所有人的时候需要一个limit条件,通过不同的查询条件可以得到不同的结果,这是额外新加的一个功能。这里主要是用了父id,enVisible,type进行查询。写的方法很多很多,能熟练使用toPredicate即可。
删除(deleteById):和上面的思想是一样的。

  1. 角色分配:我们将功能实现的Role的系列中。

权限分配(assignPerms):第一步,我们要将request过来的对象信息获取到;第二步,我们要将确定给予角色的权限以set的方式存进来并且对应着权限去给予对象实际的能力;第三步,将角色与权限的关系进行数据绑定到联合表中。第四步,保存。

  1. 将用户与角色进行绑定,这样用户-角色-权限就绑定起来了。

4.5 认证机制

常见的认证机制如下:

HTTP Basic Auth
简单来说,直接账号密码验证,过了就能登录。

Cookie Auth
登录的时候在Server端建立一个Session对象,同时在Client的浏览器端创建一个Cookie对象。通过Client带上来Cookie对象来与服务端的Session对象匹配来通过登录认证。并且cookie可以设置失效时间。
但是在微服务的时候,我们一使用跨域访问多端口的业务,cookie就不一样了,就会出错,所以cookie现在也不太好了。

OAuth
开放授权,用第三方去授权登录网站。

Token Auth
使用基于Token的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

  1. 客户端使用用户名密码登录
  2. Server端收到请求进行验证
  3. 验证通过,Server端会签发一个Token,再把Token发送到客户端
  4. 之后前端再访问api的时候就用token当请求头用了,只要验证成功就可以get到数据
    在这里插入图片描述

优点

  1. 支持跨域
  2. 不需要保存登录信息在Server端
  3. 不影响页面显示效果
  4. token可以在任何地方生成,不必非得在登录系统中用
  5. 很难伪造出token进行跨站伪造访问(CSRF)
  6. 性能强
  7. 基于标准化,可以采用JWT(Json Web Token)
  8. 做测试的时候可以用之前生成好的令牌
4.5.1 JWT(Java Web Token)

利用生成的token完成用户认证与登录

设置认证Jwt

前端将用户名和密码填写完整之后登录,便会触发jwt。
步骤:

  1. 根据用户名查询用户是否存在
  2. 比较密码
  3. 生成对应的token
  4. 令前端访问后,可以凭借token访问

思路:
(1) 引入jwt工具类
(2) 在userController中添加用户登录
(3) 验证用户信息
(4) 返回
在这里插入图片描述

@PostMapping(value = "/login")
    public Result login(@RequestBody Map<String,String> loginMap) {
        String mobile = loginMap.get("mobile");
        String password = loginMap.get("password");
        User user = userService.findByMobile(mobile);
        if (user == null || !user.getPassword().equals(password)) {
            return new Result(ResultCode.MOBILEORPASSWORDERROR);//登录失败
        } else {
            Map<String, Object> map = new HashMap<>();
            map.put("companyId", user.getCompanyId());
            map.put("companyName", user.getCompanyName());//claims添加
            String jwt = jwtUtils.createJWT(user.getId(), user.getUsername(), map);
            //根据id 用户名和自定义的claims生成token
            return new Result(ResultCode.SUCCESS, jwt);
        }
    }

设置解析Jwt
功能:获取用户信息,像权限标识(三种),角色之类的
思路 :

  1. 获取头信息的token
  2. 从token中提取userid
  3. 查询用户
  4. 构造数据

在这里插入图片描述

/**
     * 获取用户信息
     * 1.获取用户id
     * 2.根据用户id查询用户
     * 3.构建返回值
     * 4.响应
     */
    @PostMapping(value = "/profile")
    public Result profile(HttpServletRequest request) throws Exception {

        /**
         * 从请求头信息中获取token数据
         * 1.获取请求头信息  名称=Authorization
         * 2.替换Bearer+空格
         * 3.解析token
         * 4.获取clamis
         */
//        1.从请求头信息中获取token数据
        String authorization = request.getHeader("Authorization");
        if (StringUtils.isEmpty(authorization)) {
            throw new CommonException(ResultCode.UNAUTHENTICATED);
        }
//        2.替换Bearer+空格
        String token = authorization.replace("Bearer ","");//去除Bearer,提取纯正的token
//        3.解析token,4.获取clamis
        Claims claims = jwtUtils.parseJwt(token);
        String userId = claims.getId();
        //获取用户信息
        User user = userService.findByid(userId);
        //根据不同的用户级别获取用户级别权限
        ProfileResult profileResult = null;
        if ("user".equals(user.getLevel())) {//最低级
            profileResult = new ProfileResult(user);
        } else {
            Map map = new HashMap();
            if ("coAdmin".equals(user.getLevel())) {//第二个级别
                map.put("enVisible", "1");
            }
            List<Permission> list = permissionService.findAll(map);
            profileResult = new ProfileResult(user, list);
        }
        return new Result(ResultCode.SUCCESS, profileResult);
    }

基于SpringBoot2.x+Vue2的SaaS-HRM项目(五)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值