您好,欢迎访问三七文档
Shiro学习Shiro简介ApacheShiro是java的安全框架。Shiro可以非常容易的开发出足够好的应用,可以帮我们完成:认证、授权、加密、会话管理、与Web集成、缓存等。Authentication:身份认证/登录,验证用户是不是拥有相应的身份;Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;SessionManager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;WebSupport:Web支持,可以非常容易的集成到Web环境;Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;Testing:提供测试支持;RunAs:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;RememberMe:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了。记住一点,Shiro不会去维护用户、维护权限;这些需要我们自己去设计/提供;然后通过相应的接口注入给Shiro即可。2.身份验证2.2环境准备1.dependencies2.dependency3.groupIdjunit/groupId4.artifactIdjunit/artifactId5.version4.9/version6./dependency7.dependency8.groupIdcommons-logging/groupId9.artifactIdcommons-logging/artifactId10.version1.1.3/version11./dependency12.dependency13.groupIdorg.apache.shiro/groupId14.artifactIdshiro-core/artifactId15.version1.2.2/version16./dependency17./dependencies添加junit、common-logging及shiro-core依赖即可。2.3登录/退出1、首先准备一些用户身份/凭据(shiro.ini)Java代码1.[users]2.zhang=1233.wang=123此处使用ini配置文件,通过[users]指定了两个主体:zhang/123、wang/123。2、测试用例(com.github.zhangkaitao.shiro.chapter2.LoginLogoutTest)Java代码1.@Test2.publicvoidtestHelloworld(){3.//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager4.Factoryorg.apache.shiro.mgt.SecurityManagerfactory=5.newIniSecurityManagerFactory(classpath:shiro.ini);6.//2、得到SecurityManager实例并绑定给SecurityUtils7.org.apache.shiro.mgt.SecurityManagersecurityManager=factory.getInstance();8.SecurityUtils.setSecurityManager(securityManager);9.//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)10.Subjectsubject=SecurityUtils.getSubject();11.UsernamePasswordTokentoken=newUsernamePasswordToken(zhang,123);12.13.try{14.//4、登录,即身份验证15.subject.login(token);16.}catch(AuthenticationExceptione){17.//5、身份验证失败18.}19.20.Assert.assertEquals(true,subject.isAuthenticated());//断言用户已经登录21.22.//6、退出23.subject.logout();24.}25.2.1、首先通过newIniSecurityManagerFactory并指定一个ini配置文件来创建一个SecurityManager工厂;2.2、接着获取SecurityManager并绑定到SecurityUtils,这是一个全局设置,设置一次即可;2.3、通过SecurityUtils得到Subject,其会自动绑定到当前线程;如果在web环境在请求结束时需要解除绑定;然后获取身份验证的Token,如用户名/密码;2.4、调用subject.login方法进行登录,其会自动委托给SecurityManager.login方法进行登录;2.5、如果身份验证失败请捕获AuthenticationException或其子类,常见的如:DisabledAccountException(禁用的帐号)、LockedAccountException(锁定的帐号)、UnknownAccountException(错误的帐号)、ExcessiveAttemptsException(登录失败次数过多)、IncorrectCredentialsException(错误的凭证)、ExpiredCredentialsException(过期的凭证)等,具体请查看其继承关系;对于页面的错误消息展示,最好使用如“用户名/密码错误”而不是“用户名错误”/“密码错误”,防止一些恶意用户非法扫描帐号库;2.6、最后可以调用subject.logout退出,其会自动委托给SecurityManager.logout方法退出。从如上代码可总结出身份验证的步骤:1、收集用户身份/凭证,即如用户名/密码;2、调用Subject.login进行登录,如果失败将得到相应的AuthenticationException异常,根据异常提示用户错误信息;否则登录成功;3、最后调用Subject.logout进行退出操作。如上测试的几个问题:1、用户名/密码硬编码在ini配置文件,以后需要改成如数据库存储,且密码需要加密存储;2、用户身份Token可能不仅仅是用户名/密码,也可能还有其他的,如登录时允许用户名/邮箱/手机号同时登录。3.授权3.1Shiro的三种方式授权编程式:通过写if/else授权代码块完成Subjectsubject=SecuriryUtils.getSubject();If(subject.hasRole(“admin”)){//有权限}else{//无权限}注解式:通过在执行的java方法上放置相应的注解完成@RequiresRoles(“admin”)Publicvoidhello(){//有权限}JSP/GSP标签:在JSP/GSP页面通过相应的标签完成shiroLhasRolename=”admin”!--有权限—/shiro:hasRole3.2授权基于角色的访问控制(隐式角色)1、在ini配置文件配置用户拥有的角色(shiro-role.ini)Java代码1.[users]2.zhang=123,role1,role23.wang=123,role1规则即:“用户名=密码,角色1,角色2”,如果需要在应用中判断用户是否有相应角色,就需要在相应的Realm中返回角色信息,也就是说Shiro不负责维护用户-角色信息,需要应用提供,Shiro只是提供相应的接口方便验证,后续会介绍如何动态的获取用户角色。2、测试用例(com.github.zhangkaitao.shiro.chapter3.RoleTest)Java代码1.@Test2.publicvoidtestHasRole(){3.login(classpath:shiro-role.ini,zhang,123);4.//判断拥有角色:role15.Assert.assertTrue(subject().hasRole(role1));6.//判断拥有角色:role1androle27.Assert.assertTrue(subject().hasAllRoles(Arrays.asList(role1,role2)));8.//判断拥有角色:role1androle2and!role39.boolean[]result=subject().hasRoles(Arrays.asList(role1,role2,role3));10.Assert.assertEquals(true,result[0]);11.Assert.assertEquals(true,result[1]);12.Assert.assertEquals(false,result[2]);13.}Shiro提供了hasRole/hasRole用于判断用户是否拥有某个角色/某些权限;但是没有提供如hashAnyRole用于判断是否有某些权限中的某一个。Java代码1.@Test(expected=UnauthorizedException.class)2.publicvoidtestCheckRole(){3.login(classpath:shiro-role.ini,zhang,123);4.//断言拥有角色:role15.subject().checkRole(role1);6.//断言拥有角色:role1androle3失败抛出异常7.subject().checkRoles(role1,role3);8.}Shiro提供的checkRole/checkRoles和hasRole/hasAllRoles不同的地方是它在判断为假的情况下会抛出UnauthorizedException异常。到此基于角色的访问控制(即隐式角色)就完成了,这种方式的缺点就是如果很多地方进行了角色判断,但是有一天不需要了那么就需要修改相应代码把所有相关的地方进行删除;这就是粗粒度造成的问题。3.3Permission字符串通配符权限规则:“资源标识符:操作:对象实例ID”即对哪个资源的哪个实例可以进行什么操作。其默认支持通配符权限字符串,“:”表示资源/操作/实例的分割;“,”表示操作的分割;“*”表示任意资源/操作/实例。1、单个资源单个权限Java代码1.subject().checkPermissions(system:user:update);用户拥有资源“system:user”的“update”权限。2、单个资源多个权限ini配置文件Java代码1.role41=system:user:update,system:user:delete然后通过如下代码判断Java代码1.subject().checkPermissions(system:user:update,system:user:delete);用户拥有资源“system:user”的“update”和“delete”权限。如上可以简写成:ini配置(表示角色4拥有system:user资源的update和delete权限)Java代码1.role42=system:user:update,delete接着可以通过如下代码判断Java代码1.subject()
本文标题:Shiro学习
链接地址:https://www.777doc.com/doc-2858421 .html