Shiro可以对URL授权,也可以对页面上的输入域或按钮等元素授权,故对URL授权的代码,我们设定以URL开头,例如
对这些权限,需要开发人员在部署系统时作为初始化数据输入到系统,系统管理员可以授权这些权限给角色,存放这些权限的数据库表以功能模块表组织,
与功能模块表构成多对一的关系。
权限与角色授权是多对多的关系
SQL
create table gf_permission(id varchar(32),
funcid varchar(32),
name varchar(100),
permission varchar(100));
create table gf_perm2role(id varchar(32),
permid varchar(32),
roleid varchar(32));
Mapper.xml
<!-- 权限表操作 -->
<insert id="savePermission" parameterType="com.gf.statusflow.def.PermissionInfo">
insert into gf_permission(id,funcid,name,permission)
values(#{id},#{funcId},#{name},#{permission})
</insert>
<update id="updatePermission" parameterType="com.gf.statusflow.def.PermissionInfo">
update gf_permission set funcid=#{funcId},name=#{name},permission=#{permission}
where id=#{id}
</update>
<delete id="deletePermById" parameterType="String">
delete from gf_permission where id=#{id}
</delete>
<delete id="deletePermByFuncId" parameterType="String">
delete from gf_permission where funcid=#{funcId}
</delete>
<select id="getPermissionByFuncId" resultType="com.gf.statusflow.def.PermissionInfo">
select * from gf_permission where funcid=#{funcId}
</select>
<select id="getPermission" resultType="com.gf.statusflow.def.PermissionInfo">
select p2r.id,a.name,a.permission,r.name roleName,c.name funcName from gf_permission a,gf_perm2role p2r,gf_role r,gf_function c
where a.funcid=c.id and a.id=p2r.permid and p2r.roleid=r.id
and (p2r.permid like '%${permId}%' and a.funcid like '%${funcId}%')
and p2r.roleid like '%${roleId}%'
</select>
<!-- 权限与角色中间表 -->
<insert id="savePerm2Role" parameterType="com.gf.statusflow.def.Perm2RoleInfo">
insert into gf_perm2role(id,permid,roleid)
values(#{id},#{permId},#{roleId})
</insert>
<delete id="deletePerm2RoleById" parameterType="String">
delete from gf_perm2role where id=#{id}
</delete>
<delete id="deletePerm2RoleByRoleId" parameterType="String">
delete from gf_perm2role where roleid=#{roleId}
</delete>
<delete id="deletePerm2RoleByPermId" parameterType="String">
delete from gf_perm2role where permid=#{permId}
</delete>
<select id="getPermByRoleId" resultType="String">
select p.permission from gf_perm2role p2r,gf_permission p
where p2r.permid=p.id and p2r.roleid=#{roleId}
</select>
IOrgModel组织机构接口
涉及权限操作,权限过滤的方法等通用功能,都设置到组织机构接口
/**
* Shiro权限相关Mybatis方法
*/
public void savePermission(PermissionInfo permission);
public void updatePermission(PermissionInfo permission);
public void deletePermById(String id);
public void deletePermByFuncId(String id);
public List<PermissionInfo> getPermissionByFuncId(String id);
public List<PermissionInfo> getPermission(String permId,
String funcId,String roleId);
/**
* 角色与权限中间表Mybatis方法
*/
public void savePerm2Role(Perm2RoleInfo p2r);
public void deletePerm2RoleById(String id);
public void deletePerm2RoleByRoleId(String roleId);
public void deletePerm2RoleByPermId(String permId);
public List<String> getPermByRoleId(String roleId);
组织机构实现类
/**
* Shiro权限相关Mybatis方法
*/
public void savePermission(PermissionInfo permission)
{
try
{
mapper.savePermission(permission);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public void updatePermission(PermissionInfo permission)
{
try
{
mapper.updatePermission(permission);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public void deletePermById(String id)
{
try
{
mapper.deletePermById(id);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public void deletePermByFuncId(String module)
{
try
{
mapper.deletePermByFuncId(module);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public List<PermissionInfo> getPermissionByFuncId(String id)
{
try
{
return mapper.getPermissionByFuncId(id);
}
catch(Exception e)
{
log.error(e.getMessage());
}
return null;
}
public List<PermissionInfo> getPermission(String permId,
String funcId,String roleId)
{
try
{
return mapper.getPermission(permId,funcId,roleId);
}
catch(Exception e)
{
log.error(e.getMessage());
}
return null;
}
/**
* 角色与权限中间表Mybatis方法
*/
public void savePerm2Role(Perm2RoleInfo p2r)
{
try
{
mapper.savePerm2Role(p2r);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public void deletePerm2RoleById(String id)
{
try
{
mapper.deletePerm2RoleById(id);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public void deletePerm2RoleByPermId(String permId)
{
try
{
mapper.deletePerm2RoleByPermId(permId);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public void deletePerm2RoleByRoleId(String roleId)
{
try
{
mapper.deletePerm2RoleByRoleId(roleId);
}
catch(Exception e)
{
log.error(e.getMessage());
}
}
public List<String> getPermByRoleId(String roleId)
{
try
{
return mapper.getPermByRoleId(roleId);
}
catch(Exception e)
{
log.error(e.getMessage());
}
return null;
}
Controller层
@RequestMapping("/module.action")
public String module()
{
return "/orgmodel/module";
}
@RequestMapping("/moduleacl.action")
public String moduleacl()
{
return "/orgmodel/moduleacl";
}
@ResponseBody
@RequestMapping("/modulefuncroot.action")
public List<TreeNode> funcroot()
{
FunctionInfo rootFi = orgmodel.getRootFunc();
if(rootFi == null)
{
rootFi = orgmodel.initFunc();
}
List<TreeNode> trees = new ArrayList<TreeNode>();
TreeNode rootTree = new TreeNode();
rootTree.setId(rootFi.getId().toString());
rootTree.setText(rootFi.getName());
rootTree.setState("closed");
Map attributes = new HashMap();
attributes.put("parentId",rootFi.getParentId());
attributes.put("path", "/");
attributes.put("fullName", "/"+rootFi.getName());
attributes.put("isload", "false");
rootTree.setAttributes(attributes);
trees.add(rootTree);
return trees;
}
@ResponseBody
@RequestMapping("/modulegettreebyid")
public List<TreeNode> modulegettreebyid(String id)
{
List<FunctionInfo> funs = orgmodel.getChildFunc(id);
List<TreeNode> rtn = new ArrayList<TreeNode>();
if(funs != null && funs.size()>0)
{
for(FunctionInfo fi:funs)
{
TreeNode ti = new TreeNode();
ti.setId(fi.getId().toString());
ti.setText(fi.getName());
ti.setIconCls(fi.getIcon()!=null?fi.getIcon():"pic_1");
ti.setUrl(fi.getUrl());
List<FunctionInfo> chd = orgmodel.getChildFunc(fi.getId());
List<PermissionInfo> perms = orgmodel.getPermissionByFuncId(fi.getId());
if(chd != null && chd.size()>0)
ti.setState("closed");
else
{
//存在下一级授权信息
if(perms != null && perms.size()>0)
ti.setState("closed");
else
ti.setState("open");
}
ti.addAttribute("path",fi.getPath());
ti.addAttribute("fullName",fi.getFullName());
ti.addAttribute("isload","false");
if(fi.getPriority() != null)
ti.addAttribute("priority",fi.getPriority().toString());
if(fi.getParentId() != null)
ti.addAttribute("parentId",fi.getParentId().toString());
rtn.add(ti);
}
}
else
{
List<PermissionInfo> perms = orgmodel.getPermissionByFuncId(id);
for(PermissionInfo pi:perms)
{
TreeNode ti = new TreeNode();
ti.setId(pi.getId().toString());
ti.setText(pi.getName());
ti.setIconCls("pic_1");
ti.setUrl("");
ti.setState("open");
ti.addAttribute("path","");
ti.addAttribute("fullName","");
ti.addAttribute("isload","true");
ti.addAttribute("permission",pi.getPermission());
ti.addAttribute("funcId",pi.getFuncId());
rtn.add(ti);
}
}
return rtn;
}
@RequestMapping("/modulesave.action")
@ResponseBody
public Boolean modulesave(PermissionInfo perm)
{
String id = perm.getId();
if("".equals(Util.fmtStr(id)))
{
perm.setId(UUID.create("perm"));
orgmodel.savePermission(perm);
}
else
orgmodel.updatePermission(perm);
return true;
}
@RequestMapping("/moduleloadfunc.action")
@ResponseBody
public List moduleloadfunc()
{
return orgmodel.getAllFunc();
}
@RequestMapping("/moduleroleload.action")
@ResponseBody
public Map loadmodule(String funcId,String roleId,Integer page,Integer rows)
{
PageHelper.startPage(page, rows);
List<PermissionInfo> lists = orgmodel.getPermission(funcId,funcId,roleId);
PageInfo pi = new PageInfo(lists);
Long total = pi.getTotal();
List<PermissionInfo> perms = pi.getList();
Map m = new HashMap();
m.put("total", total);
m.put("rows", perms);
return m;
}
@RequestMapping("/moduleroledelete.action")
@ResponseBody
public Boolean moduleroledelete(String[] id)
{
if(id != null)
{
for(String id2:id)
{
orgmodel.deletePerm2RoleById(id2);
}
}
return true;
}
@RequestMapping("/modulerolesave.action")
@ResponseBody
public Boolean modulerolesave(String[] permId,String[] roleId)
{
if(permId != null && roleId != null)
{
for(String permId2:permId)
{
//判断前台选中的是功能节点还是权限节点
if(permId2.startsWith("perm"))//是权限节点
{
orgmodel.deletePerm2RoleByPermId(permId2);
for(String roleId2:roleId)
{
if(!"".equals(Util.fmtStr(permId2)) && !"".equals(Util.fmtStr(roleId2)))
{
Perm2RoleInfo p2r = new Perm2RoleInfo();
p2r.setId(UUID.create("p2r"));
p2r.setPermId(permId2);
p2r.setRoleId(roleId2);
orgmodel.savePerm2Role(p2r);
}
}
}
else//是功能节点
{
FunctionInfo fi = orgmodel.getFuncById(permId2);
if(fi != null)
{
//根据路径查询所有子节点列表
List<FunctionInfo> child = orgmodel.getListByPath(fi.getPath());
for(FunctionInfo fi2:child)
{
//根据模块ID查询所有权限
List<PermissionInfo> perms = orgmodel.getPermissionByFuncId(fi2.getId());
//遍历所有权限
for(PermissionInfo pi:perms)
{
//删除已授权权限,重新授权
orgmodel.deletePerm2RoleByPermId(pi.getId());
//遍历角色
for(String roleId2:roleId)
{
if(!"".equals(Util.fmtStr(pi.getId())) && !"".equals(Util.fmtStr(roleId2)))
{
Perm2RoleInfo p2r = new Perm2RoleInfo();
p2r.setId(UUID.create("p2r"));
p2r.setPermId(pi.getId());
p2r.setRoleId(roleId2);
orgmodel.savePerm2Role(p2r);
}
}
}
}
}
}
}
}
return true;
}
JSP页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String webCtx = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<script type="text/javascript" src="<%=webCtx %>/static/easyui/jquery.min.js"></script>
<script type="text/javascript" src="<%=webCtx %>/static/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="<%=webCtx %>/static/easyui/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" href="<%=webCtx %>/static/easyui/themes/default/easyui.css"/>
<link rel="stylesheet" href="<%=webCtx %>/static/easyui/themes/icon.css"/>
<link rel="stylesheet" href="<%=webCtx %>/static/easyui/myicon.css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
function reloadtree()
{
$.get('/modulefuncroot.action',function(data)
{
$('#tree').tree({
data: data
});
}
)
}
function addperm()
{
$('#id').val('');
$('#funcId').val('');
var nodes = $('#tree').tree('getChecked');
if(nodes.length != 1)
{
$.messager.alert('提示','请选择唯一功能模块');
return;
}
for(var i=0;i<nodes.length;i++)
{
funcid=nodes[i].id;
}
if(funcid == 'root')
{
$.messager.alert('提示','禁止选择根节点');
return;
}
if(funcid.substr(0,4) == 'perm')
{
$.messager.alert('提示','请选择唯一功能模块,不能选择权限节点');
return;
}
var rtn = $('#frm').form('validate');
if(rtn)
{
$('#funcId').val(funcid);
$('#frm').form('submit', {
url:'/modulesave.action',
onSubmit: function(){
},
success:function(data){
reloadtree();
}
});
}
}
function saveperm()
{
var funcid = $('#funcId').val();
if(funcid == null || funcid =='')
{
var nodes = $('#tree').tree('getChecked');
if(nodes.length != 1)
{
$.messager.alert('提示','请选择唯一功能模块');
return;
}
for(var i=0;i<nodes.length;i++)
{
funcid=nodes[i].id;
}
if(funcid == 'root')
{
$.messager.alert('提示','禁止选择根节点');
return;
}
if(funcid.substr(0,4) == 'perm')
{
$.messager.alert('提示','请选择唯一功能模块,不能选择权限节点');
return;
}
}
var rtn = $('#frm').form('validate');
if(rtn)
{
$('#funcId').val(funcid);
$('#frm').form('submit', {
url:'/modulesave.action',
onSubmit: function(){
},
success:function(data){
reloadtree();
}
});
}
}
function deleteperm()
{
var nodes = $('#tree').tree('getChecked');
var id = '';
for(var i=0;i<nodes.length;i++)
{
if(nodes[i].id.substr(0,4) == 'perm')
id = id + nodes[i].id + ',';
}
$.ajax({
url:'/moduledelete.action?id='+id,
success:function(data)
{
reloadtree();
}
})
}
$(document).ready(function()
{
reloadtree();
$('#tree').tree({
onBeforeExpand:function(node,param)
{
if(node.attributes.isload=='false')
{
$.ajaxSettings.async = false;
var url = '/modulegettreebyid.action?id='+node.id;
$.get(url,function(data)
{
$('#tree').tree('append', {
parent: node.target,
data: data
});
}
)
$.ajaxSettings.async = true;
node.attributes.isload = 'true';
}
},
onExpand: function(node){
},
onClick: function(node){
//如果是点击末级权限节点,窗口显示信息,权限ID以perm为前缀
if(node.id.substr(0,4) == 'perm')
{
$('#id').val(node.id);
$('#name').textbox('setValue',node.text);
$('#funcId').val(node.attributes.funcId);
$('#permission').textbox('setValue',node.attributes.permission);
}
}
})
}
);
</script>
</head>
<body class="easyui-layout">
<div data-options="region:'west',title:'功能模块导航'" style="width:200px;padding:0px;">
<ul id="tree" class="easyui-tree" data-options="checkbox:true,cascadeCheck:false,lines:true">
</ul>
</div>
<div data-options="region:'center',title:'模块权限管理'">
<form id="frm" method="post">
<input type="hidden" id="id" name="id"/>
<input type="hidden" id="funcId" name="funcId"/>
<div style="margin-left:50px;margin-top:30px">
<input class="easyui-textbox" type="text" id="name" name="name" data-options="required:true,label:'权限名称:',width:300" />
</div>
<div style="margin-left:50px;margin-top:30px">
<input class="easyui-textbox" type="text" id="permission" name="permission" data-options="required:true,label:'权限代码:',width:300" />
</div>
<div style="margin-left:50px;margin-top:30px">
<a id="btn" onclick="addperm()" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-save'">新增模块权限</a>
<a id="btn" onclick="saveperm()" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-save'">保存模块权限</a>
<a id="btn" onclick="deleteperm()" href="#" class="easyui-linkbutton" data-options="iconCls:'icon-remove'">删除模块权限</a>
</div>
</form>
</div>
</body>
</html>
界面效果
权限授权角色页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String webCtx = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<script type="text/javascript" src="<%=webCtx %>/static/easyui/jquery.min.js"></script>
<script type="text/javascript" src="<%=webCtx %>/static/easyui/jquery.easyui.min.js"></script>
<script type="text/javascript" src="<%=webCtx %>/static/easyui/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" href="<%=webCtx %>/static/easyui/themes/default/easyui.css"/>
<link rel="stylesheet" href="<%=webCtx %>/static/easyui/themes/icon.css"/>
<link rel="stylesheet" href="<%=webCtx %>/static/easyui/myicon.css"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
function reloadtree()
{
$.get('/modulefuncroot.action',function(data)
{
$('#tree').tree({
data: data
});
}
)
}
function reloadroletree()
{
$.get('/roleroot.action',function(data)
{
$('#roletree').tree({
data: data
});
}
)
}
function addperm()
{
var nodes = $('#tree').tree('getChecked');
if(nodes.length == 0)
{
$.messager.alert('提示','请选择模块或者权限节点,选择模块节点时将授权此模块下所有权限');
return;
}
var permId = '';
for(var i=0;i<nodes.length;i++)
{
permId = permId + nodes[i].id + ',';
}
var nodes2 = $('#roletree').tree('getChecked');
if(nodes2.length == 0)
{
$.messager.alert('提示','请选择角色节点');
return;
}
var roleId = '';
for(var i=0;i<nodes2.length;i++)
{
roleId = roleId + nodes2[i].id + ',';
}
console.log('roleid='+roleId+',permid='+permId);
$.ajax({
url:'/modulerolesave.action?permId='+permId+"&roleId="+roleId,
success:function(data)
{
$('#permdg').datagrid('reload');
}
})
}
function deleteperm()
{
var objs = $('#permdg').datagrid('getChecked');
var id = '';
for(i=0;i<objs.length;i++)
id = id + objs[i].id+ ',';
console.log('deleteperm id='+id);
$.ajax({
url:'/moduleroledelete.action?id='+id,
success:function(data)
{
$('#permdg').datagrid('reload');
}
})
}
$(document).ready(function()
{
reloadtree();
$('#tree').tree({
onBeforeExpand:function(node,param)
{
if(node.attributes.isload=='false')
{
$.ajaxSettings.async = false;
var url = '/modulegettreebyid.action?id='+node.id;
$.get(url,function(data)
{
$('#tree').tree('append', {
parent: node.target,
data: data
});
}
)
$.ajaxSettings.async = true;
node.attributes.isload = 'true';
}
},
onExpand: function(node){
},
onClick: function(node){
$('#permdg').datagrid({
url:'/moduleroleload.action?funcId='+node.id
});
}
});
$('#roletree').tree({
onClick: function(node){
$('#permdg').datagrid({
url:'/moduleroleload.action?roleId='+node.id
});
}
});
reloadroletree();
});
</script>
</head>
<body class="easyui-layout">
<div data-options="region:'west',title:'权限导航'" style="width:200px;padding:0px;">
<ul id="tree" class="easyui-tree" data-options="checkbox:true,cascadeCheck:false,lines:true">
</ul>
</div>
<div data-options="region:'center'">
<div id="p" class="easyui-panel" style="width:100%;height:100%" data-options="iconCls:'icon-save',closable:true">
<div class="easyui-layout" data-options="fit:true">
<div data-options="region:'west',title:'角色导航'" style="width:200px;padding:0px;">
<ul id="roletree" class="easyui-tree" data-options="checkbox:true,cascadeCheck:false,lines:true">
</ul>
</div>
<div data-options="region:'center',title:'权限管理'">
<table id="permdg" class="easyui-datagrid" style="width:100%;height:100%"
data-options="url:'/moduleroleload.action',fitColumns:true,pagination:true,
pageSize:10,pageList:[10,50,100,200],toolbar:'#tb'">
<thead>
<tr>
<th data-options="field:'id',width:100,checkbox:true">ID</th>
<th data-options="field:'funcName',width:100">模块名称</th>
<th data-options="field:'name',width:100">权限名称</th>
<th data-options="field:'permission',width:100">权限代码</th>
<th data-options="field:'roleName',width:100">授权角色</th>
</tr>
</thead>
</table>
<div id="tb">
<a id="btn" onclick="addperm()" class="easyui-linkbutton" data-options="iconCls:'icon-add'">添加授权</a>
<a id="btn" onclick="deleteperm()" class="easyui-linkbutton" data-options="iconCls:'icon-remove'">删除授权</a>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
效果图
代码下载
git clone -b day11 https://github.com/qixiangchen/gufang_fisys.git