我們用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
qiushi是管理員,所以用戶邱石可以訪問到數據。
3,http://localhost:8080/user2?name=qiushi
由於接口/user2沒有添加 @Permission註解,所以不用做安全校驗,直接返回數據。