springboot藉助aop和註解實現權限校驗

我們用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註解,所以不用做安全校驗,直接返回數據。

到這裏我們就輕鬆實現通過 @Permission一個註解,就可以實現數據的安全校驗。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章