国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

Cors跨域(三):Access-Control-Allow-Origin多域名?

安全 應用安全
本文將實戰Cors解決跨域問題中最為重要的響應頭:Access-Control-Allow-Origin。它用于服務端告訴瀏覽器允許共享本資源的Origin,那么如何允許多個域名呢?

[[406060]]

前言

你好,我是YourBatman。

本系列前兩篇文章用文字把跨域、Cors相關概念介紹完了,從下開始進入實戰階段。畢竟學也學了,看也看了,是騾子是馬該拉出來遛一遛。

本文將實戰Cors解決跨域問題中最為重要的響應頭:Access-Control-Allow-Origin。它用于服務端告訴瀏覽器允許共享本資源的Origin,那么如何允許多個域名呢?

本文提綱

版本約定

  • JDK:8
  • Servlet:4.x
  • tomcat:9.x

正文

正如前文所述,響應頭Access-Control-Allow-Origin 用于在跨域請求中告訴瀏覽器服務端允許的Origin,瀏覽器拿到這個頭的值跟自己的Origin對比決定是否正常接收響應。

從命名上就有所察覺:Access-Control-Allow-Origin值是單數,否則就會叫Access-Control-Allow-Origins?

(瀏覽器)官方對此響應頭的可能值有明確規定:

也就說此響應頭的取值只可能是上圖中的3選1。

null值的作用:讓data:和file:打開的頁面也能夠共享跨域資源(因為這種協議下有Origin頭,但是值是null,比較特殊)?

那么問題來了,倘若服務端本資源需要允許多個域來共享,又該如何指定Access-Control-Allow-Origin 的值呢?這是一個開發中常見的場景,本文將繼續深入討論和介紹最佳實踐。

環境準備

因為要構造不同的Origin來發送http://localhost:8080/multiple_origins_cors這個跨域請求,因此需要不同的域名,所以我需要在本機模擬出來。我的實踐方案為:

用本機Tomcat作為靜態頁面服務器,托管html頁面

修改本機host文件,達到支持多域名的目的

1. Tomcat托管靜態html頁面

之前我都是用的IDEA內建的靜態服務器來托管html頁面,但由于它不支持綁定多域名而無法模擬出本例需要的效果,因此我就不得不開辟新的方法嘍。

做Java開發的小伙伴對Tomcat再熟悉不過,但由于Spring Boot的普及它屏蔽了開發者對Web Server的感知,所以可能雖然天天用但其實鮮有接觸,特別是standalone的Tomcat服務器。

所以我這里稍微介紹下我的做法(關鍵步驟)。去到Tomcat的目錄,僅需修改它的server.xml文件即可:

步驟一:修改端口為9090(因為我Server端服務器也是Tomcat,端口為8080,避免沖突)

步驟二:在host里托管Context上下文,關聯到你的html文件夾(Tips:這只是托管的方式之一)

說明:docBase表示靜態頁面所在的文件夾(絕對路徑),path表示對應的url訪問路徑?

完成后,啟動tomcat sh startup.sh后即可通過http://localhost:9090/static/xxx.html訪問到靜態頁面啦。

2. 修改Host支持多域名

這個就比較簡單了,無需多言,粘張圖就懂。

這樣通過如圖中的3個域名就都可對頁面進行正常訪問啦

3. 書寫前端html頁面

  1. <!DOCTYPE html> 
  2. <html lang="en"
  3. <head> 
  4.     <meta charset="UTF-8"
  5.     <title>多Origin響應CORS跨域請求</title> 
  6.     <!--導入Jquery--> 
  7.     <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script> 
  8. </head> 
  9. <body> 
  10. <button id="btn">多Origin響應CORS跨域請求</button> 
  11. <div id="content"></div> 
  12.  
  13. <script> 
  14.     $("#btn").click(function () { 
  15.         // 跨域請求 
  16.         $.get("http://localhost:8080/multiple_origins_cors"function (result) { 
  17.             $("#content").append(result).append("<br/>"); 
  18.         }); 
  19.     }); 
  20. </script> 
  21. </body> 
  22. </html> 

 

 

 

 

 

 

4. 書寫服務端代碼

  1. /** 
  2.  * 多Origin響應 
  3.  * 
  4.  * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a> 
  5.  * @site https://yourbatman.cn 
  6.  * @date 2021/6/9 10:36 
  7.  * @since 0.0.1 
  8.  */ 
  9. @Slf4j 
  10. @WebServlet(urlPatterns = "/multiple_origins_cors"
  11. public class MultipleOriginsCorsServlet extends HttpServlet { 
  12.  
  13.     @Override 
  14.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 
  15.         String requestURI = req.getRequestURI(); 
  16.         String method = req.getMethod(); 
  17.         String originHeader = req.getHeader("Origin"); 
  18.         log.info("收到請求:{},方法:{}, Origin頭:{}", requestURI, method, originHeader); 
  19.  
  20.         resp.getWriter().write("hello multiple origins cors..."); 
  21.         setCrosHeader(resp); 
  22.     } 
  23.  
  24.     /** 
  25.      * 寫跨域響應頭 
  26.      */ 
  27.     private void setCrosHeader(HttpServletResponse resp) { 
  28.         resp.setHeader("Access-Control-Allow-Origin""http://localhost:9090"); 
  29.     } 

至此,環境已經準備好。此頁面有三個地址/域名可以訪問到(不包括localhost),也就是Origin可能有這三種情況:

  • http://foo.baidu.com:9090
  • http://bar.baidu.com:9090
  • http://static.yourbatman.cn:9090

Access-Control-Allow-Origin支持多域名

現實場景中,服務端資源如若是完全公開的,那么可以使用Access-Control-Allow-Origin: *。但在現實場景中大多數資源并非完全public的,因此需要指定Access-Control-Allow-Origin具體值來達到控制的目的。

那么,如何讓Access-Control-Allow-Origin支持多域名呢?下面示范一下常見的錯誤方式,最后給出最佳實踐。

要實現Access-Control-Allow-Origin允許多個域名共享資源,按照“常規思維”,有好些個使用誤區,這里我嘗試羅列出來。

誤區一:Access-Control-Allow-Origin值使用,分隔

,分隔在程序員的世界很常見,很多時候可表示多值。那在這里是否好使呢?試一試

  1. private void setCrosHeader(HttpServletResponse resp) { 
  2.     resp.setHeader("Access-Control-Allow-Origin""http://foo.baidu.com:9090,http://bar.baidu.com:9090"); 

點擊按鈕,發送跨域請求,失敗詳情:

可以看到不僅沒實現多值,連foo.baidu.com:9090這個域名都不能訪問啦~

誤區二:寫多個Access-Control-Allow-Origin響應頭

這種方式也是“正常思維”之一。試一下:

  1. private void setCrosHeader(HttpServletResponse resp) { 
  2.     resp.addHeader("Access-Control-Allow-Origin""http://foo.baidu.com:9090"); 
  3.     resp.addHeader("Access-Control-Allow-Origin""http://bar.baidu.com:9090"); 

小細節:這里將setHeader改用為addHeader(xxx)了喲,你懂的?

點擊按鈕,發送跨域請求,失敗詳情:

多說一句:在實際開發中這種出現兩個Access-Control-Allow-Origin響應頭的case還是比較常見的。根據經驗一般原因是:Web Server設置了一個頭,而Nginx(或者Gateway網關)又添加了一個頭(一般值為*)。

強調:瀏覽器只要收到兩個Access-Control-Allow-Origin響應頭,不論值是什么(即使一模一樣),都不會接受。

誤區三:Access-Control-Allow-Origin值使用正則

當需要允許的多域名符合某個規律時,會想到使用簡單的正則去匹配,那么是否支持呢?試一下:

  1. private void setCrosHeader(HttpServletResponse resp) { 
  2.     resp.addHeader("Access-Control-Allow-Origin""http://*.baidu.com:9090"); 

點擊按鈕,發送跨域請求,失敗詳情:

強調:瀏覽器拿Access-Control-Allow-Origin的值和Origin進行匹配的規則是完全匹配,通配符只認*。

誤區四:Access-Control-Allow-Origin值使用*通配符

這是一個特殊的使用“誤區”:它能正常work,但并不能“很好的work”。試一下

  1. private void setCrosHeader(HttpServletResponse resp) { 
  2.     resp.addHeader("Access-Control-Allow-Origin""*"); 

點擊按鈕,發送跨域請求,正常響應:

 

既然能夠正常響應完成跨域請求,為何我會認為這么處理屬于誤區呢?

其原因主要為:使用*通配符屬于暴力配置,表示任意源都可以訪問此資源,對大部分場景來講這違背了安全原則,存在安全漏洞,所以實際生產中并不建議這么做(除非是public資源)。

使用*通配符的漏洞

為何對使用*樂此不疲?答:因為簡單,似乎能夠解決“所有”跨域問題,且能一勞永逸。正所謂天下哪有那么多歲月靜好,黑客們在那蠢蠢欲動。

在與瀏覽器“溝通”過程中,不恰當的使用Cors會造成一些可能的漏洞,比如最常見的便是當允許多個域名跨域請求時,很多同學為了方便就將Access-Control-Allow-Origin寫為*,或者在Ng上直接賦值為$http_origin(效果完全同*)。這種暴力配置是很危險的,相當于任意網站都可以直接訪問你的資源,那就失去跨域限制的意義了。

這么配置的話,在最基本的滲透測試中都是過不去的。如若你這么做且公司有安全部門,沒過多久應該就會有人找你聊天喝茶了。

別問我為什么會知道,因為我就曾被安全部門同事招呼過???

最佳實踐

來了,期待的最佳實踐它來了。允許多域名跨域是如此常見的場景,本文當然要給出最佳實踐(供以參考)。

既然瀏覽器是精確的完整匹配這個規則我們無法修改,那只有唯一的一個辦法:在服務端給Access-Control-Allow-Origin賦值之前做邏輯:

若允許跨域,將請求的Origin賦值給它

若不允許跨域,不返回此頭(或者給賦值一個默認值也是可以的)

有了理論支撐,用代碼實現乃分分鐘之事:

  1. private List<String> ALLOW_ORIGINS = new ArrayList<>(); 
  2. @Override 
  3. public void init() throws ServletException { 
  4.     ALLOW_ORIGINS.add("http://localhost:9090"); 
  5.     ALLOW_ORIGINS.add("http://foo.baidu.com:9090"); 
  6.     ALLOW_ORIGINS.add("http://bar.baidu.com:9090"); 
  7.     ALLOW_ORIGINS.add("http://static.yourbatman.cn:9090"); 
  8.  
  9. private void setCrosHeader(String reqOrigin, HttpServletResponse resp) { 
  10.     if (reqOrigin == null) { 
  11.         return
  12.     } 
  13.     // 匹配算法:equals 
  14.     if (ALLOW_ORIGINS.contains(reqOrigin)) { 
  15.         resp.addHeader("Access-Control-Allow-Origin", reqOrigin); 
  16.     } 

如果是Ng,可以這么寫(簡單舉例而已):

  1. location / {   
  2.   
  3.  // 枚舉列出允許跨域的domian(可以使用NG支持的匹配方式) 
  4.  set $cors_origin ""
  5.     if ($http_origin ~* "^http://foo.baidu.com$") { 
  6.             set $cors_origin $http_origin; 
  7.     } 
  8.     if ($http_origin ~* "^http://bar.baidu.com$") { 
  9.             set $cors_origin $http_origin; 
  10.     } 
  11.     add_header Access-Control-Allow-Origin $cors_origin; 

既然接管了Access-Control-Allow-Origin賦值邏輯。腦洞更大一點,這可極具個性化和擴展性:

  • ALLOW_ORIGINS:不需要再hard code,可以支持外部化配置,甚至打通配置中心
  • 匹配算法:可以支持完全匹配、前綴匹配、正則匹配,設置更復雜的匹配邏輯都可
  • ...

說了這么多,這些個性化擴展性都需要代碼去實現,那到底有沒有現成可用的最佳實踐代碼呢?

當然,有!!!

作為Java開發者yyds:Spring框架。怎能沒考慮到這么常見的Cors跨域場景呢?它提供的org.springframework.web.filter.CorsFilter就是真實可用的最佳實踐,可以拿來就用或者作為參考和學習。

說明:關于Spring/Spring Boot場景下對Cors跨域問題的解決方案以及原理分析,本系列已安排在下下篇詳細剖析?

補充:Vary: Origin解決緩存問題

在文章最后想補充一個“小知識點”:有關于瀏覽器緩存和Vary的問題。

關于Vary,平時比較細心的同學應該會比較有印象。Vary中文含義:變化。它是一個HTTP響應頭,決定了對于下一個請求,應該使用緩存還是向源服務器請求一個新的Response,和內容協商(你知道的,內容協商也屬于我的一個技術專欄)有關。現在的瀏覽器都支持這個響應頭~

標準語法是:

  1. ary: * // 告訴瀏覽器,所有的響應頭都是變得所以都不緩存 
  2. Vary: <header-name>, <header-name>, ... // 告訴瀏覽器,有些頭都是變的就不要緩存了 

說了這么多,它和本文有何關系呢?

由于這和瀏覽器緩存(cache-control)背景知識強關聯,并非本文重點無需詳細展開。因此這里只是提示你:如若出現同一份URL(相同的Referer),不同的Origin(如foo.baidu.com和bar.baidu.com)請求時一個能行一個不能行,那很有可能就是瀏覽器緩存導致,這時就可以增加一個響應頭Vary: Origin來解決。

?說明:這里假設服務端對Access-Control-Allow-Origin的賦值邏輯一切正常,也就是說服務端沒有問題?

總結

本文圍繞Access-Control-Allow-Origin這個響應頭,從幾大誤區到最佳實踐,希望能夠幫助你加深對它的理解。當然最重要的是:盡量不要一碰到Access-Control-Allow-Origin就只會賦值*啦,多些思考多些安全性考慮,畢竟安全部門的茶水最好還是不要喝。

 

責任編輯:武曉燕 來源: BAT的烏托邦
相關推薦

2021-06-15 07:32:59

Cookie和Sess實現跨域

2019-04-10 10:32:16

CORSNginx反向代理

2014-08-19 10:36:02

AngularCORS

2021-06-25 09:04:39

Cors跨域JSONP vs CO

2022-04-29 09:11:14

CORS瀏覽器

2021-06-10 18:11:02

Cors跨域Web開發Cors

2023-12-20 14:42:59

2013-11-27 10:23:23

2020-08-31 19:20:33

瀏覽器CORS跨域

2019-03-13 14:15:25

CORS跨域資源前端

2024-01-31 07:55:52

2016-11-01 21:51:03

phpjavascript

2020-08-13 07:04:45

跨域CORS瀏覽器

2021-04-27 15:20:41

人工智能機器學習技術

2020-12-18 09:36:01

JSONP跨域面試官

2024-05-20 09:28:44

Spring客戶端瀏覽器

2022-03-21 07:35:34

處理方式跨域

2023-11-20 08:02:49

2009-12-08 14:43:04

WCF跨域

2021-05-06 20:51:52

跨域http協議
點贊
收藏

51CTO技術棧公眾號

美国欧美日韩国产在线播放| 欧美久久天堂| 亚洲精品欧美一区二区三区| 亚洲第一男人天堂| 一区二区成人在线视频| 国产精品自在在线| 亚洲黄页一区| 国产亚洲一区| eeuss国产一区二区三区四区| 羞羞的视频网站| 亚洲一区二区三区sesese| 国内精品久久久| 在线观看视频一区二区欧美日韩| 欧美不卡高清| 中文字幕亚洲精品| 久久五月天婷婷| 久久久久久久网| 欧美日韩亚洲一区| 国产一区二区三区探花| 粉嫩av一区二区三区四区五区| av在线免费观看网| 日韩毛片在线一区二区毛片| 午夜免费一区二区| 欧美老熟妇喷水| 一本久道高清无码视频| 欧美日韩一区二区三| 欧美xxxx做受欧美| 日韩三级在线观看| 欧美一区二区播放| 精品国产乱码久久久久久蜜臀| 精品国产污污免费网站入口| 欧美精品在线一区二区三区| 亚洲婷婷国产精品电影人久久| 国产色一区二区| 亚洲日本一区二区| 亚洲午夜av在线| 在线视频亚洲一区| 5月丁香婷婷综合| 91精品国产91综合久久蜜臀| 日韩精品一区二区三区在线播放| 精品美女被调教视频大全网站| 日韩三级电影网址| 日韩视频一区在线观看| 国产亚洲综合久久| 久久人人97超碰精品888| 国产欧美日韩中文字幕| 114国产精品久久免费观看| 国内精品视频在线播放| 新呦u视频一区二区| 国产美女三级视频| 伊人色综合久久| 美女尤物在线视频| 色综合视频一区二区三区日韩| 欧美一级片网址| 欧美成免费一区二区视频| 蘑菇福利视频一区播放| 成人一区二区三区视频在线观看| 亚洲色图欧美偷拍| 精品国产一区二区三区四区四| 久久影院中文字幕| 国产精品swag| 久久婷婷国产精品| 激情小视频在线| 成人亚洲精品| 最新日韩在线| 久久品道一品道久久精品| 91国内精品野花午夜精品| 中文字幕亚洲色图| 国产精品久久久久久久天堂| 精品999在线观看| 免费看污污网站| 日本动漫同人动漫在线观看| 久久久久毛片免费观看| 国产精品视频久久一区| 1024国产精品| 亚洲午夜激情免费视频| 91久久精品国产91久久性色| 999一区二区三区| 国产露出视频在线观看| 欧美亚洲二区| 美女视频黄免费的久久| 一区二区三区免费网站| 亚洲午夜精品久久久久久久久久久久 | 亚洲精品videossex少妇| 成人欧美一区二区三区在线| 久久久久人妻精品一区三寸| 1区2区3区在线| 噜噜噜天天躁狠狠躁夜夜精品| 高清国产一区二区| 精品粉嫩aⅴ一区二区三区四区| 成人写真视频福利网| 粉嫩tv在线播放| 中文字幕日韩高清在线| 国产精品18久久久久久久久| 亚洲成人黄色网址| 麻豆av一区二区三区| 在线国产中文字幕| 欧美色女视频| 亚洲精品成人天堂一二三| 欧美激情综合亚洲一二区| 国产av天堂无码一区二区三区| 成人观看网址| 国产高清视频一区| 一区二区国产精品视频| 在线观看成人av| 欧美片第一页| 久久99久久99| 亚洲色图美腿丝袜| 成人在线观看你懂的| 警花av一区二区三区| 久久婷婷色综合| 欧美精品久久久久久久久| 欧美,日韩,国产在线| 成人黄色av网址| 日本一区二区视频在线观看| 久久天天躁狠狠躁夜夜爽蜜月| 精品一卡二卡三卡| 国产精品男女| 亚洲综合视频网| 欧美一区二区视频17c| 国内精品一区视频| 久久精品中文| 亚洲视频在线观看视频| 少妇黄色一级片| 性欧美69xoxoxoxo| 精品日韩一区二区三区| 性欧美大战久久久久久久| 香蕉久久精品日日躁夜夜躁| 亚洲mv在线观看| 日韩av在线一区二区三区| 欧美大片黄色| 欧美国产综合一区二区| 成人有码视频在线播放| 日韩理论视频| 亚洲精品乱码久久久久久| 久久国产精品精品国产色婷婷| 亚洲成人激情社区| 一区二区欧美在线观看| 天天干天天操天天干天天操| 精品国产一区二区三区不卡蜜臂| 日韩欧美亚洲综合| 久久综合久久久久| 91tv精品福利国产在线观看| 亚洲精品久久久久| 午夜网站在线观看| 久久精品日产第一区二区 | 日本天堂免费a| 在线精品视频在线观看高清| 亚洲天堂开心观看| 欧洲一区av| 国产欧美日韩另类一区| 免费在线国产精品| 欧美一级做a| 欧美日韩成人在线一区| 女人裸体免费网站| 97精品国产97久久久久久久久久久久| 精品一卡二卡三卡四卡日本乱码| 成人性生交大片免费看中文视频| 综合av第一页| 欧美亚洲色图视频| 日韩精品电影在线观看| 日韩av黄色在线观看| 欧美成人黄色| 日韩精品在线免费观看| 国产大片在线免费观看| 中文字幕一区二区三区不卡在线 | 亚洲成人自拍偷拍| 97在线国产视频| 日韩精品免费视频人成| 国产日韩欧美综合| 精品自拍视频| 欧美日韩亚洲丝袜制服| 男女啪啪网站视频| 国产a级毛片一区| 日本一级黄视频| 国产一区二区在线观看视频| 日产精品一线二线三线芒果| 亚洲大胆av| 亚洲va电影大全| 欧美激情日韩| 国外成人免费视频| 国产亚洲毛片| 日本公妇乱淫免费视频一区三区| 亚洲夜间福利| 国产精品日韩电影| 日韩在线观看一区| 3d动漫精品啪啪一区二区三区免费| 欧美www视频在线观看| 高清不卡一区二区三区| 99精品国产福利在线观看免费| 国产精品黄视频| 国产精品av一区二区| 国产精品美女诱惑| 久久精品国产精品亚洲综合| 亚洲一区二区三区免费观看| 日韩欧美1区| 国产精品久久久久久久久婷婷| 全部av―极品视觉盛宴亚洲| 在线日韩av永久免费观看| 91免费看片在线观看|