Contents
  1. 1. 参考资料
  2. 2. 前端控制逻辑
  3. 3. 后端控制的逻辑
  4. 4. User类
  5. 5. Shiro标签的使用
  6. 6. 整合ehcache
    1. 6.1. 配置
    2. 6.2. ehcache的权限清空缓存
  7. 7. 解决无权限不跳转设置JSP的问题

参考资料

shiro标签
https://www.cnblogs.com/fancongcong/p/8093258.html

前端控制逻辑

  1. 通过数据库查询控制menu,登录时查询该用户拥有权限的menu,然后foreach展示出来,这种方法不安全,而且控制不到某个按钮,但是最简单

  2. 通过shiro标签来控制,shiro标签认证会触发 授权认证,需要重写realm中add进相应的permission和role

后端控制的逻辑

通过设置规则,在进行后端资源访问的时候,会调用doGetAuthorizationInfo()方法,并且会比对info里面的权限和当前方法的url是否匹配,匹配则有权限访问,不匹配则无权限

  1. 通过配置文件url控制,支持通配符匹配,方便实现 路径对权限,或者路径对角色的控制

    /user/test=roles[admin]
    /user/test=perms["user:test"]
  2. 通过注解进行方法控制

    @RequiresPermissions("user:test")
    @RequestMapping("test")
    public String test() {
    return "hello WRN";
    }
    @RequiresRoles("admin")
    @RequestMapping("test")
    public String test() {
    return "hello WRN";
    }

常用注解

@RequiresAuthenthentication:表示当前Subject已经通过login进行身份验证;即 Subjec.isAuthenticated()返回 true
@RequiresUser:表示当前Subject已经身份验证或者通过记住我登录的
@RequiresGuest:表示当前Subject没有身份验证或者通过记住我登录过,即是游客身份
@RequiresRoles(value = {"admin","user"},logical = Logical.AND):表示当前Subject需要角色admin和user
@RequiresPermissions(value = {"user:delete","user:b"},logical = Logical.OR):表示当前Subject需要权限user:delete或者user:b

User类

public class User implements Serializable {
private Integer id;
private String username;//帐号
private String name;//名称(昵称或者真实姓名,不同系统不同定义)
private String password; //密码;
private List<Role> roleList;// 一个用户具有多个角色
}
  • 常规设置路径–> permission的时候,常规的认证 用户访问方法 –> 查找用户所有的角色 –>遍历角色的资源添加进去,然后匹配

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
    UserInfo userInfo = (UserInfo)principals.getPrimaryPrincipal();
    for(SysRole role:userInfo.getRoleList()){
    authorizationInfo.addRole(role.getRole());
    for(SysPermission p:role.getPermissions()){
    authorizationInfo.addStringPermission(p.getPermission());
    }
    }
    return authorizationInfo;
    }
  • 如果权限控制时需要实现 访问路径 –> 角色的话,则User类必须要设置 List的字段,且add进info里面

    过滤器里面设置,/user/test的资源需要有admin权限的用户才可以访问, 用户-->role
    /user/test=roles[admin]
    info权限认真的时候,把role设置到info里面,这样就可以实现完整的用户对角色路径的权限访问
    User user = (User) principals.getPrimaryPrincipal();
    List<Role> roleList=roleService.getRoleListByUserId(user.getId());
    for(Role role :roleList){
    if (StringUtil.isNotEmpty(role.getName())) {
    info.addRole(role.getName());
    }
    }

Shiro标签的使用

如果jsp里面有权限标签,会触发 权限认证并且从info中check是否有权限

  • 引入依赖

    <%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>
  • principal 标签:显示用户身份信息,默认调用
    Subjec.getPrincipal()获取,即Primary Principal

    属性是set进去的User类的属性值,默认是username,如果User里面不是,则按照User里面的定
    <shiro:principal property = "userName"/>
  • authenticted 标签

    <shiro:authenticted>
    已身份验证通过
    </shiro:authenticted>
  • hasPermission、hasRole
    (需要在权限认证的时候往 info里面添加对应的 permission 和 role才能认证)

    <shiro:hasPermission name="user:setRole">
    <a href="#" class="btn btn-success btn-sm" data-code="user:setRole">
    <i class="icon-cog"></i>设置角色
    </a>
    </shiro:hasPermission>
    <shiro:hasRole name="god">
    welcome God!
    </shiro:hasRole>

整合ehcache

配置

可以实现查询授权登录的时候对用户info做缓存,大大提升效率,因为用户权限不会经常发生改变,非常实用的技术

  • 依赖jar包

    <dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-ehcache</artifactId>
    <version>${shiro.version}</version>
    </dependency>
    <dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-core</artifactId>
    <version>2.5.3</version>
    </dependency>
  • ehcache.xml配置

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd">
    <diskStore path="java.io.tmpdir"/>
    <defaultCache
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="120"
    timeToLiveSeconds="120"
    maxElementsOnDisk="10000000"
    diskExpiryThreadIntervalSeconds="120"
    memoryStoreEvictionPolicy="LRU">
    </defaultCache>
    </ehcache>
  • spring 配置

    <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
    <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
    </bean>
    <!-- 安全管理器 -->
    <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
    <property name="realm" ref="customRealm" />
    <property name="cacheManager" ref="cacheManager"/>
    </bean>

ehcache的权限清空缓存

在自定义Realm中添加clearCached()方法,来清空该用户的缓存。

//清除缓存
public void clearCached() {
PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
super.clearCache(principals);
}

在其他地方里面调用主动刷新缓存

@Autowired
private CustomRealm realm;
public void test(){
realm.clearCached();
}

解决无权限不跳转设置JSP的问题

https://www.cnblogs.com/qlong8807/p/5524381.html
直接在shiro里面专门配置一个跳转设置,记得是 MVC的重定向,在MVC路径下的JSP

<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.apache.shiro.authz.UnauthorizedException">/403</prop>
</props>
</property>
</bean>

Contents
  1. 1. 参考资料
  2. 2. 前端控制逻辑
  3. 3. 后端控制的逻辑
  4. 4. User类
  5. 5. Shiro标签的使用
  6. 6. 整合ehcache
    1. 6.1. 配置
    2. 6.2. ehcache的权限清空缓存
  7. 7. 解决无权限不跳转设置JSP的问题