在第一部分,使用shiro主要做了基于url的登陆拦截,但是在真正的生产环境下往往是注解,标签等综合使用,以下是基于注解和标签的代码笔记
URL拦截权限控制是基于过滤器或者拦截器的
方法注解权限控制是基于代理(action代理)
【1】spring配置中开启shiro注解
注意:这里最好开启cglib代理(产生的是子类对象),默认是jdk代理(新的代理对象)
知识拓展:
1.JDK动态代理
此时代理对象和目标对象实现了相同的接口
2.CGLIB代理
CGLIB(CODE GENERLIZE LIBRARY)代理是针对类实现代理,主要是对指定的类生成一个子类
具体查看:http://blog.csdn.net/cpzhong/article/details/6423333
另外注意:这里如果使用shiro了,在action中的baseAction就不能直接强转了,因为如果是jdk代理是action的新代理对象,而非action对象或者子类对象,所以强转会报错,这也是为什么要使用cglib代理的原因。
【2】方法上使用权限注解
/**
* 删除派遣员
* @return
*/
@RequiresPermissions(value="staff11")//执行当前方法需要具有staff权限
//@RequiresRoles(value="staff")//执行当前方法需要具有staff角色
public String delete(){
staffService.deleteBatch(ids);
/**
* 当权限或者角色任意一个不满足都会抛出org.apache.shiro.authz.UnauthorizedException:
* 异常,所以需要我们做公共异常捕获,在struts配置文件中配置公共异常捕获页面
*/
return "list";
}
【3】Realm中授权
在bosReaml的授权方法中授予相应权限
/**
* 授权方法(这个用户有什么权限)
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("进入授权方法... ...");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("staff");//为当前用户授予staff权限
//TODO 根据当前登录用户查询数据库,获取其对应的权限数据
return info;
}
【4】访问查看
(当授权是staff11是会正常操作删除方法,当授权非staff11时,我们分别授权staff11和staff,发现staff会报错,抛出异常org.apache.shiro.authz.UnauthorizedException)
当shiro使用注解时,遇到权限和角色不足时均会抛出org.apache.shiro.authz.UnauthorizedException异常,所以这里需要捕获处理
【5】struts中配置全局异常处理
/login.jsp
/unauthorizedUrl.jsp
修改后
使用标签进行资源控制
【1】jsp页面引入shiro标签
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
【2】对需要权限拦截的菜单 按钮进行拦截添加
这里主要shiro标签可以直接包html代码,也可以直接包js代码
//工具栏(给删除安全添加权限拦截)
var toolbar = [ {
id : 'button-view',
text : '查询',
iconCls : 'icon-search',
handler : doView
}, {
id : 'button-add',
text : '增加',
iconCls : 'icon-add',
handler : doAdd
}, {
id : 'button-delete',
text : '作废',
iconCls : 'icon-cancel',
handler : doDelete
}, {
id : 'button-save',
text : '还原',
iconCls : 'icon-save',
handler : doRestore
}];
注意:表示只有拥有staff11权限的用户才会显示该按钮
前后对比
【通过查询数据库,进行用户授权】
修改自定义Realm的授权方法
/**
* 授权方法(这个用户有什么权限)
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("进入授权方法... ...");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//info.addStringPermission("staff");//为当前用户授予staff权限
//info.addRole("staff");//为当前用户授予staff角色(角色是权限的集合)
//TODO 根据当前登录用户查询数据库,获取其对应的权限数据
//获取当前用户
User user = (User) principals.getPrimaryPrincipal();
List list = null;
if(user.getUsername().equals("admin")){
//超级管理员(查询所有权限)
list = functionDao.findAll();
}else{
//普通用户(查询拥有权限)
list = functionDao.findListByuserId(user.getId());
}
//授权
for(Function function : list){
info.addStringPermission(function.getCode());
}
return info;
}