上些章节我们都学习了shiro中的各种实际应用技巧,今天我想讲的是如何动态控制页面节点权限,相信这个控制对于很多玩权限的人来说都是一个比较头痛的,
因为这实在不怎么好统一控制的,现在我来展示下我通过shiro是如何实现的,算是抛砖引玉,希望大家有更好的解决方案,可以相互学习;下面就直接进入主题不啰嗦了
之前我们已经学习了如何在项目启动的时候加载所有的资源角色,包括第三方资源,下面我再帖上加长加粗版的代码方便说明
package com.silvery.security.shiro.service.impl;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.shiro.cache.Cache;
import org.springframework.beans.factory.annotation.Autowired;
import com.silvery.project.cms.model.Authority;
import com.silvery.project.cms.model.Permission;
import com.silvery.project.cms.service.PermissionService;
import com.silvery.project.cms.vo.PermissionVo;
import com.silvery.security.shiro.cache.SimpleMapCache;
import com.silvery.security.shiro.cache.extend.SimpleCacheManager;
import com.silvery.security.variable.Const;
/**
*
* 加载第三方角色资源配置服务类
*
* @author shadow
*
*/
public class SimpleFilterChainDefinitionsService extends AbstractFilterChainDefinitionsService {
@Autowired
private SimpleCacheManager simpleCacheManager;
@Autowired
private PermissionService permissionService;
@Override
public Map initOtherPermission() {
return converResultMap(initOperation());
}
@SuppressWarnings("unchecked")
private Map
1. 加载所有资源,包括请求URL,元素节点等数据,我这里为了演示,没有分那么细就只有两种
2. 请求URL的直接放到框架中,形式如/user/list.do*=role[root,user],跟我们shiro.xml配置的一样
3. 元素节点则相应放到以键值对的形式放到缓存,以节点的编号组合成key保证可以找到这个缓存对,值是相应的角色集合
我们的缓存就存在各个资源所需要的角色集合, 加载数据步骤已经完毕了下面看看我们是怎么应用的
首先我是使用springMVC+freemarker作为展现层,具体怎么配置整合我也不说,百度一堆,直接看我帖代码说明
欢迎主页
${username!"游客"}, 欢迎您的访问!
可选操作:
<#if username??>
<@sec id="2" body="用户列表" />权限列表资源列表注销退出
<#else>
前往登录
#if>
然后我们怎么通过这个标签来判定是否在页面渲染body的节点内容呢?
下面我们看看这个@sec的实现
package com.silvery.core.freemarker;
import java.io.IOException;
import java.util.Map;
import java.util.Set;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import com.silvery.security.shiro.cache.extend.SimpleCacheManager;
import com.silvery.security.variable.Const;
import freemarker.core.Environment;
import freemarker.template.TemplateDirectiveBody;
import freemarker.template.TemplateDirectiveModel;
import freemarker.template.TemplateException;
import freemarker.template.TemplateModel;
/**
*
* FreeMarker自定义标签,节点权限控制
*
* @author shadow
*
*/
public class SecurityTag implements TemplateDirectiveModel {
@Autowired
private SimpleCacheManager simpleCacheManager;
@SuppressWarnings("unchecked")
public void execute(Environment env, Map params, TemplateModel[] loopVars, TemplateDirectiveBody directiveBody)
throws TemplateException, IOException {
Object id = params.get("id");
Object body = params.get("body");
validate(id, body);
if (hasRole(id)) {
env.getOut().write(body.toString());
} else {
env.getOut().write("");
}
}
private void validate(Object id, Object body) throws TemplateException {
if (id == null || id.toString().trim().equals("")) {
throw new TemplateException("参数[id]不能为空", null);
}
if (body == null) {
throw new TemplateException("参数[body]不能为空", null);
}
}
@SuppressWarnings("unchecked")
private boolean hasRole(Object id) {
Cache cache = simpleCacheManager.getCache(Const.OTHER_PERMISSSION_CACHE_NAME + "_" + id);
if (cache == null) {
return false;
} else {
Object obj = cache.get(Const.OTHER_PERMISSSION_CACHE_NAME);
if (obj == null) {
return false;
}
Set authoritySet = (Set) obj;
Subject subject = SecurityUtils.getSubject();
for (String authority : authoritySet) {
if (subject.hasRole(authority)) {
return true;
}
}
}
return false;
}
}
如Subject拥有角色[root,user],而x编号资源拥有[user,test]角色,很明显有交集会认证通过,反之则直接渲染空字符
大概流程就是这样,有的人可能会问,如何配置这个tag实现类呢?我帖下spring-mvc.xml的freemarker配置
10
zh_CN
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd
#.####
版权声明:本文为博主原创文章,未经博主允许不得转载。