shiro开发文档阅读(二)授权

Authorization(授权)

在这里插入图片描述
授权,又称作为访问控制,是对资源的访问管理的过程。换句话说,控制谁有权限在应用程序中做什么。 授权检查的例子是:该用户是否被允许访问这个网页,编辑此数据,查看此按钮,或打印到这台打印机?这些都是 决定哪些是用户能够访问的。

1.shiro实现授权的方式:

1. 编写代码——你可以在你的 Java 代码中用像 if 和 else 块的结构执行授权检查。

1.**基于角色授权

a. 角色检查*
所谓角色检查就是,检查当前subject是否具有该角色,从而决定是否能执行相关操作

    /*****subject提供这些方法供我们检查当前subject所拥有的角色********/ 
    hasRole(String roleName) 返回 true 如果 Subject 被分配了指定的角色,否则返回 falsehasRole(List<String> roleNames) 返回 true 如果 Subject 被分配了所有指定的角色,否则返回 falsehasAllRoles(Collection<String> roleNames) 返回一个与方法参数中目录一致的 hasRole 结果的数组。有性能的提高如果许多角 色需要执行检查(例如,当自定义一个复杂的视图)。 
	
	/**********例如***************/
	Subject currentUser = SecurityUtils.getSubject();   
    if(currentUser.hasRole("administrator")) {
       //show the admin button
    } else {    
       //don't show the button? Grey it out?
    } 

b. 角色断言***
所谓角色断言就是使用布尔值在执行需要权限的行为前来判断 Subject 是否拥有一个角色,如果它们有预期的角色,断言将悄悄 地执行,并且逻辑将如预期般继续,如果 Subject 没有预期的角色,AuthorizationException 将会被抛出

        /*****subject提供这些方法供我们检查当前subject所拥有的角色********/ 
        checkRole(String roleName) 安静地返回,如果 Subject 被分配了指定的角色,不然的话就抛出   AuthorizationException。 
       
        checkRoles(Collection<String> roleNames) 安静地返回,如果 Subject 被分配了所有的指定的角色,不然的话就抛出 AuthorizationException。 
        
        checkRoles(String… roleNames) 与上面的 checkRoles 方法的效果相同,但允许 Java5 的 var-args 类型的参数。
             
        /**********例如***************/
        Subject currentUser = SecurityUtils.getSubject(); 
        //guarantee that the current user is a bank teller and  
        //therefore allowed to open the account: 
        currentUser.checkRole("bankTeller"); 
        openBankAccount();

2 基于权限授权

a. 权限检查*
所谓权限检查就是,看一个 Subject 是否被允许做某事,检查权限主要有 两个方式——基于对象的权限实例或代表权限的字符串.

第一,基于对象的权限检查
执行权限检查的一个可行方法是实例化 org.apache.shiro.authz.Permission 接口的一个 实例,并把它传递给接收权限 实例的*isPermitted 方法。 例如,请考虑以下情况:在办公室有一台打印机,具有唯一标识符 laserjet4400n。我们的软件需要检查当前用户是 否被允许在该打印机上打印文档在我们允许他们按下“打印”按钮之前。上述情况的权限检查可以明确地像这样表达:

    Permission printPermission = new PrinterPermission("laserjet4400n","print");  
    Subject currentUser = SecurityUtils.getSubject();
     If (currentUser.isPermitted(printPermission)) { 
          //show the Print button 
     } else {      
     //don't show the button? Grey it out? 
     } 

优点:
编译时类型安全,保证行为,定制蕴含逻辑等

第二,基于权限字符串的权限检查

基于对象的权限可以是很有用的(编译时类型安全,保证行为,定制蕴含逻辑等),它们有时对应用程序来说会感 到有点“笨手笨脚”的。另一种方法是使用正常的字符串来表示权限实例。
    Subject currentUser = SecurityUtils.getSubject();    
    if(currentUser.isPermitted("printer:print:laserjet4400n")) {        
    	 //show the Print button 
     } else {         
    	 //don't show the button?  Grey it out? 
     } 

这个特别的例子显示了一个特殊冒号分隔的格式,它由 Shiro 默认的 org.apache.shiro.authz.permission.WildcardPermission 实现来定义,其中大多数人会找到适合自己的格式。 也就是说,上面的代码块(大部分)是下面代码的简化


           /*****subject提供这些方法供我们检查当前subject所拥有的权限********/ 
           isPermitted(Permission p) 返回 true 如果该 Subject 被允许执行某动作或访问被权限实例指定的资源集 合,否则返回 falseisPermitted(List<Permission> perms) 返回一个与方法参数中目录一致的 isPermitted 结果的数组。有性能的提高如 果需要执行许多检查(例如,当自定义一个复杂的视图)。 
           
           isPermittedAll(Collection<Permission> perms) 返回 true 如果该 Subject 被允许所有指定的权限,否则返回 false

b. 权限断言*
相同道理

      /*****subject提供这些方法供我们检查当前subject所拥有的权限********/ 
      checkPermission(Permission p) 安静地返回,如果 Subject 被允许执行某 动作或访问被特定的权限实例指定的资 源,不然的话就抛出 AuthorizationException 异常。 
    
      checkPermission(String perm) 安静地返回,如果 Subject 被允许执行某 动作或访问被特定的字符串权限指定的 资源,不然的话就抛出 AuthorizationException 异常。 
    
      checkPermissions(Collection<Permission> perms) 安静地返回,如果 Subject 被允许所有的 权限,不然的话就抛出 AuthorizationException 异常。 
    
      checkPermissions(String… perms) 和上面的 checkPermissions 方法效果相 同,但是使用的是基于字符串的权限

2. JDK 的注解——你可以添加授权注解给你的 Java 方法。
再启动shiro的jdk注解之前,要开启应用程序的aop支持

       /**
         * shiro AOP 支持
         */
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
            AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
            authorizationAttributeSourceAdvisor.setSecurityManager(getSecurityManager(credentialsMatcher()));
            return authorizationAttributeSourceAdvisor;
        }

@RequiresAuthentication

     //RequiresAuthentication 注解要求当前 Subject 已经在当前的 session 中被验证通过才能被注解的类/实例/方法访问或 调用。
     @RequiresAuthentication  
     public void updateAccount(Account userAccount) {
             //this method will only be invoked by a 
             //Subject that is guaranteed authenticated      } 
     
    //这通常等同于接下来的基于 Subject 的逻辑: 
    public void updateAccount(Account userAccount) {  
    if (!SecurityUtils.getSubject().isAuthenticated()) {  
   		 throw new AuthorizationException(...); 
    }   
    //Subject is guaranteed authenticated here } 

@RequiresGuest

    //RequiresGuest 注解要求当前的 Subject 是一个"guest",也就是说,他们必须是在之前的 session 中没有被验证或记住 才能被注解的类/实例/方法访问或调用。
    @RequiresGuest 
    public void signUp(User newUser) {
      //this method will only be invoked by a   
      //Subject that is unknown/anonymous } 
      
    //这通常等同于接下来的基于 Subject 的逻辑: 
    public void signUp(User newUser) {  
    	Subject currentUser = SecurityUtils.getSubject(); 
    	PrincipalCollection principals = currentUser.getPrincipals(); 
    	if (principals != null && !principals.isEmpty()) { 
    		//known identity - not a guest: throw new AuthorizationException(...);
   	    } 
    	//Subject is guaranteed to be a 'guest' here … } 

@RequiresPermissions

    //RequiresPermissions 注解要求当前的 Subject 被允许一个或多个权限,以便执行注解的方法。 
    @RequiresPermissions("account:create")  
    public void createAccount(Account account) {  
    	//this method will only be invoked by a Subject 
    	//that is permitted to create an account } 
    	
    //这通常等同于接下来的基于 Subject 的逻辑: 
    public void createAccount(Account account) {  
    	Subject currentUser = SecurityUtils.getSubject();  
    	if (!subject.isPermitted("account:create")) {
    	 	 throw new AuthorizationException(...);
    	 	  }   
    	 	  //Subject is guaranteed to be permitted here}

@RequiresRoles


       //RequiresRoles 注解要求当前的 Subject 拥有所有指定的角色。如果他们没有,则该方法将不会被执行,而且 AuthorizationException 异常将会被抛出。
       @RequiresRoles("administrator") 
       public void deleteUser(User user) {  
       	//this method will only be invoked by an administrator } 
      
      //这通常等同于接下来的基于 Subject 的逻辑: 
      public void deleteUser(User user) {  
       	Subject currentUser = SecurityUtils.getSubject();  
       	if (!subject.hasRole("administrator")) { 
       		throw new AuthorizationException(...); 
       		}   
       		//Subject is guaranteed to be an 'administrator' here} 

@RequiresUser


  //RequiresUser 注解需要当前的 Subject 是一个应用程序用户才能被注解的类/实例/方法访问或调用。一个“应用程序 用户”被定义为一个拥有已知身份,或在当前 session 中由于通过验证被确认,或者在之前 session 中的'RememberMe' 服务被记住。 
    @RequiresUser  
      public void updateAccount(Account account) {  
      		//this method will only be invoked by a 'user'  
      		//i.e. a Subject with a known identity} 
     
     //这通常等同于接下来的基于 Subject 的逻辑:  
      public void updateAccount(Account account) {  
      	Subject currentUser = SecurityUtils.getSubject();  
     	 	PrincipalCollection principals = currentUser.getPrincipals(); 
      	if (principals == null || principals.isEmpty()) { 
      		//no identity - they're anonymous, not allowed: throw new AuthorizationException(...); }   //Subject is guaranteed to have a known identity here … }

3. JSP/GSP 标签库——你可以控制基于角色和权限的 JSP 或者 GSP 页面输出。
Shiro 提供了一个用于控制 JSP/GSP 页面输出的基于 Subject 状态的标签库。这些包含在 Web 章节的 JSP/GSP 标签库 部分。

    <!--首先一定要引入标签-->
    <!--jsp-->
    <%@ taglib prefix=”shiro” uri=”http://shiro.apache.org/tags” %>
    <!--html-->
    <html lang="en"  xmlns:shiro="http://www.w3.org/1999/xhtml">

    <!-- authenticated 用户已经经过身份验证,但不是记住我登录的 -->
    <shiro:authenticated>
        <shiro:principal />已经经过身份验证<br><br>
    </shiro:authenticated>
    
    <!-- 用户没有进行身份验证,记住我自动登录的属于没有进行身份验证 -->
    <shiro:notAuthenticated>
        用户没有进行身份验证,记住我自动登录的属于没有进行身份验证<br><br>
    </shiro:notAuthenticated>
    
    <!-- guest  :用户没有验证时显示相应信息 ,如登录等相关信息-->
    <shiro:guest>
        <a href="login.jsp">登录</a><br><br>
    </shiro:guest>
    
    <!-- 当前用户有任意一个角色将会显示body体中的内容 -->
    <shiro:hasAnyRoles name="admin,user,manager">
        <shiro:principal></shiro:principal>拥有admin/user/manager中的角色<br><br>
    </shiro:hasAnyRoles>
    
    <!-- 当前用户有相应的权限,将显示body体中的信息 -->
    <shiro:hasPermission name="customer:delete">
        <shiro:principal />拥有customer:delete权限<br><br>
    </shiro:hasPermission>
    
    <!-- 当前用户没有相应的权限,将显示body体中的信息 -->
    <shiro:lacksPermission name="customer:delete">
        没有权限customer:delete<br><br>
    </shiro:lacksPermission>
    
    <!-- 当前用户没有相应的角色,将显示body中的信息 -->
    <shiro:lacksRole name="manager">
        <shiro:principal></shiro:principal>没有manager角色<br><br>
    </shiro:lacksRole>
    
    <!-- user: 用户已经经过认证/记住我登录后 显示相应的信息 -->
    <shiro:user>
        <a href="logout">登出</a><br><br>
    </shiro:user>
    
    <!-- 当前用户是否拥有该角色,有就显示相关信息 -->
    <shiro:hasRole name="admin">
        <a href="admin.jsp">Admin Page</a><br><br>
    </shiro:hasRole>
    --------------------- 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值