Apache shiro集群实现 (一) shiro入门介绍
Apache shiro集群实现 (二) shiro 的INI配置
Apache shiro集群实现 (三)shiro身份认证(Shiro Authentication)
Apache shiro集群实现 (四)shiro授权(Authentication)--访问控制
Apache shiro集群实现 (五)分布式集群系统下的高可用session解决方案
Apache shiro集群实现 (六)分布式集群系统下的高可用session解决方案---Session共享
授权(Authorization)也叫做访问控制,是一个对资源的访问进行管理的过程,也就是说在应用程序汇总,谁有怎样的权限(用户可以看到什么内容,可以进行什么操作)。
在ITOO项目中,首先是考虑基于角色的授权,当用户的角色发生变化的时候,不灵活,所以为了更好的结合项目的实际情况,是采用的通过字符串的方式的权限验证;当然针对后台的方法的可以采用注解式的权限控制(可以用户类/属性/方法,用于表明当前用户需是经过认证的用户)。
权限
权限是shiro权限系统中的原子单位,明确定义了用户的行为,例如用户在系统中可以做什么不可以做什么。
例如:下载某个文件,访问/user/list链接,删除用户等等。权限一般都是基于资源和对资源的操作(例如CRUD等)的。
权限只是反映了行为(对资源的操作),不反应谁去执行。权限要分配给用户,或者角色,来确定哪些用户拥有某些权限。
资源
系统中的所有可访问,可操作的所有的东西。例如,系统中的链接,按钮,方法,等等。
用户
也叫主体(Subjects),访问应用的人或者其他的,例如另一个应用程序。用户只有被授权了才可以访问系统的资源。
权限是Apache Shiro安全机制最核心的元素。它在应用程序中明确声明了被允许的行为和表现。一个格式良好好的权限声明可以清晰表达出用户对该资源拥有的权限。
大多数的资源会支持典型的CRUD操作(create,read,update,delete),但是任何操作建立在特定的资源上才是有意义的。因此,权限声明的根本思想就是建立在资源以及操作上。
而我们通过权限声明仅仅能了解这个权限可以在应用程序中做些什么,而不能确定谁拥有此权限。 于是,我们就需要在应用程序中对用户和权限建立关联。 通常的做法就是将权限分配给某个角色,然后将这个角色关联一个或多个用户。
一个角色代表着一系列的操作,当需要对某一操作进行授权验证时,只需判断是否是该角色即可。这种角色权限相对简单、模糊,不利于扩展。
一个角色拥有一个权限的集合。授权验证时,需要判断当前角色是否拥有该权限。这种角色权限可以对该角色进行详细的权限描述,适合更复杂的权限设计。
下面将详细描述对两种角色模式的授权实现。
下面将详细描述对两种角色模式的授权实现。
Shiro支持三种方式实现授权过程:
• 编码实现
• 注解实现
• JSP Taglig实现
1、在应用程序中调用授权验证方法(Subject的isPermitted*或hasRole*等)
2、Subject的实例通常是DelegatingSubject类(或子类)的实例对象,在认证开始时,会委托应用程序设置的securityManager实例调用相应的isPermitted*或hasRole*方法。
3、接下来SecurityManager会委托内置的Authorizer的实例(默认是ModularRealmAuthorizer 类的实例,类似认证实例,它同样支持一个或多个Realm实例认证)调用相应的授权方法。
4、每一个Realm将检查是否实现了相同的 Authorizer 接口。然后,将调用Reaml自己的相应的授权验证方法。
在认证、授权内部实现机制中都有提到,最终处理都将交给Real进行处理。因为在Shiro中,最终是通过Realm来获取应用程序中的用户、角色及权限信息的。通常情况下,在Realm中会直接从我们的数据源中获取Shiro需要的验证信息。可以说,Realm是专用于安全框架的DAO.
正如前文所提到的,Shiro的认证过程最终会交由Realm执行,这时会调用Realm的getAuthenticationInfo(token)方法。
该方法主要执行以下操作:
1、检查提交的进行认证的令牌信息
2、根据令牌信息从数据源(通常为数据库)中获取用户信息
3、对用户信息进行匹配验证。
4、验证通过将返回一个封装了用户信息的AuthenticationInfo实例。
5、验证失败则抛出AuthenticationException异常信息。
而在我们的应用程序中要做的就是自定义一个Realm类,继承AuthorizingRealm抽象类,重载doGetAuthenticationInfo (),重写获取用户信息的方法。
Java代码
而授权实现则与认证实现非常相似,在我们自定义的Realm中,重载doGetAuthorizationInfo()方法,重写获取用户权限的方法即可。
Java代码
<span style="font-size:18px;"><span style="font-size:18px;">1.protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException { 2. UsernamePasswordToken token = (UsernamePasswordToken) authcToken; 3. User user = accountManager.findUserByUserName(token.getUsername()); 4. if (user != null) { 5. return new SimpleAuthenticationInfo(user.getUserName(), user.getPassword(), getName()); 6. } else { 7. return null; 8. } 9. } </span></span>
二、授权实现
根据角色解析相应的权限集合。
<span style="font-size:18px;"><span style="font-size:18px;">package com.tgb.itoo.authority.service; import java.util.Iterator; import java.util.List; import javax.annotation.Resource; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.cache.Cache; import org.apache.shiro.cache.CacheManager; import org.apache.shiro.cas.CasRealm; import org.apache.shiro.session.Session; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import com.tgb.itoo.authority.entity.AllUsers; public class ShiroRealmBean extends CasRealm { // 用于获取用户信息及用户权限信息的业务接口 private ShiroBean permissionMgr; // 授权 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 权限名称 String permissionName; try { // 查询用户授权信息 SimpleAuthorizationInfo author = new SimpleAuthorizationInfo(); // 查找登录用户名称 String username = (String) principals.getPrimaryPrincipal(); System.out.println(username); // 查询用户对应角色对应的资源 List<String> lstPermission = permissionMgr .queryUserPermission(username); // 迭代查询 Iterator<String> it = lstPermission.iterator(); while (it.hasNext()) { permissionName = it.next().toString(); // 把资源名称添加到用户所对于的资源集合中 author.addStringPermission(permissionName); } return author; } catch (Exception e) { e.printStackTrace(); return null; } } public ShiroBean getPermissionMgr() { return permissionMgr; } public void setPermissionMgr(ShiroBean permissionMgr) { this.permissionMgr = permissionMgr; } }</span></span>
在jsp页面我们引入shiro标签
<span style="font-size:18px;"><span style="font-size:18px;"><%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%></span></span>
<span style="font-size:18px;"><span style="font-size:18px;"><shiro:hasPermission name="itoo-authority-role-role-add"> <a href="javascript:void(0)" id="btnAdd" class="easyui-linkbutton" style="height: 30px; width: 60px" iconCls="icon-add" plain="true" onclick="addRoleUI()">添加</a> </shiro:hasPermission> <shiro:hasPermission name="itoo-authority-role-role-edit"> <a href="javascript:void(0)" id="btnEdit" class="easyui-linkbutton" style="height: 30px; width: 60px" iconCls="icon-edit" plain="true" onclick="editRoleUI()">编辑</a> </shiro:hasPermission> <shiro:hasPermission name="itoo-authority-role-role-delete"> <a href="javascript:void(0)" id="btnDel" class="easyui-linkbutton" style="height: 30px; width: 60px" iconCls="icon-remove" plain="true" onclick="deleteRole()">删除</a> </shiro:hasPermission></span></span>
基于角色解析的相应的权限集合实现了按钮和资源的控制,接下来一起学习解决session,共享、资源cache共享 ,结合redis来实现,首先我们应该学习高可用性集群下的相关内容