第一讲、权限认证核心要素
权限认证,也就是访问控制,即在应用中控制谁能访问哪些资源。 在权限认证中,最核心的三个要素是:权限,角色和用户;
Authorization has three core elements that we reference quite a bit in Shiro: permissions, roles, and users.
权限permissions,即操作资源的权利,比如访问某个页面,以及对某个模块的数据的添加,修改,删除,查看的权利; 角色,是权限的集合,一中角色可以包含多种权限; 用户,在 Shiro 中,代表访问系统的用户,即 Subject;
第二讲、授权
一、编程式授权Programmatic Authorization
在pom添加junit依赖
<!-- https://mvnrepository.com/artifact/junit/junit --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
新建common包 ShiroUtil.java用于封装shiro/HelloWorld.java
将ini文件设置成参数configFile动态添加进来解析将用户名和密码也动态添加进来
package com.guo.common; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; public class ShiroUtil { public static Subject login(String configFile,String userName,String password){ // 读取配置文件,初始化SecurityManager工厂 Factory<SecurityManager> factory=new IniSecurityManagerFactory(configFile); // 获取securityManager实例 SecurityManager securityManager=factory.getInstance(); // 把securityManager实例绑定到SecurityUtils SecurityUtils.setSecurityManager(securityManager); // 得到当前执行的用户 Subject currentUser=SecurityUtils.getSubject(); // 创建token令牌,用户名/密码 UsernamePasswordToken token=new UsernamePasswordToken(userName, password); try{ // 身份认证 currentUser.login(token); System.out.println("身份认证成功!"); }catch(AuthenticationException e){ e.printStackTrace(); System.out.println("身份认证失败!"); } return currentUser; } }
1、基于角色的访问控制 Role-Based Authorization
(a)在resource/新建个shiro_role.in
[users] Robin=123456,role1,role2 Tom=123,role1
用名户Robin 密码123456 角色是role1 role2 表示权限
(b)方法
hasRole(String roleName)
判断是否有这个角色,返回值是布尔类型,只判断一个
hasRoles(List<String> roleNames)
可以判断多个角色是否拥有,返回布尔型数组
hasAllRoles(Collection<String> roleNames) 判断角色是否全部拥有,要全都有才返回true
在shiro包下新建个单元测试junittestcase,RoleTest用于测试上述方法
@Test public void testHasRole() { Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "Robin", "123456"); System.out.println(currentUser.hasRole("role1")?"有role1这个角色":"没有role1这个角色"); boolean []results=currentUser.hasRoles(Arrays.asList("role1","role2","role3")); System.out.println(results[0]?"有role1角色":"没有role1角色"); System.out.println(results[1]?"有role2角色":"没有role2角色"); System.out.println(results[2]?"有role3角色":"没有role3角色"); System.out.println(currentUser.hasAllRoles(Arrays.asList("role1","role2"))?"有role1 role2角色":"没有role1 role2角色"); currentUser.logout(); // 退出当前用户 }
除上述三个方法外还有
checkRole(String roleName)
检查是否拥有角色,没有的话抛出异常而不是返回布尔值false
checkRoles(Collection<String> roleNames)
checkRoles(String... roleNames)
2 基于权限的访问控制
(a)再新建个shiro_permission.ini
[users] Robin=123456,role1,role2 Tom=123,role1 [roles] role1=user:select role2=user:add,user:update
因为基于权限所以 添加角色权限,role1有查找权限,role2有添加 修改权限
(b)方法
isPermitted(Permission p)
判断角色是否有权限,返回布尔类型
isPermitted(List<Permission> perms)
isPermittedAll(Collection<Permission> perms)
因为Permission是接口,不能实例化,实例化需实例化它的实现类,太麻烦所以实际项目中不用,直接用下面这种形式,直接传字符串
isPermittedAll(String... perms)
(c)再新建个单元测试PermissionTest
@Test public void testIsPermitted() { Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "Robin", "123456"); // Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "jack", "123"); System.out.println(currentUser.isPermitted("user:select")?"有user:select这个权限":"没有user:select这个权限"); System.out.println(currentUser.isPermitted("user:update")?"有user:update这个权限":"没有user:update这个权限"); boolean results[]=currentUser.isPermitted("user:select","user:update","user:delete"); System.out.println(results[0]?"有user:select这个权限":"没有user:select这个权限"); System.out.println(results[1]?"有user:update这个权限":"没有user:update这个权限"); System.out.println(results[2]?"有user:delete这个权限":"没有user:delete这个权限"); System.out.println(currentUser.isPermittedAll("user:select","user:update")?"有user:select,update这两个权限":"user:select,update这两个权限不全有"); currentUser.logout(); // 退出当前用户 }
除上述三个方法外还有
checkPermission(Permission p)
判断角色是否有权限,没有抛出异常
checkPermissions(Collection<Permission> perms)
checkPermissions(String... perms)
二,注解式授权
@RequiresAuthentication 要求当前 Subject 已经在当前的 session 中被验证通过才能被访问或调用。
@RequiresGuest 要求当前的 Subject 是一个"guest",也就是说,他们必须是在之前的 session 中没有被验证或被记住才
能被访问或调用。
@RequiresPermissions("account:create") 要求当前的 Subject 被允许一个或多个权限,以便执行注解的方法。
@RequiresRoles("administrator") 要求当前的 Subject 拥有所有指定的角色。如果他们没有,则该方法将不会被执行,而
且 AuthorizationException 异常将会被抛出。
@RequiresUser RequiresUser 注解需要当前的 Subject 是一个应用程序用户才能被注解的类/实例/方法访问或调用。一个“应
用程序用户”被定义为一个拥有已知身份,或在当前 session 中由于通过验证被确认,或者在之前 session 中的'RememberMe'
服务被记住
三,Jsp 标签授权
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
Guest 标签:用户没有身份验证时显示相应信息,即游客访问信息;
User 标签:用户已经身份验证/记住我登录后显示相应的信息;
Authenticated 标签:用户已经身份验证通过,即 Subject.login 登录成功,不是记住我登录的。
notAuthenticated 标签:用户没有身份验证通过,即没有调用 Subject.login 进行登录,包括记住我自动登录
的也属于未进行身份验证。
principal 标签 显示用户身份信息,默认调用 Subject.getPrincipal()获取,即 Primary Principal。
hasRole 标签 如果当前 Subject 有角色将显示 body 体内容。
lacksRole 标签 如果当前 Subject 没有角色将显示 body 体内容。
hasAnyRoles 标签 如果当前 Subject 有任意一个角色(或的关系)将显示 body 体内容。
hasPermission 标签 如果当前 Subject 有权限将显示 body 体内容。
lacksPermission 标签 如果当前 Subject 没有权限将显示 body 体内容。
第三讲、Permissions 对权限深入理解
单个权限 query
单个资源多个权限 user:query user:add 多值 user:query,add
单个资源所有权限 user:query,add,update,delete user:*
所有资源某个权限 *:view
实例级别的权限控制
单个实例的单个权限 printer:query:lp7200 printer:print:epsoncolor
所有实例的单个权限 printer:print:*
所有实例的所有权限 printer:*:*
单个实例的所有权限 printer:*:lp7200
单个实例的多个权限 printer:query,print:lp7200
第四讲、授权流程