用springboot做后台开发,难免会用到权限校验,比如查看当前用户是否合法,是否是管理员.而spring的面向切面的特性可以帮助我们很好的实现动态的权限校验.下面我们就用spring的aop和注解来快速的实现权限校验.
1.项目结构搭建
2.相关依赖
<!--aop支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--切面注解支持-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!--lombok支持@Slf4j-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.12</version>
</dependency>
3.代码实现
UserService
package com.example.demo.service;
import org.springframework.stereotype.Service;
import java.util.Arrays;
@Service
public class UserService {
private String[] admins = {"sj1", "sj2", "sj3"};
//是否为管理员
public boolean isAdmin(String name) {
return Arrays.asList(admins).contains(name);
}
}
Permission
package com.example.demo.permission;
import java.lang.annotation.*;
/**
* 自定义权限注解
*/
@Target(ElementType.METHOD) //规定自定义注解可以使用的位置
@Retention(RetentionPolicy.RUNTIME) //规定注解的生命周期(运行时可以通过反射获得)
@Documented //该注解是否可以生成到API文档中
public @interface Permission {
String authorities() default "我是默认值";
}
ControllerAspect
package com.example.demo.permission;
import com.example.demo.service.UserService;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import java.lang.reflect.Method;
import javax.security.auth.login.LoginException;
/**
* 切面类
*/
@Aspect
@Component
public class ControllerAspect {
private final static Logger logger = LoggerFactory.getLogger(ControllerAspect.class);
@Autowired
private UserService userService;
/**
* 定义切点(切入位置)
* execution(修饰符表达式? 返回值表达式 类路径表达式?方法名表达式(参数表达式)异常表达式?)
* 说明:包名部分的..表示当前包及其所有子包.后面带有?的表示为可选项.参数部分的..表示零个或多个任意参数
*/
@Pointcut("execution(public * com.example.demo.controller.*.*(..))")
public void privilege() {
System.out.println("==>切入");//不执行
}
/**
* 权限环绕通知
*/
@ResponseBody
@Around("privilege()") //value&#