token与用户权限-前端权限控制-RBAC模型
程序员文章站
2022-07-14 15:32:49
...
token与用户权限-前端权限控制-RBAC模型
目录
内容
完整的权限控制包括后端和前端,这里我们先分析下前端。
1、登录和token携带
关于token的生成和解析,这里不再详述,可以看我上一篇博文,这里主要讲解下登录和登录成功后返回token.
1.1、 登录
登录流程:
-
前端发送登录表单:手机号+密码
- 未避免密码明文传输,这里我们直接md5加密
1. npm install js-md5 2. md5(password) 完成MD5加密就这么简单
-
后端接收:map接收
-
登录校验
- 根据手机号查询用户
- 不存在:提示用户名或者密码错误
- 校验密码
- 不存在:提示用户名或者密码错误
- 根据手机号查询用户
-
生成token返回
-
接收token存储到vuex store和cookie中
- vuex store token 每次从cookie获取
-
路由请求拦截器,每次发送请求携带token
- 判断是否有token
- 有就在请求头中携带
- 判断是否有token
-
后端实现代码:
@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. 携带token,token中携带userId -
根据用户id,获取菜单权限
- 菜单权限为2级层级数据
- 符合前端路由要求
-
按钮权限获取
- 为字符串集合
-
前端接收和存储
- 接收后存储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 // 前端后台管理系统
上一篇: 学习shiro框架记的一次随笔
下一篇: PBAC基于策略的权限控制