我们用springboot做后台开发,难免会用到权限校验,比如查看当前用户是否合法,是否是管理员。而spring的面向切面的特效可以帮助我们很好的实现动态的权限校验。这里我们就用到的spring的aop。接下来就带领大家用aop和注解来快速的实现权限校验
一,在pom.xml里引入aop的类库。
<!--aop切面的使用-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二,自定义注解
package com.demo.permission;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by qcl on 2019/2/18
* 微信:2501902696
* desc:自定义权限管理注解
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Permission {
String authorities() default "我是默认值";
}
三,借助@Aspect实现切面
package com.demo.permission;
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.util.StringUtils;
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;
/**
* 定义切点
*/
@Pointcut("execution(public * com.demo.permission.controller.*.*(..))")
public void privilege() {
}
/**
* 权限环绕通知
*
* @param joinPoint
* @throws Throwable
*/
@ResponseBody
@Around("privilege()")
public Object isAccessMethod(ProceedingJoinPoint joinPoint) throws Throwable {
//获取访问目标方法
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method targetMethod = methodSignature.getMethod();
//得到方法的访问权限
final String methodAccess = AnnotationParse.privilegeParse(targetMethod);
//如果该方法上没有权限注解,直接调用目标方法
if (StringUtils.isEmpty(methodAccess)) {
return joinPoint.proceed();
} else {
//获取当前用户
Object[] args = joinPoint.getArgs();
if (args == null) {
throw new LoginException("参数错误");
}
String currentUser = args[0].toString();
logger.info("访问用户,{}", currentUser);
if (!userService.isAdmin(currentUser)) {
throw new LoginException("您不是管理员");
} else {
logger.info("您是管理员");
//是管理员时,才返回所需要的信息
return joinPoint.proceed();
}
}
}
}
四,定义一个简单的管理员名单
package com.demo.permission;
import org.springframework.stereotype.Service;
import java.util.Arrays;
/**
* Created by qcl on 2019/2/18
* 微信:2501902696
* desc:
*/
@Service
public class UserService {
private String[] admins = {"qiushi", "weixin", "xiaoshitou"};
//是否是管理员
boolean isAdmin(String name) {
return Arrays.asList(admins).contains(name);
}
}
这里简单起见,就用一个本地的数组来维护管理员,正常应该是把管理员相关信息存到数据库里。
五,获取用户名,@Permission注解进行权限校验
package com.demo.permission.controller;
import com.demo.permission.Permission;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import lombok.extern.slf4j.Slf4j;
/**
* Created by qcl on 2019/2/18
* 微信:2501902696
* desc:
*/
@RestController
@Slf4j
public class UserController {
//带注解,需要校验权限
@GetMapping(value = "/user")
@Permission
public String user(@RequestParam String name) {
return "你好:"+name+",您有管理权限";
}
//不带注解,不需要安全校验
@GetMapping(value = "/user2")
public String user2(@RequestParam String name) {
return "不用检查权限,直接返回的数据";
}
}
然后通过url请求来验证结果
1,http://localhost:8080/user?name=qcl2
由于qcl2不在管理员数组里面,所以抛出异常
2,http://localhost:8080/user?name=qiushi
image.png
qiushi是管理员,所以用户邱石可以访问到数据。
3,http://localhost:8080/user2?name=qiushi
image.png
由于接口/user2没有添加 @Permission注解,所以不用做安全校验,直接返回数据。
image.png
网友评论