前言 新的公司让我去熟悉下Shiro框架,公司的项目的权限管理都是基于Shiro写的,照着前辈们的blog学习了一番,这里做点个人学习记录。
Shiro的整体架构图
</div>
首先是Shiro的几个组件
SecurityManager 即所有Subject的管理者,这是Shiro框架的核心组件,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务。
Authenticator 认证器,登入登出,对“Who are you?”进行核实。通常涉及用户名和密码。
Authorizer 授权器,赋予主体有哪些权限,身份验证通过后,由这个组件对登录人员进行访问控制的筛查,比如“who can do what”, 或者“who can do which actions”。Shiro 采用“基于 Realm”的方法,即用户(又称 Subject)、用户组、角色和 permission 的聚合体。
Session Manager 这个组件保证了异构客户端的访问,配置简单。它是基于POJO/J2SE的,不跟任何的客户端或者协议绑定。
Subject 即当前用户,在权限管理的应用程序里往往需要知道谁能够操作什么,谁拥有操作该程序的权利,shiro中则需要通过Subject来提供基础的当前用户信息,Subject 不仅仅代表某个用户,也可以是第三方进程、后台帐户(Daemon Account)或其他类似事物。
Realms Realms也就是域,是用户的信息认证器和用户的权限人证器,我们需要自己来实现Realms来自定义的管理我们自己系统内部的权限规则。
通过ini文件来自定义Realm Maven依赖
1 2 3 4 5 <dependency > <groupId > org.apache.shiro</groupId > <artifactId > shiro-core</artifactId > <version > 1.2.3</version > </dependency >
shiro.ini
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 [users] root = 123 ,adminuser001 = 123 ,productManageruser002 = 123 ,orderManager[roles] admin = *productManager = addProduct,deleteProduct,editProduct,listProductorderManager = addOrder,deleteOrder,editOrder,listOrder
这里分配了三种角色各自拥有不同的权限
admin
productManager
addProduct
deleteProduct
editProduct
listProduct
orderManager
addOrder
deleteOrder
editOrder
listOrder
Tutorial .java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 package shiro;import org.apache.shiro.SecurityUtils;import org.apache.shiro.authc.*;import org.apache.shiro.config.IniSecurityManagerFactory;import org.apache.shiro.mgt.SecurityManager;import org.apache.shiro.session.Session;import org.apache.shiro.subject.Subject;import org.apache.shiro.util.Factory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;public class Tutorial { private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class); public static void main (String[] args) { Factory<SecurityManager> factory = new IniSecurityManagerFactory ("classpath:shiro.ini" ); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); Subject currentUser = SecurityUtils.getSubject(); Session session = currentUser.getSession(); session.setAttribute("oneKey" ,"aValue" ); String value = (String)session.getAttribute("oneKey" ); if (value.equals("trueValue" )) { log.info("值正确![" + value +"]" ); } else { log.info("value有错误哦!您的value:[" + value+"]" ); } log.info("\n**********************是否登陆成功*********************\n" ); if (!currentUser.isAuthenticated()) { String username = "user001" , password = "1123" ; UsernamePasswordToken token = new UsernamePasswordToken (username, password); token.setRememberMe(true ); try { currentUser.login(token); log.info("你居然登陆上了,牛逼" ); log.info("\n**********************打印这些登陆用户的信息*********************\n" ); log.info("用户[" + currentUser.getPrincipal() + "] 登陆成功!" ); String roleName = "productManager" ; if (currentUser.hasRole(roleName)) { log.info("这个角色:[" + roleName + "]" ); } else { log.info("emmmm,mere mortal!" ); } log.info("\n**********************测试不同类型的权限*********************\n" ); if (currentUser.isPermitted("addProduct" )) { log.info("您可以对产品进行管理" ); } else { log.info("你不配使用" ); } if (currentUser.isPermitted("addOrder" )) { log.info("您可以对订单系统进行管理" ); } else { log.info("抱歉,你不配管理订单系统" ); } } catch (UnknownAccountException uae) { log.info("没有这个用户名:" + token.getPrincipal()); } catch (IncorrectCredentialsException ice) { log.info("这个账号" + token.getPrincipal() + "的密码是错的啦,try again?" ); } catch (LockedAccountException lae) { log.info("这个用户" + token.getPrincipal() + "已被封锁" + "请联系管理员解锁" ); } catch (AuthenticationException ae) { log.info("发生了一些未知的情况,请联系管理员!" ); } } currentUser.logout(); System.exit(0 ); } }
测试类Tutorial,通过UsernamePasswordToken
创建的token
对象来让Subject
(当前对象)进行登陆验证,认证通过后,可以用getPrincipal()
这个方法来获取当前对象的用户名.
角色相关验证方法
Subject方法
描述
hasRole(String roleName)
当用户拥有指定角色时,返回true
hasRoles(List roleNames)
按照列表顺序返回相应的一个boolean值数组
hasAllRoles(Collection roleNames)
如果用户拥有所有指定角色时,返回true
</br>
Subject方法
描述
checkRole(String roleName)
断言用户是否拥有指定角色
checkRoles(Collection roleNames)
断言用户是否拥有所有指定角色
checkRoles(String… roleNames)
对上一方法的方法重载
权限相关验证方法
Subject方法
说明
checkPermission(Permission p)
断言用户是否拥有制定权限
checkPermission(String perm)
断言用户是否拥有制定权限
checkPermissions(Collection perms)
断言用户是否拥有所有指定权限
checkPermissions(String… perms)
断言用户是否拥有所有指定权限
</br>
Subject方法
描述
isPermitted(Permission p)
Subject拥有制定权限时,返回true
isPermitted(List perms)
返回对应权限的boolean数组
isPermittedAll(Collection perms)
Subject拥有所有制定权限时,返回true