SpringCloud(8)---zuul權限校驗、接口限流
zuul權限校驗、接口限流
一、權限校驗搭建
正常項目開發時,權限校驗可以考慮JWT和springSecurity結合進行權限校驗,這個後期會總結,這裏做個基於ZuulFilter過濾器進行一個簡單的權限校驗過濾。
對於組件zuul中,其實帶有權限認證的功能,那就是ZuulFilter過濾器。ZuulFilter是Zuul中核心組件,通過繼承該抽象類,覆寫幾個關鍵方法達到自定義調度請求的作用
使用到的組件包括:Eureka、Feign、Zuul,包括以下四個項目:
(1)Eureka-server: 7001 註冊中心
(2)product-server : 8001 商品微服務
(3)order-server : 9001 訂單微服務
(4)zuul-gateway : 6001 Zuul網關
有關四個服務的基本配置我這裏就不寫了,具體可以看之前幾篇博客,這裏只寫LoginFilter權限校驗類
1、LoginFilter類
/** * 登錄過濾器
*記得類上加Component註解 */ @Component public class LoginFilter extends ZuulFilter { /** * 過濾器類型,前置過濾器 */ @Override public String filterType(){ return PRE_TYPE; } /** * 過濾器順序,越小越先執行 */ @Override public int filterOrder() { return 4; } /** * 過濾器是否生效 * 返回true代表需要權限校驗,false代表不需要用戶校驗即可訪問 */ @Override public boolean shouldFilter() { //共享RequestContext,上下文對象RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); System.out.println(request.getRequestURI()); //需要權限校驗URL if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) { return true; } else if ("/apigateway/order/api/v1/order/list".equalsIgnoreCase(request.getRequestURI())) { return true; } else if ("/apigateway/order/api/v1/order/find".equalsIgnoreCase(request.getRequestURI())) { return true; } return false; } /** * 業務邏輯 * 只有上面返回true的時候,才會進入到該方法 */ @Override public Object run() throws ZuulException { //JWT RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); //token對象,有可能在請求頭傳遞過來,也有可能是通過參數傳過來,實際開發一般都是請求頭方式 String token = request.getHeader("token"); if (StringUtils.isBlank((token))) { token = request.getParameter("token"); } System.out.println("頁面傳來的token值為:" + token); //登錄校驗邏輯 如果token為null,則直接返回客戶端,而不進行下一步接口調用 if (StringUtils.isBlank(token)) { // 過濾該請求,不對其進行路由 requestContext.setSendZuulResponse(false); //返回錯誤代碼 requestContext.setResponseStatusCode(HttpStatus.UNAUTHORIZED.value()); } return null; } }
2、關鍵說明
(1)方法說明
filterType : filter類型,分為pre、error、post、 route
filterOrder: filter執行順序,通過數字指定,數字越小,執行順序越先
shouldFilter: filter是否需要執行 true執行 false 不執行
run : filter具體邏輯(上面為true那麽這裏就是具體執行邏輯)
(2)filter類型說明
pre: 請求執行之前filter
route: 處理請求,進行路由
post: 請求處理完成後執行的filter
error: 出現錯誤時執行的filter
3、測試
先在請求頭和傳參都不傳token,校驗失敗:返回401狀態碼
在參數的時候傳入token值
看後臺輸出
說明模擬校驗通過,返回用戶信息。
二、接口限流搭建
接口限流可以在nginx層面做限流,也可以在網關層面做限流,這裏在網關層面做限流,基於guava框架來做網關限流。
先對guava框架限流的概念進行講解下:
它的大致意思就是每一個請求進來先到桶裏去拿令牌,拿到令牌的請求放行,假設你設置了1000個令牌,如果拿完了,那麽後面來調接口的請求就需要排隊等有新的令牌才能調用該接口。
OrderRateLimiterFilter限流過濾類
/** * 訂單限流 *其它和上面都一樣,只是run()中邏輯不一樣 */ @Component public class OrderRateLimiterFilter extends ZuulFilter { //每秒產生1000個令牌 private static final RateLimiter RATE_LIMITER = RateLimiter.create(1000); @Override public String filterType() { return PRE_TYPE; } @Override public int filterOrder() { return -4; } @Override public boolean shouldFilter() { RequestContext requestContext = RequestContext.getCurrentContext(); HttpServletRequest request = requestContext.getRequest(); //只對訂單接口限流 if ("/apigateway/order/api/v1/order/save".equalsIgnoreCase(request.getRequestURI())) { return true; } return false; } @Override public Object run() throws ZuulException { RequestContext requestContext = RequestContext.getCurrentContext(); //就相當於每調用一次tryAcquire()方法,令牌數量減1,當1000個用完後,那麽後面進來的用戶無法訪問上面接口 //當然這裏只寫類上面一個接口,可以這麽寫,實際可以在這裏要加一層接口判斷。 if (!RATE_LIMITER.tryAcquire()) { requestContext.setSendZuulResponse(false); //HttpStatus.TOO_MANY_REQUESTS.value()裏面有靜態代碼常量 requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value()); } return null; } }
我只是偶爾安靜下來,對過去的種種思忖一番。那些曾經的舊時光裏即便有過天真愚鈍,也不值得譴責。畢竟,往後的日子,還很長。不斷鼓勵自己,
天一亮,又是嶄新的起點,又是未知的征程(上校10)
SpringCloud(8)---zuul權限校驗、接口限流