【Shiro】权限控制注解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Mr_EvanChen/article/details/80696134

Shiro共有5个注解:

  • RequiresAuthentication:

    使用该注解标注的类,实例,方法在访问或调用时,当前Subject必须在当前session中已经过认证。

  • RequiresGuest:

    使用该注解标注的类,实例,方法在访问或调用时,当前Subject可以是“gust”身份,不需要经过认证或者在原先的session中存在记录。

  • RequiresPermissions:

    当前Subject需要拥有某些特定的权限时,才能执行被该注解标注的方法。如果当前Subject不具有这样的权限,则方法不会被执行。

  • RequiresRoles:

    当前Subject必须拥有所有指定的角色时,才能访问被该注解标注的方法。如果当天Subject不同时拥有所有指定角色,则方法不会执行还会抛出AuthorizationException异常。

  • RequiresUser

    当前Subject必须是应用的用户,才能访问或调用被该注解标注的类,实例,方法。


使用方法:

Shiro的认证注解处理是有内定的处理顺序的,如果有个多个注解的话,前面的通过了会继续检查后面的,若不通过则直接返回,处理顺序依次为(与实际声明顺序无关):

RequiresRoles 
RequiresPermissions 
RequiresAuthentication 
RequiresUser 
RequiresGuest

例如:你同时声明了RequiresRoles和RequiresPermissions,那就要求拥有此角色的同时还得拥有相应的权限。

需要注意的是,shiro注解可以放到Controller层方法上,也可以放到Service层方法上。但在日常开发中,往往会在Service层添加“@Transactional”注解,为的是当Service发送数据库异常时,所有数据库操作可以回滚。当在Service层添加“@Transactional”注解后,执行Service方法前,会开启事务。此时的Service已经是一个代理对象了,此时如果我们将Shiro的权限注解加载Service层是不合适的,此时需要加到Controller层。这是因为不能让Service是“代理的代理”,如果强行注入,会发生类型转换异常。因此尽量加在Controller层比较好。

下面用@RequiresPermissions为例,将注解加在controller层,看在项目中是怎么用的,其他四种都是类似的。

当方法前可能需要多个权限时,可以自定义注解。如下,就表示RequiresPermissions可以有多个权限标识,默认的逻辑关系为与,即需要同时满足多个权限标识才能执行相关方法,逻辑关系也可修改为或。

package com.yealink.version.shiro;

import org.apache.shiro.authz.annotation.Logical;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by yl1794 on 2018/6/13.
 */
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RequiresPermissions {
    String[] value();
    Logical logical() default Logical.AND;
}

在controller的方法前加上注解,逻辑关系为或

    @RequiresPermissions(value={"version:delete","version:delete2"},logical = Logical.OR)
    @GetMapping("/delete/{id}")
    @ResponseBody
    public Result delete(@PathVariable String id){
        versionService.deleteVersion(id);
        return success();
    }

此时当用户同时具有version:delete,version:delete2权限标识时,才可执行delete方法,否则会提示如下报错。从打印的信息可以看出,当前用户aaa,具有的权限标识中并没有version:delete,因此会报错AuthorizationException。

用户: aaa 具有的角色: [admin]
用户: aaa 具有的权限: [add, query, version:list, version:release, update, delete, version:edit]
2018-06-14T18:31:23.180+0800 WEBERROR 8852 --- [nio-8890-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.apache.shiro.authz.UnauthorizedException: Subject does not have permission [version:delete]] with root cause

org.apache.shiro.authz.AuthorizationException: Not authorized to invoke method: public com.yealink.microservice.core.result.Result com.yealink.version.controller.VersionController.delete(java.lang.String)
	at org.apache.shiro.authz.aop.AuthorizingAnnotationMethodInterceptor.assertAuthorized(AuthorizingAnnotationMethodInterceptor.java:90)
	at org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor.assertAuthorized(AnnotationsAuthorizingMethodInterceptor.java:100)

在这里我们可以看到没有权限时会抛出异常,项目中可能会有很多的方法都会加上权限注解,那么我们应该怎么样对异常进行捕获,并且最好能够对这个异常进行统一的处理。这部分内容请参看:https://blog.csdn.net/Mr_EvanChen/article/details/80696872

猜你喜欢

转载自blog.csdn.net/Mr_EvanChen/article/details/80696134