Zuul:Pre和Post过滤器(下)
生活随笔
收集整理的這篇文章主要介紹了
Zuul:Pre和Post过滤器(下)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
可以看到所有的請求都會經過他,那么我們現在要對這個請求做一個權限的校驗,加入沒有Zuul這個服務,那你Server A/B/C,都要校驗一次,這個每個服務都要做一次,所以權限校驗我們可以放到Zuul統一的實現掉,接下來我們演示如何對請求進行統一的校驗,我們現在來做這么一件事,希望所有經過Zuul的請求,都要有一個參數叫做Token,并且內容不能為空,如果你不帶這個參數的話,如果不帶這個參數的話,那么就權限校驗不通過,我們新建一個包叫filter,下面新建一個TokenFilterimport static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;import javax.servlet.http.HttpServletRequest;import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;@Component
public class TokenFilter extends ZuulFilter {@Overridepublic String filterType() {return PRE_TYPE;}@Overridepublic int filterOrder() {return PRE_DECORATION_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//這里從url參數里獲取, 也可以從cookie, header里獲取String token = request.getParameter("token");if (StringUtils.isEmpty(token)) {requestContext.setSendZuulResponse(false);requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());}return null;}
}/*** {@code 401 Unauthorized}.* @see <a href="http://tools.ietf.org/html/rfc7235#section-3.1">HTTP/1.1: Authentication, section 3.1</a>*/
UNAUTHORIZED(401, "Unauthorized"),繼承ZuulFiltercom.netflix.zuul.ZuulFilter這里要實現幾個方法,實現這四個方法,這里有一個常量類FilterConstants,這里我們要做的是參數校驗,用這個PRE_TYPE@Override
public String filterType() {return PRE_TYPE;
}/*** {@link ZuulFilter#filterType()} pre type.*/
String PRE_TYPE = "pre";這個filterOrder這是順序,這個順序用什么順序呢,正如我們之前所說,一種過濾器一個類型下面,有很多個過濾器,這些都是pre的,這個ORDER我們填什么呢,我們把順序放到這個過濾器之前,這些順序越小的越靠前,越小的優先級越高,放到他前面我們減1就好了@Override
public int filterOrder() {return PRE_DECORATION_FILTER_ORDER - 1;
}/*** Filter Order for {@link org.springframework.cloud.netflix.zuul.filters.pre.PreDecorationFilter}*/
int PRE_DECORATION_FILTER_ORDER = 5;這也是官方推薦的一個寫法,@Override
public boolean shouldFilter() {return true;
}這里就是我們的邏輯@Override
public Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//這里從url參數里獲取, 也可以從cookie, header里獲取String token = request.getParameter("token");if (StringUtils.isEmpty(token)) {requestContext.setSendZuulResponse(false);requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());}return null;
}我們從一個對象里面拿到一個請求的內容,叫做RequestContext,這也是Zuul他自己封裝的,獲取當前的一個上下文,RequestContext requestContext = RequestContext.getCurrentContext();在從這里面拿到Request,拿到Request之后大家就熟了,從這我們就可以拿到Token了,這里寫點注釋,這里我們是從參數里面去拿,你也可以從Cookie或者header里面獲取,基本上也就放到這里面了,獲取到了之后判斷一下,如果他是空的話呢,這個時候返回沒有權限,往requestContext這里面設置一些值就好了,首先設置sendZuulResponse為false,false是不通過,再設置一個HTTP的狀態碼,狀態碼權限不足我們一般是用401,我們也可以直接寫枚舉HttpStatus.UNAUTHORIZED.value()BAD_REQUEST(400, "Bad Request"),
/*** {@code 401 Unauthorized}.* @see <a href="http://tools.ietf.org/html/rfc7235#section-3.1">HTTP/1.1: Authentication, section 3.1</a>*/
UNAUTHORIZED(401, "Unauthorized"),org.springframework.http.HttpStatus.UNAUTHORIZEDhttp://localhost:8040/myProduct/product/list?token=1234現在地址帶了token,沒問題和之前一樣http://localhost:8040/myProduct/product/list如果不帶TOKEN就401,返回的是401,權限沒有通過,會走這個校驗的邏輯,你的業務類型可能也不只是判斷是否為空,你拿到這個值之后也可以從數據庫里面去讀,從Redis里面去比較,都是可以的,我們也可以自定義一個POST Filter,就是請求到了目標服務,返回了結果之后,對結果進行加工,我們從返回的頭里面寫一些東西吧@Component
public class AddResponseHeaderFilter extends ZuulFilter{@Overridepublic String filterType() {return POST_TYPE;}@Overridepublic int filterOrder() {return SEND_RESPONSE_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletResponse response = requestContext.getResponse();response.setHeader("X-Foo", UUID.randomUUID().toString());return null;}
}同樣的繼承ZuulFilter,type是POST_TYPE/*** {@link ZuulFilter#filterType()} post type.*/
String POST_TYPE = "post";org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPEfilterOrder這個也是比較有講究的,我們再去看一下order,如果我們自定義POST order的話,我們會把它放到這個之前,也就是放到這個fiter之前,所以我們選中這個再減1@Override
public int filterOrder() {return SEND_RESPONSE_FILTER_ORDER - 1;
}/*** Filter Order for {@link org.springframework.cloud.netflix.zuul.filters.post.SendResponseFilter#filterOrder()}*/
int SEND_RESPONSE_FILTER_ORDER = 1000;org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER優先級在他之前了,也是獲取requestContext@Override
public Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletResponse response = requestContext.getResponse();response.setHeader("X-Foo", UUID.randomUUID().toString());return null;
}不是request,而是要拿到結果了,我們從返回的結果里面寫東西了,設置一個header,header名隨便設置一個,生成一下隨機數,這就寫完了http://localhost:8040/myProduct/product/list?token=1234結果是返回了,返回頭里面有沒有我們添加進去的信息呢,Response Header有吧以上就是自定義POST Filter的內容
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.learn.cloud</groupId><artifactId>api-gateway</artifactId><version>0.0.1-SNAPSHOT</version><packaging>jar</packaging><parent><groupId>cn.learn</groupId><artifactId>microcloud02</artifactId><version>0.0.1</version></parent><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><java.version>1.8</java.version></properties> <dependencies><!-- <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-config</artifactId></dependency> --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka</artifactId></dependency><!-- <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-eureka-server</artifactId></dependency> --><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zuul</artifactId></dependency></dependencies><!-- 這個插件,可以將應用打包成一個可執行的jar包 --><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
package com.learn.cloud;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.zuul.EnableZuulProxy;@EnableZuulProxy
@SpringBootApplication
public class APIGatewayApplication {public static void main(String[] args) {SpringApplication.run(APIGatewayApplication.class, args);}}
package com.learn.cloud.filter;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_DECORATION_FILTER_ORDER;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.PRE_TYPE;import javax.servlet.http.HttpServletRequest;import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;@Component
public class TokenFilter extends ZuulFilter {@Overridepublic String filterType() {return PRE_TYPE;}@Overridepublic int filterOrder() {return PRE_DECORATION_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletRequest request = requestContext.getRequest();//這里從url參數里獲取, 也可以從cookie, header里獲取String token = request.getParameter("token");if (StringUtils.isEmpty(token)) {requestContext.setSendZuulResponse(false);requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value());}return null;}
}
package com.learn.cloud.filter;import java.util.UUID;import javax.servlet.http.HttpServletResponse;import org.springframework.stereotype.Component;import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.POST_TYPE;
import static org.springframework.cloud.netflix.zuul.filters.support.FilterConstants.SEND_RESPONSE_FILTER_ORDER;@Component
public class AddResponseHeaderFilter extends ZuulFilter{@Overridepublic String filterType() {return POST_TYPE;}@Overridepublic int filterOrder() {return SEND_RESPONSE_FILTER_ORDER - 1;}@Overridepublic boolean shouldFilter() {return true;}@Overridepublic Object run() {RequestContext requestContext = RequestContext.getCurrentContext();HttpServletResponse response = requestContext.getResponse();response.setHeader("X-Foo", UUID.randomUUID().toString());return null;}
}
server.port=8040
spring.application.name=api-gateway
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=${spring.application.name}:${spring.cloud.client.ipAddress}:${spring.application.instance_id:${server.port}}
eureka.client.serviceUrl.defaultZone=http://admin:1234@10.40.8.152:8761/eureka
#eureka.instance.appname=api-gateway
#zuul.routes.user-route.service-id=product
#zuul.ignoredServices=microservice-consumer-movie-ribbon-hystrix
#zuul.routes.user-route.path=/user/**
#zuul.routes.user-route.url=http://localhost:7900/
#ribbon.eureka.enabled=false
#microservice-simple-provider-user.ribbon.listOfServers=http://localhost:7900/,http://localhost:7901/zuul.routes.myProduct.path=/myProduct/**
zuul.routes.myProduct.service-id=product
zuul.routes.myProduct.sensitiveHeaders=
#zuul.routes.product=/myProduct/**
management.security.enabled=false
?
總結
以上是生活随笔為你收集整理的Zuul:Pre和Post过滤器(下)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Zuul:Pre和Post过滤器(上)
- 下一篇: Zuul:限流