token与用户权限-前端权限控制-RBAC模型

token与用户权限-前端权限控制-RBAC模型

目录




内容

完整的权限控制包括后端和前端,这里我们先分析下前端。

1、登录和token携带

关于token的生成和解析,这里不再详述,可以看我上一篇博文,这里主要讲解下登录和登录成功后返回token.

1.1、 登录

登录流程:

  1. 前端发送登录表单:手机号+密码

    • 未避免密码明文传输,这里我们直接md5加密
    1. npm install js-md5
    2. md5(password) 完成MD5加密就这么简单
    
  2. 后端接收:map接收

  3. 登录校验

    1. 根据手机号查询用户
      1. 不存在:提示用户名或者密码错误
    2. 校验密码
      1. 不存在:提示用户名或者密码错误
  4. 生成token返回

  5. 接收token存储到vuex store和cookie中

    1. vuex store token 每次从cookie获取
  6. 路由请求拦截器,每次发送请求携带token

    1. 判断是否有token
      1. 有就在请求头中携带
  • 后端实现代码:

       @Override
      public String login(Map<String, Object> map) {
    
      	String mobile = (String) map.get("mobile");
      	String password = (String) map.get("password");
      	UserEntity userEntity = userDao.selectOne(new QueryWrapper<UserEntity>().eq("mobile", mobile));
    
      	if ( userEntity == null || !StringUtils.equals(password, userEntity.getPassword())) {
      		throw new RRException("用户名或者密码错误");
      	}
      	Map<String, Object> m = new HashMap<>();
      	m.put("companyId", userEntity.getCompanyId());
      	m.put("companyName", userEntity.getCompanyName());
      	m.put("userId", userEntity.getId());
      	return jwtUtils.createJwt(userEntity.getId(), userEntity.getUsername(), m);
      }
    
  • 前端

    • 登录和token 获取

        login({ commit }, userInfo) {
        	const { mobile, password } = userInfo
        	return new Promise((resolve, reject) => {
        	  login({ mobile: mobile.trim(), password: password }).then(response => {
        		console.log(response, 'res');
        		const { token } = response
        		commit('SET_TOKEN', token)
        		setToken(token)
        		resolve()
        	  }).catch(error => {
        		reject(error)
        	  })
        	})
          },
      
    • 请求头携带token

        service.interceptors.request.use(
          config => {
        	if (store.getters.token) {
        	  config.headers['Authorization'] = getToken()
        	}
        	return config
          },
          error => {
        	console.log(error) 
        	return Promise.reject(error)
          }
        )
      

2、用户信息(权限信息)获取和存储

要实现前端权限校验,登录成功后,菜单和按钮权限是必须。

获取步骤:

  1. 登录成功后,请求用户信息
    1. 携带token,token中携带userId

  2. 根据用户id,获取菜单权限

    1. 菜单权限为2级层级数据
    2. 符合前端路由要求
  3. 按钮权限获取

    1. 为字符串集合
  4. 前端接收和存储

    1. 接收后存储vuex store中
  • 后端代码

    • 获取个人信息

        @Override
        	public Map<String, Object> profile(String token) {
      
        		// 解析token,获取claims
        		Claims claims = jwtUtils.parseJwt(token);
                System.out.println(claims);
        //        String id = claims.getId();
        //        Object o = claims.get("jti");
        		String userId = (String) claims.get("userId");
        //        System.out.println(claims.get("userId"));
      
        		// 获取用户信息
        		UserEntity userEntity = userDao.selectById(userId);
        		// 根据用户id获取权限
        		// 获取菜单权限
        		List<PermissionEntity> menus = queryLevelMenusByUserId(userId);
        		// 获取按钮权限
        		List<String> btns = permissionDao.queryBtnsByUserId(userId);
      
        		Map<String, Object> userInfo  = new HashMap<>();
        		userInfo.put("user", userEntity);
        		if (CollectionUtils.isNotEmpty(menus)) {
        			userInfo.put("menus", menus);
        		}
        		if (CollectionUtils.isNotEmpty(btns)) {
        			userInfo.put("btns", btns);
        		}
        	   return userInfo;
        	}
      
    • 获取菜单

        private List<PermissionEntity> queryLevelMenusByUserId(String id) {
      
        		List<PermissionEntity> menus = permissionDao.queryMenusByUserId(id);
      
        		// 1、如果是集合为空结束
        		if (CollectionUtils.isEmpty(menus)) {
        			return null;
        		}
        		PermissionEntity root = new PermissionEntity();
        		root.setId("0");
        		LinkedList<PermissionEntity> stack = new LinkedList<>();
        		stack.push(root);
      
        		while (!stack.isEmpty() && menus.size() > 0) {
        			PermissionEntity m = stack.pop();
        			List<PermissionEntity> children = new LinkedList<>();
        			Iterator<PermissionEntity> iterator = menus.iterator();
        			while (iterator.hasNext()) {
        				PermissionEntity next = iterator.next();
        				if (StringUtils.equals(m.getId(),next.getPid())) {
        					// 2.1、找到元素,加入子集合;同时删除在原有集合中移除
        //                    next.setParent(m);
        					children.add(next);
        					iterator.remove();
        				}
        			}
        			if (children.size() > 0) {
        				// 3、子集合不为空,封装层级数据
      
        				m.setChildren(children);
        				stack.addAll(children);
        //                for (PermissionEntity x: children) {
        //                    stack.push(x);
        //                }
        			}
        		}
        		return root.getChildren();
        	}
      
    • 获取按钮权限

        <select id="queryBtnsByUserId" resultType="java.lang.String">
        		select
        			tp.perms
        		from tb_permission tp
        		left join tb_role_perm trp on trp.perm_id = tp.id
        		left join tb_user_role tur on tur.role_id = trp.role_id
        		where tur.user_id = #{id} and type = 2
        	</select>
      
  • 前端

    • 把个人信息存储到store中

       getInfo({ commit, state }) {
       	return new Promise((resolve, reject) => {
       	  getInfo(state.token).then(response => {
       		console.log(response, 'info');
       		const { userInfo } = response
       		const {user, menus, btns} = userInfo
       		if (!user) {
       		  reject('认证失败,请重新登录')
       		}
      
       		// const { roles, name, avatar, introduction } = data
      
       		// roles must be a non-empty array
       		if (!menus || menus.length <= 0) {
       		  reject('权限不能为空,请先获取权限')
       		}
      
       		commit('SET_MENUS', menus)
       		commit('SET_BTNS', btns)
       		commit('SET_USER', user)
      
       		resolve(userInfo)
       	  }).catch(error => {
       		reject(error)
       	  })
       	})
         },
      

到此我们登录和前端权限控制所需信息获取已完成,下面我要实现前端动态菜单的生成。

后记

本项目为参考某马视频开发,相关视频及配套资料可自行度娘或者联系本人。上面为自己编写的开发文档,持续更新。欢迎交流,本人QQ:806797785

后端JAVA源代码地址:https://gitee.com/gaogzhen/ihrm-parent    // 后端项目
前端项目源代码地址:https://gitee.com/gaogzhen/ihrm-vue    // 前端后台管理系统
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gaog2zh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值