博客详情

shiro授权过程 (原创)

作者: 朝如青丝暮成雪
发布时间:2019-03-25 09:07:19  文章分类:shiro   阅读(1022)  评论(0)

一、授权的核心概念

授权,也就是权限认证或访问控制,即在应用中控制谁能访问哪些资源
授权中的核心要素:
1 用户,在shiro中代表访问系统的任何客户端,即subject
2 角色,是权限的集合,或字符串值表示的一种能力。
3 权限,即操作资源的权利。比如访问某个页面,以及对某功能模块的添加、修改、删除、查看的权利


(http://shiro.apache.org/authorization.html)

二、授权方式

1、编程式授权  

    基于角色(role)的编程式授权、基于权限(permission)的编程式授权

1.1 基于角色(role)的编程式授权

public class RoleTest {

	@Test
	public void testHasRole() {
		Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "zhangsan", "zs123456");
		
		 
		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();
	}

	@Test
	public void testCheckRole() {
		Subject currentUser=ShiroUtil.login("classpath:shiro_role.ini", "zhangsan","zs123456");
	 
		currentUser.checkRole("role1");
		currentUser.checkRoles(Arrays.asList("role1","role2"));
		currentUser.checkRoles("role1","role2","role3");
		
		currentUser.logout();
	}
}
 

hasRole()和checkRole()的区别在于,前者是有相应角色则返回布尔值,后者是没有角色则会抛出异常。

1.2 基于权限(permission)的编程式授权

public class PermissionTest {

	@Test
	public void testIsPermitted() {
		Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "zhangsan", "zs123456");
		 
		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();
	}

	@Test
	public void testCheckPermitted() {
		Subject currentUser=ShiroUtil.login("classpath:shiro_permission.ini", "zhangsan", "zs123456");
		 
		currentUser.checkPermission("user:select");
		currentUser.checkPermissions("user:select","user:update","user:delete");
		currentUser.logout();
	}
}
isPermmitted()和checkPermitted()的区别在于:前者是若用户没有相应权限则返回布尔值false,而后者则会抛出异常。



2、注解授权

@RequiresAuthentication 要求subjejct已经通过了身份认证
@RequiresGuest   要求当前subject是一个"guest",即subject必须是没有被记住且没有通过身份认证
@RequiresUser    要求当前subject是一个用户,可以是被记住(rememberMe)的,或者是通过了身份认证的
@RequiresRoles   要求当前subject必须拥有相应角色,value可为一个String集合,默认是And关系。可以标记在类和方法上。
@RequiresPermissions 要求当前subject必须拥有相应权限,value可为一个String集合,默认是And关系。可以标记在类和方法上。

@RequiresRoles注解:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresRoles {

    /**
     * A single String role name or multiple comma-delimitted role names required in order for the method
     * invocation to be allowed.
     */
    String[] value();
    
    /**
     * The logical operation for the permission check in case multiple roles are specified. AND is the default
     * @since 1.1.0
     */
    Logical logical() default Logical.AND; 
}
@RequiresPermission注解:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissions {

    /**
     * The permission string which will be passed to {@link org.apache.shiro.subject.Subject#isPermitted(String)}
     * to determine if the user is allowed to invoke the code protected by this annotation.
     */
    String[] value();
    
    /**
     * The logical operation for the permission checks in case multiple roles are specified. AND is the default
     * @since 1.1.0
     */
    Logical logical() default Logical.AND; 

}


3、jsp标签授权

 1 在pom.xml中引入shiro-web-1.3.2.jar
 
2 在jsp页面中引入shiro的自定义标签库  
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>

3 在jsp页面中使用shiro-xx的标签

<shiro:guest>用户没有被RememberMe,也没有通过身份认证时显示  </shiro:guest>

<shiro:user> 用户被RememberMe,或者通过了身份认证时显示</shiro:user>

<shiro:authenticated>用户通过了身份认证时显示 </shiro:authenticated>
<shiro:notAuthenticated>用户没有通过身份认证时显示 </shiro:notAuthenticated>
 

<shiro:hasRole>用户拥有相应角色则显示  </shiro:hasRole>
<shiro:lacksRole> 用户缺少相应角色则显示 </shiro:lacksRole>
<shiro:hasAnyRole>用户拥有其中任意一个角色则显示  </shiro:hasAnyRole>

<shiro:hasPermission> 用户拥有相应权限则显示</shiro:hasPermission>
<shiro:lacksPermission>用户缺少相应权限则显示 </shiro:lacksPermission>





三、授权过程



Step 1: Application or framework code invokes any of the Subject hasRole*checkRole*isPermitted*, or checkPermission* method variants, passing in whatever permission or role representation is required.

Step 2: The Subject instance, typically a DelegatingSubject (or a subclass) delegates to the application’s SecurityManager by calling the securityManager’s nearly identical respective hasRole*checkRole*isPermitted*, or checkPermission* method variants (the securityManager implements the org.apache.shiro.authz.Authorizer interface, which defines all Subject-specific authorization methods).

Step 3: The SecurityManager, being a basic ‘umbrella’ component, relays/delegates to its internal org.apache.shiro.authz.Authorizer instance by calling the authorizer’s respective hasRole*checkRole*isPermitted*, or checkPermission* method. The authorizer instance is by default a ModularRealmAuthorizer instance, which supports coordinating one or more Realm instances during any authorization operation.

Step 4: Each configured Realm is checked to see if it implements the same Authorizer interface. If so, the Realm’s own respective hasRole*checkRole*isPermitted*, or checkPermission* method is called.



四、权限粒度


资源级别
单个权限:query
单个资源多个权限: user:query user:add   多值user:query,add
单个资源所有权限: user:query,user:add,user:update,user:delete  所有user:*
所有资源的某个权限:   *:view

实例级别
单个实例的单个权限 printer:query:lp7200   printer:print:epsoncolor
所有实例的单个权限 printer:print:*
所有实例的所有权限 printer:*:*
单个实例的所有权限 printer:*:lp7200
单个实例的多个权限 printer:query,print:lp7200


printer  等价于 printer:*:*
printer:print 等价与 printer:print:*



关键字:  shiro  授权
评论信息
暂无评论
发表评论

亲,您还没有登陆,暂不能评论哦! 去 登陆 | 注册

博主信息
   
数据加载中,请稍候...
文章分类
   
数据加载中,请稍候...
阅读排行
 
数据加载中,请稍候...
评论排行
 
数据加载中,请稍候...

Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1

鄂公网安备 42011102000739号