1. 程式人生 > >SpringCloud工作筆記038---spring cloud-簡單閘道器許可權控制_直接在zuul裡面做

SpringCloud工作筆記038---spring cloud-簡單閘道器許可權控制_直接在zuul裡面做

這樣也是一種方式吧,比較Low的一種吧,應該是,

在閘道器裡,判斷,是否有token,當然不能攔截登入啊,登入的時候本來就沒有token,

登入以後,判斷如果有token,就轉發,轉發以後就到了,對應的微服務中的controller中了,這樣

在controller,做具體的許可權控制,一般都是對url做的許可權吧,不過我們這個太噁心嘛?

你們都沒有這種需求嗎,就是不同的角色,訪問同一個url,會返回不同的資料,還是說,

這是兩種設計思想,就是,對於不同的角色,就應該對應不同的url,通過不同的url來返回不同的資料

------------------------------------------------------------------------------------------------------------

看下面的做法吧:

閘道器api Gateway的重要性不言而喻,閘道器負責統一接收所有請求,然後根據不同的規則進行轉發到不同的服務。使用閘道器能夠統一的管理請求日誌、進行許可權控制、過濾等,這樣就能避免在每個單體應用中做重複的工作。

這一篇主要是講zuul的獨立使用,就是隻作為一個獨立的專案進行請求轉發,而不關聯SpringCloud的那一堆Eureka、Ribbon等,因為很多時候我們的專案並不都是基於springcloud的微服務,或者不想搞那麼麻煩用註冊中心什麼的,就只想做個簡單的請求轉發代理和許可權控制。

zuul是可以進行開發的,裡面可以自定義一些自己的規則,譬如涉及查表之類的,能夠完成顆粒很細的需求。

這裡我們打算完成如下的功能,當訪問ip/user時就進入到User的獨立專案中,訪問ip/club時就進入到club的獨立專案中。入口是zuul,在zuul裡做許可權控制,譬如查表過濾黑名單、限制同一個userId單位時間內的訪問次數等。

請求轉發

使用zuul很簡單,新建一個Springboot專案,建立時勾選zuul即可。pom.xml如下

  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

  4. <modelVersion>4.0.0</modelVersion>

  5. <groupId>com.tianyalei</groupId>

  6. <artifactId>testzuul</artifactId>

  7. <version>0.0.1-SNAPSHOT</version>

  8. <packaging>jar</packaging>

  9. <name>testzuul</name>

  10. <description>Demo project for Spring Boot</description>

  11. <parent>

  12. <groupId>org.springframework.boot</groupId>

  13. <artifactId>spring-boot-starter-parent</artifactId>

  14. <version>1.5.6.RELEASE</version>

  15. <relativePath/> <!-- lookup parent from repository -->

  16. </parent>

  17. <properties>

  18. <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

  19. <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

  20. <java.version>1.8</java.version>

  21. <spring-cloud.version>Dalston.SR3</spring-cloud.version>

  22. </properties>

  23. <dependencies>

  24. <dependency>

  25. <groupId>org.springframework.cloud</groupId>

  26. <artifactId>spring-cloud-starter-zuul</artifactId>

  27. </dependency>

  28. <dependency>

  29. <groupId>org.springframework.boot</groupId>

  30. <artifactId>spring-boot-starter-test</artifactId>

  31. <scope>test</scope>

  32. </dependency>

  33. </dependencies>

  34. <dependencyManagement>

  35. <dependencies>

  36. <dependency>

  37. <groupId>org.springframework.cloud</groupId>

  38. <artifactId>spring-cloud-dependencies</artifactId>

  39. <version>${spring-cloud.version}</version>

  40. <type>pom</type>

  41. <scope>import</scope>

  42. </dependency>

  43. </dependencies>

  44. </dependencyManagement>

  45. <build>

  46. <plugins>

  47. <plugin>

  48. <groupId>org.springframework.boot</groupId>

  49. <artifactId>spring-boot-maven-plugin</artifactId>

  50. </plugin>

  51. </plugins>

  52. </build>

  53. </project>

然後在Application類加上@EnableZuulProxy註解即可,該專案就具備了zuul的功能了

  1. @EnableZuulProxy

  2. @SpringBootApplication

  3. public class TestzuulApplication {

  4. public static void main(String[] args) {

  5. SpringApplication.run(TestzuulApplication.class, args);

  6. }

  7. }

然後關鍵的地方在application.yml配置裡,規則在這裡配置

  1. server:

  2. port: 9000

  3. zuul:

  4. routes:

  5. api-1:

  6. path: /user/**

  7. url: http://localhost:8081/

  8. api-2:

  9. path: /club/**

  10. url: http://localhost:8082/

主要就是配置zuul.routes相關,api-1名字隨便起,主要是配置裡面的path和url這個是固定的

通過原始碼可以看到支援serviceId,url兩種,path是固定的,代表訪問zuul時的路徑,url代表訪問該路徑時會被轉發到哪個url上,serviceId是給springcloud用的,代表在Eureka上註冊的服務id,也是確定是轉發到哪一個服務的。

這裡我們配置的是url,當訪問localhost:9000/user/abc時,就相當於訪問localhost:8081/abc.

到這裡就已經完成了請求轉發了,如果你本地跑了兩個專案,埠分別是8081,8082,就已經可以通過請求zuul配置的url規則訪問到了。

  1. @RequestMapping("club")

  2. public String index() {

  3. return "hello,我來自Club客戶端";

  4. }

許可權控制

在zuul裡新建一個AccessFilter類,如下的寫法。

  1. package com.tianyalei.testzuul;

  2. import com.netflix.zuul.ZuulFilter;

  3. import com.netflix.zuul.context.RequestContext;

  4. import org.slf4j.Logger;

  5. import org.slf4j.LoggerFactory;

  6. import org.springframework.stereotype.Component;

  7. import javax.servlet.http.HttpServletRequest;

  8. @Component

  9. public class AccessFilter extends ZuulFilter {

  10. private static Logger log = LoggerFactory.getLogger(AccessFilter.class);

  11. @Override

  12. public String filterType() {

  13. //前置過濾器

  14. return "pre";

  15. }

  16. @Override

  17. public int filterOrder() {

  18. //優先順序,數字越大,優先順序越低

  19. return 0;

  20. }

  21. @Override

  22. public boolean shouldFilter() {

  23. //是否執行該過濾器,true代表需要過濾

  24. return true;

  25. }

  26. @Override

  27. public Object run() {

  28. RequestContext ctx = RequestContext.getCurrentContext();

  29. HttpServletRequest request = ctx.getRequest();

  30. log.info("send {} request to {}", request.getMethod(), request.getRequestURL().toString());

  31. //獲取傳來的引數accessToken

  32. Object accessToken = request.getParameter("accessToken");

  33. if(accessToken == null) {

  34. log.warn("access token is empty");

  35. //過濾該請求,不往下級服務去轉發請求,到此結束

  36. ctx.setSendZuulResponse(false);

  37. ctx.setResponseStatusCode(401);

  38. ctx.setResponseBody("{\"result\":\"accessToken is empty!\"}");

  39. return null;

  40. }

  41. //如果有token,則進行路由轉發

  42. log.info("access token ok");

  43. //這裡return的值沒有意義,zuul框架沒有使用該返回值

  44. return null;

  45. }

  46. }

別的先不管,看看run方法,在這裡可以獲取到使用者傳來的所有引數,然後可以配置自己的規則來決定是否往最終的服務轉發請求,false為不給最終的服務傳送這次請求,預設為true。在這裡,我們設定如果accessToken為空,就停止轉發,直接給客戶端返回結果。需要注意一點,Filter是可以配置多個的,按照order從小到大依次執行,即使設定了setSendZuulResponse(false),也是會繼續執行下一個Filter的。

注意,路由轉發的停止和繼續是由ctx.setSendZuulResponse來控制的,與下面的return null無關,這個方法的return值沒有意義,並沒有使用。

效果如圖

下一篇來詳細看看Filter的配置。