我们前面做的权限控制都是建立在对URL的访问控制,我们把它称之为粗颗粒的访问控制。
我们还可以使用shiro的细颗粒授权控制。
细颗粒授权控制包括:方法级别 与 代码级别
对某个方法加访问控制,用户必须拥有某项权限才可以访问该方法,没有权限则抛出异常,无法访问。
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" >
<property name="proxyTargetClass" value="true" />
bean>
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
bean>
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
Subject subject = SecurityUtils.getSubject();
//采购订单申请
if(Orders.TYPE_IN.equals(orders.getType())) {
//代码级别的权限控制
//判断当前登录的用户是否有采购订单申请的权限
if(!subject.isPermitted("采购订单申请")) {
throw new ErpException("权限不足");
}
}else if(Orders.TYPE_OUT.equals(orders.getType())) {
if(!subject.isPermitted("销售订单录入")) {
throw new ErpException("权限不足");
}
}else {
throw new ErpException("非法参数");
}
我们在添加shiro框架后,每次执行功能都会调用授权方法,而每次调用都会执行很多查询,这样会影响效率。这么提升程序性能?我们可以考虑使用缓存数据库来实现。
Redis是一个高性能的key-value缓存系统。Redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部分场合可以对关系数据库起来很好的补充作用。它提供了Java, C++, C#, PHP, JavaScript, Perl, Object-C, pathon, Ruby, Erlang等客户端,使用很方便
安装
Windows无需安装,解压后即可使用
双击redis-server.exe即可启动服务
进入到reids-server.exe的上当下,在Dos提示符下输入命令,即可连接本地的Redis
如果是连接远程的Redis,则输入如下命令
此时表示连接成功
<bean id="jedis" class="redis.clients.jedis.Jedis" >
<constructor-arg index="0" value="127.0.0.1" > constructor-arg>
bean>
@Override
public List<Menu> getMenusByEmpuuid(Long uuid) {
// 1、尝试着从缓存当中去出menuList
String menuListJson = jedis.get("menuList_"+uuid);
List<Menu> menuList = null;
if (menuListJson != null) {
System.out.println("从缓存当中取出menuList");
//3、缓存当中已经存在,取出后再转换成为List对象
menuList = JSON.parseArray(menuListJson, Menu.class);
} else {
System.out.println("从数据库当中查询出menuList");
// 第一次查询
// 2.Jedis不支持对象的存储,支持字符串的存储,所以当第一次存入缓存的时候,就要转换成为JSON字符串存入
menuList = empDao.getMenusByEmpuuid(uuid);
jedis.set("menuList_"+uuid, JSON.toJSONString(menuList));
}
// return empDao.getMenusByEmpuuid(uuid);
return menuList;
}
// 更新用户角色
public void updateEmpRoles(Long uuid, String checkedStr) {
Emp emp = empDao.get(uuid);
// 清空该用户下的所有角色
emp.setRoles(new ArrayList<Role>());
String[] ids = checkedStr.split(",");
Role role = null;
for (String id : ids) {
role = roleDao.get(Long.valueOf(id));
// 设置用户的角色
emp.getRoles().add(role);
}
//清除缓存
try {
//清除缓存中当前用户的菜单权限
jedis.del("menuList_" + uuid);
} catch (Exception e) {
e.printStackTrace();
}
}
@JSONField(serialize=false)
private List<Emp> emps;//属于这个角色下的用户集合,@JSONField(serialize=false)阻止JSON序列化
public List<Emp> getEmps() {
return emps;
}
public void setEmps(List<Emp> emps) {
this.emps = emps;
}
<bag name="emps" order-by="empuuid" table="emp_role" >
<key column="roleuuid">key>
<many-to-many class="com.itzheng.erp.entity.Emp" column="empuuid" >many-to-many>
bag>
//1、通过角色反差属于这个角色的有哪些用户
List<Emp> empList = role.getEmps();
//2、清除这些用户的菜单权限缓存
try {
for (Emp emp :empList) {
//清除每个用户菜单权限缓存
jedis.del("menuList_" + emp.getUuid());
}
} catch (Exception e) {
e.printStackTrace();
}