目的or背景
shiro有个注解是@RequiresPermissions,接口方法加上这个表示需要有指定权限才能访问,不然提示无权限访问等类似信息,这个吧,有点意思,没玩过,所以就来简单模仿下,自己自定义一个注解,具备指定权限才可调通。
码代码的工具人—is me
接下来就是demo实现
1. 自定义一个校验权限的注解
package com.example.demo.anno;
import java.lang.annotation.*;
/**
*
* @author apollo
* @description
* @date 2021/11/27 10:01
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface VerifyPermissions {
/**
* 权限标识
*/
String[] value();
}
2. 码好咱们的切面
在这里面我先写死用户有【book_read】的权限,你们可根据自己的业务查数据库or缓存,自由发挥,只是个demo,别太较真
package com.example.demo.aspect;
import com.example.demo.anno.VerifyPermissions;
import com.example.demo.exception.BaseException;
import com.example.demo.exception.Code;
import com.example.demo.exception.Message;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;
/**
* @author apollo
* @description
* @date 2021/11/27 10:11
*/
@Aspect
@Component
@Slf4j
public class AuthAspect {
@Before("execution(public * com.example.demo.controller..*.*(..))")
public void apiDoBefore(JoinPoint point) {
verifyProceed(point);
}
private void verifyProceed(JoinPoint point) {
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
int modifiers = method.getModifiers();
if (!Modifier.isPublic(modifiers)) {
return;
}
//初始化用户有的权限值(为了演示方便,这个地方一般不是写死的权限,根据自己业务来灵活加载)
final List<String> userBindingPermissions = Arrays.asList("book_read");
//校验api的权限值
VerifyPermissions verifyPermissions = method.getAnnotation(VerifyPermissions.class);
if (verifyPermissions != null) {
//拿到添加注解的api所需要的权限
String[] verifyPermissionsStrs = verifyPermissions.value();
List<String> needPermisions = Arrays.asList(verifyPermissionsStrs);
//1.判断用户有权限
if (CollectionUtils.isEmpty(userBindingPermissions)) {
log.info("用户无权限,不可操作!", needPermisions);
throw new BaseException(Code.UNAUTHORIZED, Message.AUTH_FAILED);
}
//2.判断用户有的权限是否匹配注解api中的权限
if (!userBindingPermissions.containsAll(needPermisions)) {
log.info("用户缺少:{}权限!", needPermisions);
throw new BaseException(Code.UNAUTHORIZED, Message.AUTH_FAILED);
}
}
}
}
3. 搞个api
我先初始化几个书名,然后来两个api,加上访问接口需要校验的权限【book_read】、【book_add】
package com.example.demo.controller;
import com.example.demo.anno.VerifyPermissions;
import org.springframework.web.bind.annotation.*;
import java.util.LinkedList;
import java.util.List;
/**
* @author apollo
* @description
* @date 2021年11月27日 10:27
*/
@RestController
@RequestMapping("/book")
public class BookApi {
private static final List<String> bookNames = new LinkedList<>();
static {
bookNames.add("霸道总裁爱上我");
bookNames.add("霸道总裁的小娇妻");
}
@GetMapping("/all")
@VerifyPermissions({
"book_read"
})
public List<String> books(){
return bookNames;
}
@PostMapping("/add")
@VerifyPermissions({
"book_add"
})
public Boolean books(
@RequestParam("name")String name
){
bookNames.add(name);
return true;
}
}
4. postman测试
4.1 看书api
因为我在切面那边给用户初始化了一个可以看书的权限【book_read】,所以是可以调通
4.2 添加书api
没有给用户绑定【book_add】的权限,所以用户在使用这个api的时候,提示无权限
如果在切面那里给他加上【book_add】权限,就可以了
这只是模仿shiro api鉴权的一个小demo,shiro里面@RequiresPermissions注解中还有Logical属性【AND,OR】,来校验权限之间的逻辑关系,有兴趣的话可以看下shiro下PermissionAnnotationHandler的源码,自己去自定义个鉴权注解~
就先说到这
\color{#008B8B}{ 就先说到这}
就先说到这
在下
A
p
o
l
l
o
\color{#008B8B}{在下Apollo}
在下Apollo
一个爱分享
J
a
v
a
、生活的小人物,
\color{#008B8B}{一个爱分享Java、生活的小人物,}
一个爱分享Java、生活的小人物,
咱们来日方长,有缘江湖再见,告辞!
\color{#008B8B}{咱们来日方长,有缘江湖再见,告辞!}
咱们来日方长,有缘江湖再见,告辞!