赞
踩
完整的权限控制包括后端和前端,这里我们先分析下前端。
关于token的生成和解析,这里不再详述,可以看我上一篇博文,这里主要讲解下登录和登录成功后返回token.
登录流程:
前端发送登录表单:手机号+密码
1. npm install js-md5
2. md5(password) 完成MD5加密就这么简单
后端接收:map接收
登录校验
生成token返回
接收token存储到vuex store和cookie中
路由请求拦截器,每次发送请求携带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)
}
)
要实现前端权限校验,登录成功后,菜单和按钮权限是必须。
获取步骤:
登录成功后,请求用户信息
1. 携带token,token中携带userId
根据用户id,获取菜单权限
按钮权限获取
前端接收和存储
后端代码
获取个人信息
@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 // 前端后台管理系统
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。