使用zuul實現驗證自定義請求頭中的token


路由:她會把外部所有對請求轉發到具體的微服務實例上,是實現外部訪問同一接口的基礎

過濾: 就是權限的檢查, 判斷當前的請求是否有權限區訪問那些服務集群

搭建后台網關:

  1. 導入eureka - client, 它本身也是一個客戶端,需要注冊進eureka

    1. 導入網關的包
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

過濾器, 重寫下面的ZuulFilter可以實現自定義的過濾規則, 每個方法的含義都通過注釋的方式寫在了方法頭

網關的過濾器

@Component
public class WebManagerFilter extends ZuulFilter {

    /**
     * 指定過濾器的類型
pre :可以在請求被路由之前調用
route :在路由請求時候被調用
post :在route和error過濾器之后被調用
error :處理請求時發生錯誤時被調用
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     *  指定過濾器的優先級, 0表示優先執行, 因為我們可以寫很多個過濾器
     * @return
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     *  當前過濾器是否開啟, true表示開啟
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     *  過濾器執行邏輯, 返回任意Object類型的值,都表示放行,包括null
     *  如果不想往后繼續執行了,就使用 setSendZullResponse(false)
     * @return
     * @throws ZuulException
     */
    @Override
    public Object run() throws ZuulException {
        System.out.println("經過了后台的過濾器");
        return null;
    }
}

我們可以通過RequestContext的實例對象,獲取出請求頭,請求parms,請求ip等信息, 針對不同的信息可以做出不同的處理

黑白名單

比如我們可以在網關中禁用掉惡意訪問的ip地址

驗證權限

如果項目是前后端分離使用jwt等工具生成token放在請求頭中做安全驗證,我們也能在網關中對請求頭做出初步解析處理

防止抓包

還能根據用戶請求中發送過來的請求參數做驗證簽名處理, 防止數據在傳輸過程中被惡意篡改


此外,網關會過濾掉一些請求的請求頭,如果請求頭是我們自己定義的,就比如下面的Authrization, 經過網關后的請求的頭信息會丟失,進而導致下面的這段代碼失效, 獲取不出頭信息,就沒辦法驗證token的合法性

解決辦法: 選着添加添加一條配置信息 sensitive-headers: 將這個配置置空,意為清空網關要過濾的請求頭

  
   RequestContext currentContext = RequestContext.getCurrentContext();
        String header =   currentContext .getRequest().getHeader("Authorization");
        System.err.println("zull header "+header);
        // 判斷是否存在header
        if (!"".equals(header)&&header!=null){
            System.err.println("轉發header");
            currentContext.addZuulRequestHeader("Authorization",header);
        }

使用過濾器做驗證的邏輯如下,驗證攜帶在請求頭中的token信息如下:

這個方法的特點就是, 只要他能在遇到 return null 就表示成功完成了驗證的邏輯

1. 導入 common,我們要使用它的jwtUtil
@Override
public Object run() throws ZuulException {
    System.err.println("經過了后台的過濾器");

    RequestContext currentContext = RequestContext.getCurrentContext();
    HttpServletRequest request = currentContext.getRequest();
    // 獲取出請求頭
    String header = request.getHeader("Authorization");

    // 放行zuul的第一次請求 todo 我並沒有觸發這個方法的執行
    if (request.getMethod().equals("OPTIONS")){
        System.err.println("OPTIONS");
        return null;
    }

    // 放行登錄請求
    if (request.getRequestURL().indexOf("login")>0){
        return null;
    }

    if (StringUtils.isNotBlank(header)){
        if (header.startsWith("Bearer ")){
            String token = header.substring(7);
            if (StringUtils.isNotBlank(token)){
                System.out.println("token=="+token);
                try{
                    Claims claims = jwtUtil.parseJWT(token);
                    String roles =(String) claims.get("roles");
                    System.out.println("roles=="+roles);
                    // 對admin放行,
                    if (roles.equals("admin")){
                        return null;
                    }
                    // todo 轉發頭信息,我改了配置文件, 讓zuul不過濾任何頭信息
                    // 其他情況, 終止訪問
                    currentContext.setSendZuulResponse(false);

                }catch (Exception e){
                    // 解析token出現的異常,說明token有問題, 終止本次請求
                    System.out.println("token出錯了,終止本次訪問: "+e);
                    currentContext.setSendZuulResponse(false);
                }
            }
        }
    }

    currentContext.setSendZuulResponse(false);
    currentContext.getResponse().setContentType("text/html;chatset=utf-8");
    try {
        currentContext.getResponse().getWriter().write("權限不足");
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM