<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                [TOC] 上一篇文章中,講了Zuul 轉發,動態路由,負載均衡,等等一些Zuul 的特性,這個一篇文章,講Zuul Filter 使用,關于網關的作用,這里就不再次贅述了,重點是zuul的Filter ,我們可以實現安全控制,比如,只有請求參數中有token和密碼的客戶端才能訪問服務端的資源。那么如何來實現Filter了? # Spring Cloud Zuul ## zuul 執行流程 ![執行流程圖][11] **Zuul**:大部分功能都是通過過濾器來實現的。Zuul中定義了四種標準過濾器類型,這些過濾器類型對應于請求的典型生命周期。 **PRE**:這種過濾器在請求被路由之前調用。我們可利用這種過濾器實現身份驗證、在集群中選擇請求的微服務、記錄調試信息等。 **ROUTING**:這種過濾器將請求路由到微服務。這種過濾器用于構建發送給微服務的請求,并使用Apache HttpClient或Netfilx Ribbon請求微服務。 **OST**:這種過濾器在路由到微服務以后執行。這種過濾器可用來為響應添加標準的HTTP Header、收集統計信息和指標、將響應從微服務發送給客戶端等。 **ERROR**:在其他階段發生錯誤時執行該過濾器。 除了默認的過濾器類型,Zuul還允許我們創建自定義的過濾器類型。例如,我們可以定制一種STATIC類型的過濾器,直接在Zuul中生成響應,而不將請求轉發到后端的微服務。 ## 準備工作 我們先拿之前兩篇文章,構建的兩個微服務代碼為基礎,進行下面的操作 **建議先閱讀以下兩篇文章** [Spring Cloud(四) 服務提供者 Eureka + 服務消費者 Feign ](http://www.ymq.io/2017/12/06/spring-cloud-feign/) [Spring Cloud(三) 服務提供者 Eureka + 服務消費者(rest + Ribbon)](http://www.ymq.io/2017/12/05/spring-cloud-ribbon-rest/) [http://www.ymq.io/2017/12/06/spring-cloud-feign/](http://www.ymq.io/2017/12/06/spring-cloud-feign/) [http://www.ymq.io/2017/12/05/spring-cloud-ribbon-rest/](http://www.ymq.io/2017/12/05/spring-cloud-ribbon-rest/) ## Eureka Service **導入第三篇文章中的項目:作為服務注冊中心** `spring-cloud-eureka-service` ## Eureka Provider **導入第三篇文章中的項目:作為服務的提供者** `spring-cloud-eureka-provider-1` `spring-cloud-eureka-provider-2` `spring-cloud-eureka-provider-3` ## 簡單使用 **新建項目** `spring-cloud-zuul-filter` ### 添加依賴 ```xml <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-zuul</artifactId> </dependency> ``` ### 開啟服務注冊 在程序的啟動類 `ZuulFilterApplication` 通過 `@EnableZuulProxy` 開啟 Zuul 服務網關 ```java package io.ymq.example.zuul.filter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; @EnableZuulProxy @SpringBootApplication public class ZuulFilterApplication { public static void main(String[] args) { SpringApplication.run(ZuulFilterApplication.class, args); } } ``` ### 添加配置 配置文件 `application.yml` ```sh spring: application: name: zuul-service-filter server: port: 9000 zuul: routes: api: path: /** serviceId: eureka-provider eureka: client: serviceUrl: defaultZone: http://localhost:8761/eureka/ ``` ### TokenFilter `ZuulFilter` 是Zuul中核心組件,通過繼承該抽象類,覆寫幾個關鍵方法達到自定義調度請求的作用 **TokenFilter 過濾器** ```java package io.ymq.example.zuul.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; /** * 描述: 過濾器 token * * @author yanpenglei * @create 2017-12-11 14:38 **/ public class TokenFilter extends ZuulFilter { private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class); @Override public String filterType() { return "pre"; // 可以在請求被路由之前調用 } @Override public int filterOrder() { return 0; // filter執行順序,通過數字指定 ,優先級為0,數字越大,優先級越低 } @Override public boolean shouldFilter() { return true;// 是否執行該過濾器,此處為true,說明需要過濾 } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); LOGGER.info("--->>> TokenFilter {},{}", request.getMethod(), request.getRequestURL().toString()); String token = request.getParameter("token");// 獲取請求的參數 if (StringUtils.isNotBlank(token)) { ctx.setSendZuulResponse(true); //對請求進行路由 ctx.setResponseStatusCode(200); ctx.set("isSuccess", true); return null; } else { ctx.setSendZuulResponse(false); //不對其進行路由 ctx.setResponseStatusCode(400); ctx.setResponseBody("token is empty"); ctx.set("isSuccess", false); return null; } } } ``` ### PasswordFilter `ZuulFilter` 是Zuul中核心組件,通過繼承該抽象類,覆寫幾個關鍵方法達到自定義調度請求的作用 **PasswordFilter 過濾器** ```java package io.ymq.example.zuul.filter; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.http.HttpServletRequest; /** * 描述: 過濾器 Password * * @author yanpenglei * @create 2017-12-11 15:40 **/ public class PasswordFilter extends ZuulFilter { private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class); @Override public String filterType() { return "post"; // 請求處理完成后執行的filter } @Override public int filterOrder() { return 1; // 優先級為0,數字越大,優先級越低 } @Override public boolean shouldFilter() { RequestContext ctx = RequestContext.getCurrentContext(); return (boolean) ctx.get("isSuccess"); // 判斷上一個過濾器結果為true,否則就不走下面過濾器,直接跳過后面的所有過濾器并返回 上一個過濾器不通過的結果。 } @Override public Object run() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); LOGGER.info("--->>> PasswordFilter {},{}", 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(400); ctx.setResponseBody("The password cannot be empty"); ctx.set("isSuccess", false); return null; } } } ``` ### 開啟過濾器 在程序的啟動類 `ZuulFilterApplication` 添加 Bean ```java @Bean public TokenFilter tokenFilter() { return new TokenFilter(); } @Bean public PasswordFilter PasswordFilter() { return new PasswordFilter(); } ``` ### filterType **filterType:返回一個字符串代表過濾器的類型,在zuul中定義了四種不同生命周期的過濾器類型,具體如下:** - pre:路由之前 - routing:路由之時 - post: 路由之后 - error:發送錯誤調用 - filterOrder:過濾的順序 - shouldFilter:這里可以寫邏輯判斷,是否要過濾,本文true,永遠過濾。 - run:過濾器的具體邏輯。可用很復雜,包括查sql,nosql去判斷該請求到底有沒有權限訪問。 ## 測試服務 依次啟動項目: `spring-cloud-eureka-service` `spring-cloud-eureka-provider-1` `spring-cloud-eureka-provider-2` `spring-cloud-eureka-provider-3` `spring-cloud-zuul-filter` 啟動該工程后,訪問服務注冊中心,查看服務是否都已注冊成功:[http://localhost:8761/](http://localhost:8761/) ![查看各個服務注冊狀態][22] **查看 eureka 監控,看服務是否都注冊成功** ### token 測試 訪問:[http://127.0.0.1:8761/](http://127.0.0.1:8761/) **步驟一** 提示 `token is empty` 訪問:[http://127.0.0.1:9000/](http://127.0.0.1:9000/) ![瀏覽器訪問][33] **步驟二** 加上token `?token=token-uuid` ,已經驗證通過了,提示 `The password cannot be empty` 訪問:[http://127.0.0.1:9000/?token=token-uuid](http://127.0.0.1:9000/?token=token-uuid) ![token is empty][44] ### password 測試 加上`token` 和 `password` `&password=123456` ,已經驗證通過 訪問:[http://127.0.0.1:9000/?token=token-uuid&password=123456](http://127.0.0.1:9000/?token=token-uuid&password=123456) F5 刷新,每次都驗證通過,并且負載均衡 ![The password cannot be empty][55] [11]: https://www.souyunku.com/images/2017/SpringCloud/zuulFilter/11.png [22]: https://www.souyunku.com/images/2017/SpringCloud/zuulFilter/22.png [33]: https://www.souyunku.com/images/2017/SpringCloud/zuulFilter/33.png [44]: https://www.souyunku.com/images/2017/SpringCloud/zuulFilter/44.png [55]: https://www.souyunku.com/images/2017/SpringCloud/zuulFilter/55.png ## 源碼下載 **GitHub:**[https://github.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-zuul-filter](https://github.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-zuul-filter) **碼云:**[https://gitee.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-zuul-filter](https://gitee.com/souyunku/spring-cloud-examples/tree/master/spring-cloud-zuul-filter)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看