ZuulFilter過濾器


Zuul作爲網關的其中一個重要功能,就是實現請求的鑑權。而這個動作我們往往是通過Zuul提供的過濾器來實現的。

1、過濾器

1.1 ZuulFilter

ZuulFilter是過濾器的頂級父類。在這裏我們看一下其中定義的4個最重要的方法:

public abstract ZuulFilter implements IZuulFilter{

    abstract public String filterType();

    abstract public int filterOrder();
    
    boolean shouldFilter();// 來自IZuulFilter

    Object run() throws ZuulException;// IZuulFilter
}

說明:

  • shouldFilter:返回一個Boolean值,判斷該過濾器是否需要執行。返回true執行,返回false不執行。
  • run:過濾器的具體業務邏輯。
  • filterType:返回字符串,代表過濾器的類型。包含以下4種:
    • pre:請求在被路由之前執行
    • route:在路由請求時調用
    • post:在route和errror過濾器之後調用
    • error:處理請求時發生錯誤調用
  • filterOrder:通過返回的int值來定義過濾器的執行順序,數字越小優先級越高。

1.2 過濾器執行生命週期

這張是Zuul官網提供的請求生命週期圖,清晰的表現了一個請求在各個過濾器的執行順序。

在這裏插入圖片描述

正常流程:

  • 請求到達首先會經過pre類型過濾器,而後到達route類型,進行路由,請求就到達真正的服務提供者,執行請求,返回結果後,會到達post過濾器。而後返回響應。

異常流程:

  • 整個過程中,pre或者route過濾器出現異常,都會直接進入error過濾器,在error處理完畢後,會將請求交給POST過濾器,最後返回給用戶。
  • 如果是error過濾器自己出現異常,最終也會進入POST過濾器,將最終結果返回給請求客戶端。
  • 如果是POST過濾器出現異常,會跳轉到error過濾器,但是與pre和route不同的是,請求不會再到達POST過濾器了。

所有內置過濾器列表:

在這裏插入圖片描述

1.3 使用場景

場景非常多:

  • 請求鑑權:一般放在pre類型,如果發現沒有訪問權限,直接就攔截了
  • 異常處理:一般會在error類型和post類型過濾器中結合來處理。
  • 服務調用時長統計:pre和post結合使用。

2、自定義過濾器

接下來我們來自定義一個過濾器,模擬一個登錄的校驗。基本邏輯:如果請求中有access-token參數,則認爲請求有效,放行。

2.1 定義過濾器類

在這裏插入圖片描述
內容:

@Component
public class LoginFilter extends ZuulFilter {
    /**
     * 過濾器類型,前置過濾器
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * 過濾器的執行順序
     * @return
     */
    @Override
    public int filterOrder() {
        return 1;
    }

    /**
     * 該過濾器是否生效
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * 登陸校驗邏輯
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        // 獲取zuul提供的上下文對象
        RequestContext context = RequestContext.getCurrentContext();
        // 從上下文對象中獲取請求對象
        HttpServletRequest request = context.getRequest();
        // 獲取token信息
        String token = request.getParameter("access-token");
        // 判斷
        if (StringUtils.isBlank(token)) {
            // 過濾該請求,不對其進行路由
            context.setSendZuulResponse(false);
            // 設置響應狀態碼,401
            context.setResponseStatusCode(HttpStatus.SC_UNAUTHORIZED);
            // 設置響應信息
            context.setResponseBody("{\"status\":\"401\", \"text\":\"request error!\"}");
        }
        // 校驗通過,把登陸信息放入上下文信息,繼續向後執行
        context.set("token", token);
        return null;
    }
}

2.2 測試

沒有token參數時,訪問失敗:

在這裏插入圖片描述

添加token參數後:
在這裏插入圖片描述

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