<font color=#999AAA >
</font>
(文章目录
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
前言
<font color=#999AAA > 需要在前端页面就获取用户信息、角色、用户菜单权限,实现对不同角色,不同用户,页面、菜单、方法甚至按钮的权限控制。 </font>
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
一、举例需求如下图:
二、前端ElementUI封装全局
系统用户信息、角色信息、菜单权限信息
data : function() {// data属性
return {
menuData : [],// 菜单数据
isCollapse:false,
defaultEpeneds : [],// 菜单默认展开
sysUser : {// 当前用户信息
id : null,
username : null,
image : null,
realName : null,
},
sysRole : {// 当前用户角色
id : null,
username : null,
roleIds : [],
roleOptions : [],
},
getUserInfo : function(func) {// 查看个人信息
// 获取当前实例
var _this = this;
// 请求个人信息
this.doGetData(_this.baseUrl + _this.getUserInfoUrl, {}, function(r) {
if (r.success) {
func(r);// 回调
} else {
_this.$message.error("服务器异常!");
}
});
},
getUserRole : function(func) {// 查看个人角色
// 获取当前实例
var _this = this;
// 请求个人信息
this.doGetData(_this.baseUrl + _this.getUserRoleUrl, {}, function(r) {
if (r.success) {
func(r);// 回调
} else {
_this.$message.error("服务器异常!");
}
});
},
getUserMenu : function() {// 获取我的菜单
// 获取当前实例
var _this = this;
// 获取数据
_this.doGetData(_this.baseUrl + _this.getUserMenuUrl, {platform : "P"}, function(r) {
if (r.success) {
_this.menuData = r.data;
for (var i = 0; i < _this.menuData.length; i++) {
_this.defaultEpeneds.push(_this.menuData[i].id);
}
} else {
_this.$message.error("服务器异常!");
}
});
},
getUserInfoUrl: "sysUser/getUserInfo.do",// 获取用户信息请求URL
getUserRoleUrl: "sysUser/getUserRole.do",// 获取用户角色请求URL
getUserMenuUrl : "sysUser/getUserMenu.do",// 获取用户菜单URL
.........
mounted : function() {
// 获取实例对象
var _this = this;
// 获取个人信息
_this.getUserInfo(function(r) {
_this.sysUser = r.data;
});
// 获取个人角色
_this.getUserRole(function(r) {
_this.sysRole = r.data;
});
// 获取菜单列表
_this.getUserMenu();
// 触发Common组件已挂载事件
_this.commonMounted();
// 监听窗口大小变化
window.onresize = function() {
// 根据高度变化调整容器高度
_this.containerStyle2.height = (window.innerHeight - 60) + "px";
}
},
三、后端获取方法
1.控制器
/**
* 查询用户信息
*/
@RequestMapping("/getUserInfo")
@ResponseBody
public Result getUserInfo() {
try {
// 查询系统用户
SysUser user = sysUserService.getSysUser(ShiroUtils.getLoginSysUserId());
// 返回Page结果集
return Results.queryOk(dto);
} catch (Exception e) {
logger.error("查询系统用户信息失败!SysUserId:" + ShiroUtils.getLoginSysUserId(), e);
return Results.queryError();
}
}
/**
* @Description 获取用户角色
**/
@RequestMapping("/getUserRole")
@ResponseBody
public Result getUserRole() {
try {
// 查询系统用户
SysUserRoles userRoles= sysUserService.getSysUserRoles(ShiroUtils.getLoginSysUserId());
return Results.queryOk(dto);
} catch (Exception e) {
logger.error("查询系统用户角色信息失败!SysUserId:" + ShiroUtils.getLoginSysUserId(), e);
return Results.queryError();
}
}
/**
* 获取用户菜单
*/
@SuppressWarnings("unchecked")
@RequestMapping("/getUserMenu")
@ResponseBody
public Result getUserMenu(@Valid GetUserMenuParam params, BindingResult r) {
try {
if (r.hasErrors()) {
return Results.paramError(r);
}
// 获取菜单会话属性
Object obj = ShiroUtils.getSessionAttr(Constants.USER_MENU_KEY);
List<SysUserMenuItem> menus = null;
if (obj == null) {// 没有会话属性
// 从数据库加载
menus = sysUserService.getUserMenuItems(params.getPlatform());
String menusJson = JSON.toJSONString(menus);
// 设置会话属性
ShiroUtils.setSessionAttr(Constants.USER_MENU_KEY, menusJson);
} else {
// 有会话属性,直接使用会话属性
menus =JSON.parseArray((String)obj, SysUserMenuItemDto.class);
}
return Results.listResult(menus);
} catch (Exception e) {
logger.error("获取我的菜单失败!params:" + params.toString(), e);
return Results.opError();
}
}
2.实现接口
/**
* 获取用户信息
*/
@Override
public SysUser getSysUser(String userId) {
SysUser sysUser = sysUserService.selectById(userId);
return sysUser ;
}
/**
* 获取用户角色
*/
@Override
public SysUserRoles getSysUserRoles(String userId) {
// 创建响应对象
SysUserRoles dto = new SysUserRoles();
// 查询系统用户信息
SysUser sysUser = sysUserService.selectById(sysUserId);
BeanUtils.copyProperties(sysUser, dto);
// 查询指定系统用户的角色信息列表
List<SysUserRole> list = sysUserRoleService.selectList(SQLHelper.build(SysUserRole.class)
.eq("userId", userId).geEntityWrapper());
// 提取系统用户的角色ID列表
List<String> roleIds = list.stream().map(SysUserRole::getRoleId).collect(toList());
dto.setRoleIds(roleIds);
// 查询所有角色选项
List<Role> roles = roleService.selectList(SQLHelper.build(Role.class).geEntityWrapper());
List<OptionDto> roleOptions = roles.stream().map(r -> {
OptionDto option = new OptionDto();
option.setDisabled(false);
option.setValue(r.getId());
option.setLabel(r.getName());
return option;
}).collect(toList());
dto.setRoleOptions(roleOptions);
return dto;
}
/**
* 获取用户菜单权限
*/
@SuppressWarnings("unchecked")
@Override
public List<SysUserMenuItem> getUserMenuItems(String platform) {
// 查询指定用户的角色ID列表
List<SysUserRole> list = sysUserRoleService.selectList(SQLHelper.build(SysUserRole.class)
.eq("sysUserId", ShiroUtils.getLoginSysUserId()).geEntityWrapper(););
// 提取系统用户的角色ID列表
List<String> roleIds = list.stream().map(SysUserRole::getRoleId).collect(toList());
// 查询当前系统用户所有角色合并的权限信息
List<String> permissionIds = rolePermissionService.selectList(// 查询角色权限关系列表
SQLHelper.build(RolePermission.class).in("roleId", roleIds).geEntityWrapper()).parallelStream()// 开始流处理
.map(RolePermission::getPermissionId)// 提取权限ID
.distinct()// 对权限ID去重
.collect(toList());// 收集权限ID
// 查询当前用户的所有权限信息列表
List<Permission> permissions = permissionService.selectBatchIds(permissionIds);
// 转换
List<SysUserMenuItem> dtos = permissions.parallelStream()// 开始并行流处理
.filter(p -> p.isMenu() && p.getPlatform().equals(platform))// 过滤出菜单权限和特定平台权限
.sequential()// 开始顺序流处理
.sorted((p1, p2) -> p1.getOrder().compareTo(p2.getOrder()))// 按Order进行排序
.map(p -> {
// 转换为DTO
SysUserMenuItem dto = new SysUserMenuItem();
BeanUtils.copyProperties(p, dto);
dto.setId(p.getUrl() == null ? p.getId() : p.getUrl());
return dto;
}).collect(toList());// 收集
// 转换为树结构
return (List<SysUserMenuItem>) TreeUtils.toTree(dtos);
}
3.ShiroUtils工具类
项目采用shiro权限控制
package com.cherry.framework.shiro.utils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import com.cherry.shop.security.entity.SysUser;
import com.cherry.shop.user.entity.User;
/**
* Shiro工具类
*/
public class ShiroUtils {
/**
* 获取凭证
* @param clazz
* 凭证字节码对象
* @return 凭证
*/
@SuppressWarnings("unchecked")
public static <T> T getPrincipal(Class<T> clazz) {
return (T) SecurityUtils.getSubject().getPrincipal();
}
/**
* 获取当前登录的系统用户
* @return 当前登录的系统用户
*/
public static SysUser getLoginSysUserId() {
return getPrincipal(SysUser.class);
}
/**
* 获取当前系统用户ID
* @return 当前系统用户ID
*/
public static String getLoginSysUserId() {
return getLoginSysUser().getId();
}
/**
* 获取当前登录的系统用户
* @return 当前登录的系统用户
*/
public static SysUser getLoginSysUser() {
return getPrincipal(SysUser.class);
}
/**
* 设置会话属性
* @param key 键
* @param value 值
*/
public static void setSessionAttr(String key, Object value) {
SecurityUtils.getSubject().getSession().setAttribute(key, value);
}
/**
* 获取会话属性
* @param key 键
* @return 值
*/
public static Object getSessionAttr(String key) {
return SecurityUtils.getSubject().getSession().getAttribute(key);
}
}
四、前端页面引用全局方法
// 开票按钮
<el-button size="mini" type="text" icon="icon iconfont icon-jihuopeizhi" @click="handleSetInvoice(scope.row)" v-if="scope.row.isInvoice == '0'" :disabled="setInvoiceVisible" >开票 </el-button>
...............................
// 查询企业列表方法(开票按钮是在查询出来的企业才能操作)
handleQuery: function (event) {
// 直接调用页面全局变量sysRole的角色roleIds
var roleIds = this.sysRole.roleIds;
for(var i=0;i<roleIds.length;i++){
var roleId = roleIds[i];
if(roleId != undefined && roleId != null && roleId != ""){
// 如果角色roleId中包括1,则设置按钮不禁用 -- 即有开票权限
if(roleId == 1 ){
this.setInvoiceVisible = false;
break;
}
}
}
// 这个是调用查询企业列表方法
this.refreshData();
}
<hr style=" border:solid; width:100px; height:1px;" color=#000000 size=1">
随心所往,看见未来。Follow your heart,see night!<br/> 欢迎点赞、关注、留言,收藏及转发,一起学习、交流!