SpringBoot利用注解方式接口權(quán)限過(guò)濾

本文主要介紹利用注解方式實(shí)現(xiàn)權(quán)限過(guò)濾,基于Spring Boot項(xiàng)目,這里權(quán)限是指不同平臺(tái)的賬號(hào)訪問(wèn)同一項(xiàng)目,從而帶來(lái)的問(wèn)題,而非業(yè)務(wù)權(quán)限。例如:在一個(gè)項(xiàng)目中,有C端用戶和M端管理用戶,接口有些通用,有些不通用,如果不加以控制則會(huì)出現(xiàn)接口垮平臺(tái)調(diào)用,C端可以調(diào)用M端接口這種不可控情況,廢話少說(shuō)直接進(jìn)入主題。

自定義注解

import java.lang.annotation.*;

@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Authority {

    Platform[] value();                   // 那些平臺(tái)能夠訪問(wèn)

}
  • 首先自定義個(gè)注解,名字可以隨便起,本文注解名稱 @Authority 意思為權(quán)限控制,該注解主要打在Controller 中對(duì)外暴露的方法中。

@RestController
@RequestMapping("/client_b_user")
public class ClientBUserController {

    @Authority(value={Platform.B})
    @GetMapping("/getUserInfo")
    public UserInfo getUserInfo(){
        ......
    }
}
  • Value[] 為一個(gè)枚舉類,主要是定義本項(xiàng)目中又那些用戶群體,例如 Platform.B 與 Platform.C 代表B端用戶與C端用戶。

  • 在編碼的過(guò)程中就定義好Controller中方法可以由那些平臺(tái)或者用戶群體訪問(wèn)。

監(jiān)聽(tīng)Spring Bean的創(chuàng)建

  • 通過(guò)實(shí)現(xiàn)BeanPostProcessor可以達(dá)到監(jiān)聽(tīng)SpringBean創(chuàng)建

  • 這里我們可以通過(guò)判斷創(chuàng)建的Bean是否為 @Controller 或者 @RestController

  • 如果 Bean 對(duì)象問(wèn) @Controller 或者 @RestController 那么則監(jiān)聽(tīng)掃描其方法是否有 @Authority 注解

@Component
public class AuthorityControllerBeanProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Class clazz = bean.getClass();
        Boolean isControllerAnnotationInClass = clazz.isAnnotationPresent(Controller.class) || clazz.isAnnotationPresent(RestController.class);

        if (isControllerAnnotationInClass) {
            // 如果這是一個(gè) Controller Bean 的話
            // 那么就讀取所有方法的權(quán)限配置
            Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());

            for (Method method : methods) {

                Boolean isAuthorityAnnotationInMethod = method.isAnnotationPresent(Authority.class);
                String target= bean.getClass().getName() + "." + method.getName();

                if (isAuthorityAnnotationInMethod) {
                    // 如果有 @Authority 注解的話
                    // 則記錄該注解中的內(nèi)容
                    Authority authority = method.getAnnotation(Authority.class);
                    AuthorityAnnotationContainer.addPlatformConfiguration(target,authority);

                }
            }

            return bean;
        } else {
            // 否則的話直接返回Bean
            return bean;
        }
    }
  • AuthorityAnnotationContainer 實(shí)質(zhì)為一個(gè)Map 記錄著那些方法是打上了 @Authority 注解的,Key 為方法名,Value為注解的內(nèi)容,本文不再提供代碼。

實(shí)現(xiàn)攔截

  • 注解打完之后,最終還是需要攔截器進(jìn)行攔截。

  • 定義攔截器

@Component
public class AuthorityInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        // 將handler強(qiáng)轉(zhuǎn)為HandlerMethod, 前面已經(jīng)證實(shí)這個(gè)handler就是HandlerMethod
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        // 從方法處理器中獲取出要調(diào)用的方法
        Method method = handlerMethod.getMethod();

        String target = handlerMethod.getBean().getClass().getName() + "." + method.getName();

        Authority authority = AuthorityAnnotationContainer .getAuthority(target);
        
        Boolean isSuccess = false;    // 是否能夠訪問(wèn)
        if(authority != null){
              // 這里進(jìn)行條件判斷,
              // 本項(xiàng)目中的做法是,取得用戶信息,然后判斷用戶是哪個(gè)平臺(tái)的,在決定是否能夠訪問(wèn)。
              // 如果能夠訪問(wèn) isSuccess = true;
        }
        return isAuthority;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}

總結(jié)

本文的重點(diǎn)是對(duì)于 BeanPostProcessor 的使用,實(shí)現(xiàn) BeanPostProcessor 即可在創(chuàng)建Bean的時(shí)候增加一個(gè)監(jiān)聽(tīng)器,做一些對(duì)應(yīng)的操作。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.1 spring IoC容器和beans的簡(jiǎn)介 Spring 框架的最核心基礎(chǔ)的功能是IoC(控制反轉(zhuǎn))容器,...
    simoscode閱讀 6,863評(píng)論 2 22
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,697評(píng)論 19 139
  • Spring Web MVC Spring Web MVC 是包含在 Spring 框架中的 Web 框架,建立于...
    Hsinwong閱讀 22,970評(píng)論 1 92
  • 本來(lái)是準(zhǔn)備看一看Spring源碼的。然后在知乎上看到來(lái)一個(gè)帖子,說(shuō)有一群**自己連Spring官方文檔都沒(méi)有完全讀...
    此魚不得水閱讀 7,050評(píng)論 4 21
  • 1、行動(dòng)力。平時(shí)的自己,總是感覺(jué)特別的拖拉,磨磨蹭蹭的,總是要感覺(jué)一切都準(zhǔn)備妥當(dāng)了才可以開(kāi)始,要不然總是覺(jué)得不完美...
    Vivi_huang閱讀 164評(píng)論 0 1

友情鏈接更多精彩內(nèi)容