4)SpringBoot-自定义注解控制权限
引入springboot-aop依赖
<!-- Spring Boot Starter AOP -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
定义权限注解
@Target({ElementType.TYPE, ElementType.METHOD}) 表示允许在类和方法上使用该注解
package com.permission_demo.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Permission {
/**
* 权限点
*/
String code() default "";
/**
* 权限点描述
*/
String desc() default "";
}
定义aop切面
关于aop可从这篇文章了解 https://blog.youkuaiyun.com/sql2008help/article/details/116424839
package com.permission_demo.aop;
import com.permission_demo.annotation.Permission;
import com.permission_demo.exception.PermissionDeniedException;
import com.permission_demo.service.PermissionService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.Objects;
@Aspect
@Component
public class PermissionAspect {
@Autowired
private PermissionService permissionService;
// 定义切点,匹配所有带有@Permission注解的类和方法
@Pointcut(value = "@within(com.permission_demo.annotation.Permission) || @annotation(com.permission_demo.annotation.Permission)")
public void pointCut() {
}
//环绕通知
@Around("pointCut()")
public Object aroundPermission(ProceedingJoinPoint joinPoint) throws Throwable {
// 1. 获取类上的权限注解
Class<?> targetClass = joinPoint.getTarget().getClass();
Permission classPermission = targetClass.getAnnotation(Permission.class);
// 如果类上没有定义权限直接放行
if (Objects.isNull(classPermission)) {
return joinPoint.proceed();
}
// 2. 获取方法上的权限注解
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
Permission methodPermission = method.getAnnotation(Permission.class);
if (Objects.isNull(methodPermission)) {
return joinPoint.proceed();
}
if (!permissionService.hasPermission(classPermission.code() + "$" + methodPermission.code())) {
throw new PermissionDeniedException("没有权限访问!");
}
return joinPoint.proceed();
}
}
权限校验类:
package com.permission_demo.service;
import org.springframework.stereotype.Component;
import java.util.HashSet;
import java.util.Set;
@Component
public class PermissionService {
// 实际从登录成功的用户数据中获取该用户所有角色的权限并集
private static Set<String> CURRENT_USER_PERMISSION = new HashSet<>();
static {
CURRENT_USER_PERMISSION.add("user_manage$view");
}
public boolean hasPermission(String permission) {
return CURRENT_USER_PERMISSION.contains(permission);
}
}
使用自定义注解
如下:
package com.permission_demo.controller;
import com.permission_demo.annotation.Permission;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(value = "/user")
@Permission(code = "user_manage",desc = "用户管理")
public class UserController {
@Permission(code = "add",desc = "新增")
@GetMapping(value = "/add")
public String add(){
return "新增用户";
}
@Permission(code = "view",desc = "查看")
@GetMapping(value = "/view")
public String view(){
return "查看用户";
}
}
全局异常处理
package com.permission_demo.handler;
import com.permission_demo.exception.PermissionDeniedException;
import lombok.Getter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(PermissionDeniedException.class)
@ResponseStatus(HttpStatus.FORBIDDEN)
public ErrorResponse handlePermissionDenied(PermissionDeniedException e) {
return new ErrorResponse(403, "FORBIDDEN", e.getMessage());
}
@Getter
static class ErrorResponse {
// Getters
private int status;
private String error;
private String message;
public ErrorResponse(int status, String error, String message) {
this.status = status;
this.error = error;
this.message = message;
}
}
}
测试
http://127.0.0.1:8093/user/view 可正常访问

http://127.0.0.1:8093/user/add 被拦截

上述代码路径:https://gitee.com/husong_zone/permission_demo
3300

被折叠的 条评论
为什么被折叠?



