服務網關Zuul 學習筆記

服務網關Zuul 學習筆記(2019.11.29完善)

使用服務網關做統一入口和統一認證,他可以和Eureka,Ribbon,Hystrix等組件配合使用。Zuul組件的核心是一系列的過濾器!

配置統一入口

1. 創建模塊SpringBoot_Zuul並引入依賴:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
        </dependency>
    </dependencies>

2. 創建包與啓動類: 並加上@EnableZuulProxy註解啓用網關

@SpringBootApplication
@EnableZuulProxy
public class ApplicationZuul {
    public static void main(String[] args) {
        SpringApplication.run(ApplicationZuul.class, args);
    }
}

3.創建application.yml配置文件,並將zuul模塊註冊上去註冊中心並配置網關相關轉發配置

server:
  port: 8080 #指定端口

spring:
  application:
    name: eureka-zuul #指定服務名
eureka:
  client:
    serviceUrl: #註冊到註冊中心
      defaultZone: http://127.0.0.1:8761/eureka/
  instance:
    prefer-ip-address: true
zuul:
  routes: #轉發配置
    springBoot-client: #  名稱可以隨便寫 但最好見名思意
      path: /client/** #配置請求URL的請求規則   請求只要是這個地址開頭就去eureka-client模塊找
      serviceId: eureka-client #指定Eureka註冊中心中的服務id
    tensquare-test: #test模塊
      path: /test/** #配置請求URL的請求規則    請求只要是這個地址開頭就去eureka-test模塊找
      serviceId: eureka-test #指定Eureka註冊中心中的服務id
 ..........................

4.啓動測試是否配置好了統一入口,訪問http://localhost:8080/client/getss?id=888888888 看看是否是去eureka-client模塊調用服務

Zuul過濾器 配置統一過濾:

1. 在SpringBoot_Zuul模塊上創建一個簡單的zuul過濾器

@Component
public class WebFilter extends ZuulFilter {

    @Override
    public String filterType() { //過濾器類型
         return "pre";// 前置過濾器
    }

    @Override
    public int filterOrder() {
        return 0;// 優先級爲0,數字越大,優先級越低
    }

    @Override
    public boolean shouldFilter() {
        return true;// 是否執行該過濾器,此處爲true,說明需要過濾
    }

    @Override
    public Object run() throws ZuulException {
        System.out.println("zuul過濾器...");
        return null;
    }
}
  • filterType:過濾器的類型,它決定過濾器在請求的哪個生命週期中執行。這裏定義爲pre,代表會在請求被路由之前執行。參數解釋:  pre: 可以在請求被路由之前調用,  route:在路由請求時候被調用,  post:在route和error過濾器之後被調用, error:處理請求時發生錯誤時被調用
  • filterOrder:過濾器的執行順序。當請求在一個階段中存在多個過濾器時,需要根據該方法返回的值來依次執行。
  • shouldFilter:判斷該過濾器是否需要被執行。這裏我們直接返回了true,因此該過濾器對所有請求都會生效。實際運用中我們可以利用該函數來指定過濾器的有效範圍。
  • run:過濾器的具體邏輯。這裏我們通過ctx.setSendZuulResponse(false)令zuul過濾該請求,不對其進行路由,然後通過ctx.setResponseStatusCode(401)設置了其返回的錯誤碼,當然我們也可以進一步優化我們的返回,比如,通過ctx.setResponseBody(body)對返回body內容進行編輯等。

2. 啓動模塊後請求,測試是否經過了過濾器

一般使用於token的校驗: (過濾器實現token校驗)

@Component
public class ManagerFilter extends ZuulFilter {

    @Autowired
    private JwtUtil jwtUtil;

    @Override
    public String filterType() {//過濾器類型
        return "pre";//前置過濾器
    }

    @Override
    public int filterOrder() {
        return 0;//優先級,數字越大,優先級越低
    }

    @Override
    public boolean shouldFilter() {
        return true;//過濾器開關,true表示開啓
    }

    @Override
    public Object run() throws ZuulException {
        System.out.println("Zuul過濾器");
        RequestContext requestContext=RequestContext.getCurrentContext();
        HttpServletRequest request = requestContext.getRequest();
        
        if(request.getMethod().equals("OPTIONS")){
            return null;
        }
        //登錄頁面不攔截
        String url=request.getRequestURL().toString();
        if(url.indexOf("/admin/login")>0){
            System.out.println("登陸頁面"+url);
            return null;
        }

        String authHeader =(String)request.getHeader("Authorization");//獲取頭信息
        if(authHeader!=null && authHeader.startsWith("Bearer ") ){
            String token = authHeader.substring(7);
            //使用工具類校驗token是否正確
            Claims claims = jwtUtil.parseJWT(token);
            if(claims!=null){
                if("admin".equals(claims.get("roles"))){
                    requestContext.addZuulRequestHeader("Authorization",authHeader);
                    System.out.println("token 驗證通過,添加了頭信息"+authHeader);
                    return null;
                }
            }
        }
        //否則攔截不給經過網關
        requestContext.setSendZuulResponse(false);//終止運行
        requestContext.setResponseStatusCode(401);//http狀態碼
        requestContext.setResponseBody("無權訪問");
        requestContext.getResponse().setContentType("text/html;charset=UTF-8");
        return null;
    }
}

需要注意,這裏我們通過requestContext.setSendZuulResponse(false)令zuul過濾該請求,不對其進行路由,然後通過requestContext.setResponseStatusCode(401)設置了其返回的錯誤碼

如果配置了網站前臺的網關就要進行token轉發

我們現在在過濾器中接收header,轉發給微服務

修改過濾器。如果有token,直接轉發。

    @Override
    public Object run() throws ZuulException {
        System.out.println("zuul過濾器...");
        //向header中添加鑑權令牌 RequestContexts是zuul包下的類		
        RequestContext requestContext = RequestContext.getCurrentContext();
        //獲取header
        HttpServletRequest request = requestContext.getRequest();
        String authorization = request.getHeader("Authorization");
        if(authorization!=null){
            requestContext.addZuulRequestHeader("Authorization",authorization);
        }
        return null;
    }
發佈了29 篇原創文章 · 獲贊 3 · 訪問量 1612
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章