摘要:大家都知道可以通過實現跨域。第一種方式在服務下添加一個實現跨域,實現起來方便。前端服務和后端服務在同一臺服務器上,服務調用服務時,服務通過負載均衡進入服務時時,服務的請求跨域成功,時,服務的請求跨域失敗。
大家都知道spring boot 可以通過@CrossOrigin實現跨域。但是在spring cloud 里,如果要粒度那么細的去控制跨域,這個就太繁瑣了,所以一般來說,會在路由zuul里實現。
第一種方式:corsFilter在zuul服務下添加一個corsFilter實現跨域,實現起來方便。代碼如下
@Configuration public class GateWayCorsConfig { @Bean public FilterRegistrationBean corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("*"); //這個請求頭在https中會出現,但是有點問題,下面我會說 //config.addExposedHeader("X-forwared-port, X-forwarded-host"); source.registerCorsConfiguration("/**", config); FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); bean.setOrder(Ordered.HIGHEST_PRECEDENCE); return bean; } }
經過測試,這樣的配置在http的情況下跨域是OK的,但是當我的環境切換的https的情況下就發生了奇怪的問題。說明一下我遇到的問題。
前端 服務A 和 后端服務B 在同一臺服務器上,服務A 調用 服務B 時,服務A通過負載均衡進入服務B時:
http時,服務A的請求跨域成功,https時,服務A的請求跨域失敗。
也就是端口為443的時候,會被認為跨域失敗!!
我一開始對比了請求頭,以為是少了ExposedHeader的"X-forwared-port, X-forwarded-host",但是添加后,還是失敗。因為急著上線,所以我沒有去深入測試到底什么原因引起的https請求跨域失敗。(所以如果大家發現我哪里寫的不對,請務必通知我,讓我也明白為什么失敗!謝謝!)
因為第一種方式在https下失敗后,我嘗試了用zuulfilter實現cors的方式
一共需要兩個filiter:一個pre, 一個post
Pre-Filter:
@Component public class FirstFilter extends ZuulFilter { private Logger logger = LoggerFactory.getLogger(FirstFilter.class); @Override public String filterType() { /* pre:可以在請求被路由之前調用 route:在路由請求時候被調用 post:在route和error過濾器之后被調用 error:處理請求時發生錯誤時被調用 * */ // 前置過濾器 return FilterConstants.PRE_TYPE; } @Override public int filterOrder() { //// 優先級為0,數字越大,優先級越低 return 0; } @Override public boolean shouldFilter() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); //只過濾OPTIONS 請求 if(request.getMethod().equals(RequestMethod.OPTIONS.name())){ return true; } return false; } @Override public Object run() { logger.debug("*****************FirstFilter run start*****************"); RequestContext ctx = RequestContext.getCurrentContext(); HttpServletResponse response = ctx.getResponse(); HttpServletRequest request = ctx.getRequest(); response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("Access-Control-Allow-Headers","authorization, content-type"); response.setHeader("Access-Control-Allow-Methods","POST,GET"); response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host"); response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers"); //不再路由 ctx.setSendZuulResponse(false); ctx.setResponseStatusCode(200); logger.debug("*****************FirstFilter run end*****************"); return null; } }
Pre-Filter 用來處理預處理OPTIONS請求,當發現是OPTIONS請求的時候,給出跨域響應頭,并且不對其進行zuul路由,直接返回成功(200), 給前端服務允許跨域
post-Filter :
@Component public class PostFilter extends ZuulFilter { private Logger logger = LoggerFactory.getLogger(PostFilter.class); @Override public String filterType() { /* pre:可以在請求被路由之前調用 route:在路由請求時候被調用 post:在route和error過濾器之后被調用 error:處理請求時發生錯誤時被調用 * */ // 前置過濾器 return FilterConstants.POST_TYPE; } @Override public int filterOrder() { //// 優先級為0,數字越大,優先級越低 return 2; } @Override public boolean shouldFilter() { RequestContext ctx = RequestContext.getCurrentContext(); HttpServletRequest request = ctx.getRequest(); //過濾各種POST請求 if(request.getMethod().equals(RequestMethod.OPTIONS.name())){ return false; } return true; } @Override public Object run() { logger.debug("*****************PostFilter run start*****************"); RequestContext ctx = RequestContext.getCurrentContext(); HttpServletResponse response = ctx.getResponse(); HttpServletRequest request = ctx.getRequest(); response.setHeader("Access-Control-Allow-Origin",request.getHeader("Origin")); response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("Access-Control-Expose-Headers","X-forwared-port, X-forwarded-host"); response.setHeader("Vary","Origin,Access-Control-Request-Method,Access-Control-Request-Headers"); //允許繼續路由 ctx.setSendZuulResponse(true); ctx.setResponseStatusCode(200); logger.debug("*****************PostFilter run end*****************"); return null; } }
Post-Filter 用來處理 預處理OPTIONS以外的請求,對于正常的請求,不但要給出跨域請求頭,還需要允許請求進行路由(否則你的請求到這兒就結束啦),然后返回狀態碼200。(emmmm……這里要不要返回200,我覺得可能還要想一想……)
按照以上方式配置的話,方法一出現的問題,就得到了解決。服務A能夠正常請求服務B了
雖然是正常實現了需求,但是感覺還是存在很多疑惑,希望大家看到的話,能給我指出不足。一起討論!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76601.html
摘要:類似這樣而在客戶端我們只需要定義一個預定好的回調函數即可。處理跨域請求得到的數據其中的是我們在客戶端定義好的在數據請求成功后要執行的回調函數。 跨域產生的原因 跨域是由瀏覽器的同源策略引起的,即不同源(協議,域名,端口中其中有一個不同)的js是不能讀取對方的資源的。當要網站中的js要請求其他網站的數據時就會產生跨域問題,就像下面這樣,瀏覽器會報錯。 showImg(https://se...
摘要:由于第二種方法如今已經采用的非常少,所以我們在這兒不做講解一帶填充的是一種可以在中繞過同源策略,并發起跨域請求的使用模式,可以啟動的跨域請求同源策略有一個顯著的例外,腳本元素是可以規避檢查的。 講跨域之前,我們先來講同源策略(SOP),同源策略是網景公司提出的一個著名安全策略。所謂同源就是域名、協議、端口相同。例如http://www.12306.cn中,http就是超文本傳輸協議,1...
摘要:例外當涉及到同源策略時,有兩個主要的例外授信范圍兩個相互之間高度互信的域名,如公司域名,不遵守同源策略的限制。端口未將端口號加入到同源策略的組成部分之中,因此和屬于同源并且不受任何限制。 原文鏈接:http://www.devsai.com/2016/11/24/talk-CORS/ 同源策略(same origin policy) 1995年,同源政策由 Netscape 公司引入瀏...
摘要:前端基本功常見概念一點這里前端基本功常見概念二點這里前端基本功常見概念三點這里什么是原型鏈當一個引用類型繼承另一個引用類型的屬性和方法時候就會產生一個原型鏈。函數式編程是聲明式而不是命令式,并且應用程序狀態通過純函數流轉。 前端基本功-常見概念(一) 點這里前端基本功-常見概念(二) 點這里前端基本功-常見概念(三) 點這里 1.什么是原型鏈 當一個引用類型繼承另一個引用類型的屬性和方...
閱讀 2434·2021-11-15 11:36
閱讀 1172·2019-08-30 15:56
閱讀 2243·2019-08-30 15:53
閱讀 1038·2019-08-30 15:44
閱讀 649·2019-08-30 14:13
閱讀 997·2019-08-30 10:58
閱讀 476·2019-08-29 15:35
閱讀 1293·2019-08-29 13:58