一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|JavaScript|易語言|

服務器之家 - 編程語言 - JAVA教程 - spring cloud-zuul的Filter使用詳解

spring cloud-zuul的Filter使用詳解

2021-03-24 15:13牛奮lch JAVA教程

這篇文章主要介紹了spring cloud-zuul的Filter使用詳解,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

在前面我們使用zuul搭建了網關http://www.ythuaji.com.cn/article/150025.html

關于網關的作用,這里就不再次贅述了,我們今天的重點是zuul的Filter。通過Filter,我們可以實現安全控制,比如,只有請求參數中有用戶名和密碼的客戶端才能訪問服務端的資源。那么如何來實現Filter了?

要想實現Filter,需要以下幾個步驟:

1、繼承ZuulFilter類,為了驗證Filter的特性,我們這里創建3個Filter

根據用戶名來過濾

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
package com.chhliu.springcloud.zuul; 
import javax.servlet.http.HttpServletRequest; 
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
public class AccessUserNameFilter extends ZuulFilter {
  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
 
    System.out.println(String.format("%s AccessUserNameFilter request to %s", request.getMethod(), request.getRequestURL().toString()));
 
    String username = request.getParameter("username");// 獲取請求的參數
    if(null != username && username.equals("chhliu")) {// 如果請求的參數不為空,且值為chhliu時,則通過
      ctx.setSendZuulResponse(true);// 對該請求進行路由
      ctx.setResponseStatusCode(200);
      ctx.set("isSuccess", true);// 設值,讓下一個Filter看到上一個Filter的狀態
      return null;
    }else{
      ctx.setSendZuulResponse(false);// 過濾該請求,不對其進行路由
      ctx.setResponseStatusCode(401);// 返回錯誤碼
      ctx.setResponseBody("{\"result\":\"username is not correct!\"}");// 返回錯誤內容
      ctx.set("isSuccess", false);
      return null;
    }
  }
 
  @Override
  public boolean shouldFilter() {
    return true;// 是否執行該過濾器,此處為true,說明需要過濾
  }
 
  @Override
  public int filterOrder() {
    return 0;// 優先級為0,數字越大,優先級越低
  }
 
  @Override
  public String filterType() {
    return "pre";// 前置過濾器
  }
}

通過繼承ZuulFilter然后覆寫上面的4個方法,就可以實現一個簡單的過濾器,下面就相關注意點進行說明
filterType:返回一個字符串代表過濾器的類型,在zuul中定義了四種不同生命周期的過濾器類型,具體如下:

  1. pre:可以在請求被路由之前調用
  2. route:在路由請求時候被調用
  3. post:在route和error過濾器之后被調用
  4. error:處理請求時發生錯誤時被調用

Zuul的主要請求生命周期包括“pre”,“route”和“post”等階段。對于每個請求,都會運行具有這些類型的所有過濾器。

filterOrder:通過int值來定義過濾器的執行順序

shouldFilter:返回一個boolean類型來判斷該過濾器是否要執行,所以通過此函數可實現過濾器的開關。在上例中,我們直接返回true,所以該過濾器總是生效

run:過濾器的具體邏輯。需要注意,這里我們通過ctx.setSendZuulResponse(false)令zuul過濾該請求,不對其進行路由,然后通過ctx.setResponseStatusCode(401)設置了其返回的錯誤碼

過濾器間的協調

過濾器沒有直接的方式來訪問對方。 它們可以使用RequestContext共享狀態,這是一個類似Map的結構,具有一些顯式訪問器方法用于被認為是Zuul的原語,內部是使用ThreadLocal實現的,有興趣的同學可以看下源碼。

再建一個過濾器,根據密碼來過濾:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package com.chhliu.springcloud.zuul; 
import javax.servlet.http.HttpServletRequest;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext; 
public class AccessPasswordFilter extends ZuulFilter { 
  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
 
    System.out.println(String.format("%s AccessPasswordFilter request to %s", request.getMethod(), request.getRequestURL().toString()));
 
    String username = request.getParameter("password");
    if(null != username && username.equals("123456")) {
      ctx.setSendZuulResponse(true);
      ctx.setResponseStatusCode(200);
      ctx.set("isSuccess", true);
      return null;
    }else{
      ctx.setSendZuulResponse(false);
      ctx.setResponseStatusCode(401);
      ctx.setResponseBody("{\"result\":\"password is not correct!\"}");
      ctx.set("isSuccess", false);
      return null;
    }
  }
 
  @Override
  public boolean shouldFilter() {
    RequestContext ctx = RequestContext.getCurrentContext();
    return (boolean) ctx.get("isSuccess");// 如果前一個過濾器的結果為true,則說明上一個過濾器成功了,需要進入當前的過濾,如果前一個過濾器的結果為false,則說明上一個過濾器沒有成功,則無需進行下面的過濾動作了,直接跳過后面的所有過濾器并返回結果
  }
 
  @Override
  public int filterOrder() {
    return 1; // 優先級設置為1
  }
 
  @Override
  public String filterType() {
    return "pre";
  }
}

最后建一個post過濾器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.chhliu.springcloud.zuul; 
import javax.servlet.http.HttpServletRequest; 
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext; 
public class AccessTokenFilter extends ZuulFilter {
  @Override
  public Object run() {
    RequestContext ctx = RequestContext.getCurrentContext();
    HttpServletRequest request = ctx.getRequest();
 
    System.out.println(String.format("%s AccessTokenFilter request to %s", request.getMethod(),
        request.getRequestURL().toString()));
     
    ctx.setSendZuulResponse(true);
    ctx.setResponseStatusCode(200);
    ctx.setResponseBody("{\"name\":\"chhliu\"}");// 輸出最終結果
    return null;
  }
 
  @Override
  public boolean shouldFilter() {
    return true;
  }
 
  @Override
  public int filterOrder() {
    return 0;
  }
 
  @Override
  public String filterType() {
    return "post";// 在請求被處理之后,會進入該過濾器
  }
}

2、在主類中,先開啟前面的兩個過濾器

?
1
2
3
4
5
6
7
8
9
@Bean
  public AccessUserNameFilter accessUserNameFilter() {
    return new AccessUserNameFilter();
  }
   
  @Bean
  public AccessPasswordFilter accessPasswordFilter(){
    return new AccessPasswordFilter();
  }

3、輸入請求,驗證

(1)請求為:http://localhost:8768/h2service/user/1?username=chhliu

測試結果為:{"result":"password is not correct!"}

控制臺打印結果

GET AccessUserNameFilter request to http://localhost:8768/h2service/user/1 
GET AccessPasswordFilter request to http://localhost:8768/h2service/user/1 

通過了AccessUserNameFilter過濾器,在驗證AccessPasswordFilter過濾器的時候失敗了

后臺無sql打印,說明請求沒有被路由

(2)請求為:http://localhost:8768/h2service/user/1?password=123456

測試結果為:{"result":"username is not correct!"}

控制臺打印結果:
GET AccessUserNameFilter request to http://localhost:8768/h2service/user/1 

說明到了AccessUserNameFilter過濾器,但是沒有到AccessPasswordFilter過濾器,因為AccessUserNameFilter過濾器的優先級高一些,會先執行,在執行的時候,發現過濾條件不符合,于是跳過了后面所有的過濾器,并返回結果
后臺無sql打印,說明請求沒有被路由

(3)請求為:http://localhost:8768/h2service/user/1?password=123456&username=chhliu

測試結果為:


 
    "id": 1, 
    "username": "user1", 
    "name": "張三", 
    "age": 20, 
    "balance": 100.00 
 

控制臺打印的結果:

GET AccessUserNameFilter request to http://localhost:8768/h2service/user/1 
GET AccessPasswordFilter request to http://localhost:8768/h2service/user/1 

說明是先執行了AccessUserNameFilter然后才執行AccessPasswordFilter這也和我們前面說的order的值越小,優先級越高是吻合的。

同時被請求的服務有sql輸出:

Hibernate: select user0_.id as id1_0_0_, user0_.age as age2_0_0_, user0_.balance as balance3_0_0_, user0_.name as name4_0_0_, user0_.username as username5_0_0_ from user user0_ where user0_.id=? 

說明請求被路由了。

4、開啟post過濾器,再跑一次

測試結果:發現post過濾器是最后執行的,盡管它的優先級為0

關于zuul的Filter的生命周期,見下圖

spring cloud-zuul的Filter使用詳解

注:上圖有個小錯誤,routing應該是route

5、拓展

zuul還提供了一類特殊的過濾器,分別為:StaticResponseFilter和SurgicalDebugFilter

StaticResponseFilter:StaticResponseFilter允許從Zuul本身生成響應,而不是將請求轉發到源。

SurgicalDebugFilter:SurgicalDebugFilter允許將特定請求路由到分隔的調試集群或主機。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:http://blog.csdn.net/liuchuanhong1/article/details/62236793

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 亚洲精品午夜在线观看 | 波多野结衣伦理在线观看 | 91天堂一区二区 | 91在线免费播放 | 国模一区二区三区视频一 | 四虎永久视频 | 亚洲国产区男人本色在线观看欧美 | 男人的天堂视频在线 | 欧美女人p | 成人一级黄色大片 | 国产精品一区二区久久不卡 | 精品国产免费观看一区高清 | 青青草综合网 | 男人操女生 | 欧美日韩精品在线视频 | 亚洲国产精品91 | 日韩欧美成末人一区二区三区 | 探花国产| 亚洲免费视频一区二区三区 | 紧缚束缚调教丨vk | 热门小说同人h改编h | 亚州精品视频 | 国产日韩一区二区三区在线播放 | 亚洲第一福利网 | 逼逼爱 | 日韩视频一区二区三区 | 色5月婷婷| 色五婷婷 | 四虎小视频 | 俄罗斯一级毛片免费播放 | 免费国产好深啊好涨好硬视频 | 国产麻豆网 | 好吊色青青青国产综合在线观看 | 日本久久啪啪婷婷激情五月 | 日本人和黑人一级纶理片 | b片在线观看 | 视频在线观看入口一二三2021 | 五月婷婷丁香在线视频 | 花房乱爱在线观看 | 色综合久久中文字幕网 | 国产欧美日韩专区毛茸茸 |