路由:她會把外部全部對請求轉發到具體的微服務實例上,是實現外部訪問同一接口的基礎html
過濾: 就是權限的檢查, 判斷當前的請求是否有權限區訪問那些服務集羣java
搭建後臺網關:spring
導入eureka - client, 它自己也是一個客戶端,須要註冊進eureka後端
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-zuul</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency>
過濾器, 重寫下面的ZuulFilter能夠實現自定義的過濾規則, 每一個方法的含義都經過註釋的方式寫在了方法頭安全
網關的過濾器 @Component public class WebManagerFilter extends ZuulFilter { /** * 指定過濾器的類型 pre :能夠在請求被路由以前調用 route :在路由請求時候被調用 post :在route和error過濾器以後被調用 error :處理請求時發生錯誤時被調用 * @return */ @Override public String filterType() { return "pre"; } /** * 指定過濾器的優先級, 0表示優先執行, 由於咱們能夠寫不少個過濾器 * @return */ @Override public int filterOrder() { return 0; } /** * 當前過濾器是否開啓, true表示開啓 * @return */ @Override public boolean shouldFilter() { return true; } /** * 過濾器執行邏輯, 返回任意Object類型的值,都表示放行,包括null * 若是不想日後繼續執行了,就使用 setSendZullResponse(false) * @return * @throws ZuulException */ @Override public Object run() throws ZuulException { System.out.println("通過了後臺的過濾器"); return null; } }
咱們能夠經過RequestContext的實例對象,獲取出請求頭,請求parms,請求ip等信息, 針對不一樣的信息能夠作出不一樣的處理前後端分離
黑白名單ide
好比咱們能夠在網關中禁用掉惡意訪問的ip地址微服務
驗證權限工具
若是項目是先後端分離使用jwt等工具生成token放在請求頭中作安全驗證,咱們也能在網關中對請求頭作出初步解析處理post
防止抓包
還能根據用戶請求中發送過來的請求參數作驗證簽名處理, 防止數據在傳輸過程當中被惡意篡改
此外,網關會過濾掉一些請求的請求頭,若是請求頭是咱們本身定義的,就好比下面的Authrization, 通過網關後的請求的頭信息會丟失,進而致使下面的這段代碼失效, 獲取不出頭信息,就沒辦法驗證token的合法性
解決辦法: 選着添加添加一條配置信息 sensitive-headers:
將這個配置置空,意爲清空網關要過濾的請求頭
RequestContext currentContext = RequestContext.getCurrentContext(); String header = currentContext .getRequest().getHeader("Authorization"); System.err.println("zull header "+header); // 判斷是否存在header if (!"".equals(header)&&header!=null){ System.err.println("轉發header"); currentContext.addZuulRequestHeader("Authorization",header); }
使用過濾器作驗證的邏輯以下,驗證攜帶在請求頭中的token信息以下:
這個方法的特色就是, 只要他能在遇到 return null
就表示成功完成了驗證的邏輯
1. 導入 common,咱們要使用它的jwtUtil @Override public Object run() throws ZuulException { System.err.println("通過了後臺的過濾器"); RequestContext currentContext = RequestContext.getCurrentContext(); HttpServletRequest request = currentContext.getRequest(); // 獲取出請求頭 String header = request.getHeader("Authorization"); // 放行zuul的第一次請求 todo 我並無觸發這個方法的執行 if (request.getMethod().equals("OPTIONS")){ System.err.println("OPTIONS"); return null; } // 放行登陸請求 if (request.getRequestURL().indexOf("login")>0){ return null; } if (StringUtils.isNotBlank(header)){ if (header.startsWith("Bearer ")){ String token = header.substring(7); if (StringUtils.isNotBlank(token)){ System.out.println("token=="+token); try{ Claims claims = jwtUtil.parseJWT(token); String roles =(String) claims.get("roles"); System.out.println("roles=="+roles); // 對admin放行, if (roles.equals("admin")){ return null; } // todo 轉發頭信息,我改了配置文件, 讓zuul不過濾任何頭信息 // 其餘狀況, 終止訪問 currentContext.setSendZuulResponse(false); }catch (Exception e){ // 解析token出現的異常,說明token有問題, 終止本次請求 System.out.println("token出錯了,終止本次訪問: "+e); currentContext.setSendZuulResponse(false); } } } } currentContext.setSendZuulResponse(false); currentContext.getResponse().setContentType("text/html;chatset=utf-8"); try { currentContext.getResponse().getWriter().write("權限不足"); } catch (IOException e) { e.printStackTrace(); } return null; }