电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

前后端分離和跨域問題的詳細解決方案(CORS的原理)

瀏覽:132日期:2022-06-06 16:55:59
目錄
  • 前后端分離
    • 前后端分離的好處
    • 個人理解上存在兩種解釋
  • 跨域問題存在的原因
    • 跨域問題的解決方案
      • 修改瀏覽器配置解決跨域
        • 使用jsonp解決跨域
          • CORS解決跨域
            • 服務軟件實現跨域
              • 基于Apache的服務
              • 基于Nignx的服務
          • 總結

            前后端分離

            前后端分離的好處

            1. 最大的好處就是前端JS可以做很大部分的數據處理工作,對服務器的壓力減小到最小。
            2. 后臺錯誤不會直接反映到前臺,錯誤接秒較為友好。
            3. 由于后臺是很難去探知前臺頁面的分布情況,而這又是JS的強項,而JS又是無法獨立和服務器進行通訊的。所以單單用后臺去控制整體頁面,又或者只靠JS完成效果,都會難度加大,前后臺各盡其職可以最大程度的減少開發難度。

            個人理解上存在兩種解釋

            • 第一種只是單純的前后端分離,實在物理層面上的,將View層的任務分配給前端,Controller和Model層給后端,這就存在一個問題,就是后端的同事需要去關注前端的展示邏輯、而前端只要存在變化,后端的數據處理需要做相應的改變。
            • 第二種是基于職責層面上的分離,將View和Controller層分配的前端,后端只處理Model和業務處理,這就需要Controller使用Node.js,M-V-C對應的是JAVA/PHP-JAVASCRIPT、HTML、CSS-Node.js。

            跨域問題存在的原因

            隨著前后端分離技術的越來越盛行,跨域問題也逐漸凸顯了出來。跨域問題的根本原因:因為瀏覽器收到同源策略的限制,當前域名的js只能讀取同域下的窗口屬性。什么叫做同源策略?就是不同的域名, 不同端口, 不同的協議不允許共享資源的,保障瀏覽器安全。同源策略是針對瀏覽器設置的門檻。如果繞過瀏覽就能實現跨域,所以說早期的跨域都是打著安全路數的擦邊球,都可以認為是 hack 處理。這一段是我從別的地方cp過來的,大家將就著看吧。

            這里要注意的是,只有訪問類型為xhr(XMLHttpRequest)的才會出現跨域。

            跨域問題的解決方案

            • 修改瀏覽器的設置
            • 修改請求的方式:jsonp
            • CORS

            修改瀏覽器配置解決跨域

            以Google Chrome為例,瀏覽器以

            "C:\ProgramFiles(x86)\Google\Chrome\Application\chrome.exe"
            --disable-web-security--user-data-dir

            中模式打開,右鍵點擊瀏覽器快捷方式,在目標中輸入上述代碼即可解決(不推薦)。

            使用jsonp解決跨域

            JQuery中的正常AJAX請求代碼片段

            $("#demo1").click(function(){    $.ajax({url : "http://www.tpadmin.top/Index/Test/crossDomain",data : {},type : "get",success : function (res) {    //No "Access-Control-Allow-Origin" header is present on the requested resource. Origin "http://127.0.0.1" is therefore not allowed access. 在執行時候報出的錯誤,這代表了跨域錯誤    alert(res);}    });});?

            JQuery中的使用JSONP的AJAX請求代碼:

            $("#demo2").click(function(){    $.ajax({url : "http://www.tpadmin.top/Index/Test/crossDomain",data : {},type : "get",dataType : "jsonp", success : function (res) {    alert(res);}    });});

            這時候我們看到 請求的網址自動變成了

            http://www.tpadmin.top/Index/Test/crossDomain?callback=jQuery331015214102388989237_1534993962395&_=1534993962396

            這是為什么呢?原來由于跨域訪問的只限制xhr類型的請求(上文中已經說了),所以js中就利用了這一特點,讓服務端不在返回的是一個JSON格式的數據,而是返回一段JS代碼,將JSON的數據以參數的形式傳遞到這個函數中,而函數的名稱就是callback參數的值,所以我們還需要修改服務端的代碼,代碼如下:

            <?php    $callback = isset($_GET["callback"])?$_GET["callback"]:"";    if (!empty($callback)) {$arr = ["code" => 200, "name" => "cui"];$data = json_encode($arr);exit($callback . "(" . $data . ")");    }?>

            OK,現在問題解決了,但是JSONP存在著諸多限制,下面將列出兩個個我知道的:

            JSONP只支持GET請求,什么?你要提交表單,sorry,此路不通它只支持跨域HTTP請求

            雖然只有兩個,但是讓很多人不得不放棄它,所以出現了下面的解決辦法。

            CORS解決跨域

            回歸問題本質,跨域問題為什么會產生,上面已經說了,是由于瀏覽器的限制,那么在執行過程中有什么不同,下面兩張度分析一下(主要看請求頭的部分):

            這是非跨域請求

            這是跨域請求

            這時我們發現跨域訪問的請求頭中存在Origin的字段,用來記錄當前的訪問域名,我們可以再服務端增加一個響應頭Access-Control-Allow-Origin來告訴瀏覽器我們支持它獲取就可以了,代碼實現:

            <?phpheader("Access-Control-Allow-Origin:http://127.0.0.1");$arr = ["code" => 200, "name" => "cui"];echo $data = json_encode($arr);?>

            那如果我有多個域名進行跨域訪問呢

            <?php$requestHeader = getallheaders();$origin = isset($requestHeader["Origin"])?$requestHeader["Origin"]:"";switch ($origin) {    case "http://127.0.0.1":header("Access-Control-Allow-Origin:http://127.0.0.1");break;    case "http://localhost":header("Access-Control-Allow-Origin:http://localhost");break;    default:break;}$arr = ["code" => 200, "name" => "cui"];echo $data = json_encode($arr);//注意,不支持下面這種寫法//header("Access-Control-Allow-Origin:http://localhost,http://127.0.0.1");?>

            或者直接寫成(很不安全,不推薦這么寫)

            <?phpheader("Access-Control-Allow-Origin:*");$arr = ["code" => 200, "name" => "cui"];echo $data = json_encode($arr);?>

            到這里,其實已經結束了,但還有一些其他的特殊情況

            • 請求方法不是GET、HEAD、POST
            • 請求頭中存在自定義頭
            • Content-Type不是text/plain、multipart/form-data、application/x-www-form-urlencoded
            • 希望獲取到服務端的Cookie

            為了應對種種限制,我們再來看一段代碼

            $("#demo1").click(function(){    $.ajax({url : "http://cui.tpadmin.top/crossDomain.php",data : {},type : "PUT",contentType : "application/json",header: {    token:"asdfgqwerttyyazxcvbvb"},success : function (res) {    alert(res);}    });});

            雖然我們在服務端加入了Access-Control-Allow-Origin響應頭,但是如果出現上面所說的情況時,我們需要做一些特殊的設置,修改服務端代碼為:

            <?php//這里增加了兩行代碼header("Access-Control-Allow-Headers:Content-Type");header("Access-Control-Allow-Methods:PUT");$requestHeader = getallheaders();$origin = isset($requestHeader["Origin"])?$requestHeader["Origin"]:"";switch ($origin) {    case "http://127.0.0.1":header("Access-Control-Allow-Origin:http://127.0.0.1");break;    case "http://localhost":header("Access-Control-Allow-Origin:http://localhost");break;    default:break;}$arr = ["code" => 200, "name" => "cui"];echo $data = json_encode($arr);?>

            這里雖然成功了,但是我們發現每次請求的時候會出現兩條請求記錄(這個可不是我請求了兩次,看下面截圖)

            這里我們需要進行一下區分(簡單請求模式與非簡單請求模式)

            • 請求方法只能為GET、HEAD、POST
            • 請求頭中無自定義頭
            • Content-Type必須為text/plain、multipart/form-data、application/x-www-form-urlencoded

            符合以上條件的為簡單請求,否則為非簡單請求,注意,非簡單請求中,瀏覽器會默認發送兩條請求,第一條為預檢請求(OPTION),第二條為AJAX的請求,處于服務器的性能考量,我們需要將預檢命令進行緩存,而不是每次都執行預檢請求,我們可以修改代碼如下:

            <?phpheader("Access-Control-Allow-Headers:Content-Type");header("Access-Control-Allow-Methods:PUT");//看這里header("Access-Control-Max-Age:3600");$requestHeader = getallheaders();$origin = isset($requestHeader["Origin"])?$requestHeader["Origin"]:"";switch ($origin) {    case "http://127.0.0.1":header("Access-Control-Allow-Origin:http://127.0.0.1");break;    case "http://localhost":header("Access-Control-Allow-Origin:http://localhost");break;    default:break;}$arr = ["code" => 200, "name" => "cui"];echo $data = json_encode($arr);?>

            這次我請求了兩次,發現第二次請求沒有發送預檢請求,新增加的代碼代表允許緩存的時間(3600S)。

            另外還有一些常用的方法,我都放到這里了,有需要的小伙伴可以參考

            <?php//支持Cookieheader("Access-Control-Allow-Credentials:true");//支持自定義頭header("Access-Control-Allow-Headers:token,Content-Type,...");??

            由于篇幅有限,Cookie的例子小伙伴們自己做就可以了,使用Cookie的時候需要注意Access-Control-Allow-Origin不可設置為*。

            服務軟件實現跨域

            上面的例子實現了跨域訪問,但是如果我不想在代碼中修改,還有其他的方法嗎,當然有了,我們可以直接修改服務軟件,下面將從最常用的Apache與Nignx兩個方面說明

            基于Apache的服務

            <VirtualHost *:80>  ServerName localhost  ServerAlias localhost  DocumentRoot "${INSTALL_DIR}/www"    Header always set Access-Control-Allow-Header "PUT"  Header always set Access-Control-Allow-Credentials "true"  Header always set Access-Control-Max-Age "3600"  #這里設置的為全匹配  Header always set Access-Control-Allow-Origin "expr=%{req:origin}"  #這里設置的為全匹配  Header always set Access-Control-Allow-Headers "expr=%{req:Access-Control-Allow-Headers}"    <Directory "${INSTALL_DIR}/www/">    Options +Indexes +Includes +FollowSymLinks +MultiViews    AllowOverride All    Require local  </Directory></VirtualHost> 

            這里說明一下,由于Apache都是模塊管理,所以這里要想使用Header的話,需要加載mod_headers.so這個模塊,去看一下自己的主配置文件,這個模塊是否開啟,如果沒有開啟,apache會啟動失敗的。

            LoadModule headers_module modules/mod_headers.so

            由于本人學藝不精,Apache的配置中的判斷沒有完全鬧懂,所以這里沒有進行區分的匹配,如果有大神知道,請指導一下,不勝感激。

            基于Nignx的服務

            在nignx服務的配置中修改為如下代碼(注意位置,這個例子是修改本地的nignx,沒有域名,如果沒有熟悉過nignx的小伙伴可以自行百度)。

            server {    listen       80 default_server;    listen       [::]:80 default_server;    server_name  _;    root /usr/share/nginx/html;    # Load configuration files for the default server block.    include /etc/nginx/default.d/*.conf;    location / {    #支持其他請求    add_header Access-Control-Allow-Methods PUT;    #設置預檢請求的緩存    add_header Access-Control-Max-Age 3600;    #允許Cookie    add_header Access-Control-Allow-Credentials true;    #這里最好做判斷,怕麻煩的話就寫*,但是不建議    if ($http_origin = http://localhost){    add_header Access-Control-Allow-Origin http://localhost;    }    if ($http_origin = http://127.0.0.1){    add_header Access-Control-Allow-Origin http://127.0.0.1;    }    #為了方便,這樣寫了    add_header Access-Control-Allow-Headers $http_access_control_request_headers;    if ($request_method = OPTIONS){    return 200;    }    }    error_page 404 /404.html;location = /40x.html {    }    error_page 500 502 503 504 /50x.html;location = /50x.html {    }}

            另外再說一句,如果您使用的是JAVA的話,可以嘗試一下正反向代理。

            總結

            到此這篇關于前后端分離和跨域問題解決的文章就介紹到這了,更多相關前后端分離和跨域解決內容請搜索以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持!

            標簽: PHP
            主站蜘蛛池模板: 济南侦探调查-济南调查取证-山东私家侦探-山东白豹调查咨询公司 密集架|电动密集架|移动密集架|黑龙江档案密集架-大量现货厂家销售 | 一体化污水处理设备,一体化污水设备厂家-宜兴市福源水处理设备有限公司 | 猎头招聘_深圳猎头公司_知名猎头公司 | 杰福伦_磁致伸缩位移传感器_线性位移传感器-意大利GEFRAN杰福伦-河南赉威液压科技有限公司 | 岛津二手液相色谱仪,岛津10A液相,安捷伦二手液相,安捷伦1100液相-杭州森尼欧科学仪器有限公司 | 打包钢带,铁皮打包带,烤蓝打包带-高密市金和金属制品厂 | 深圳市万色印象美业有限公司| 七维官网-水性工业漆_轨道交通涂料_钢结构漆 | 泰兴市热钻机械有限公司-热熔钻孔机-数控热熔钻-热熔钻孔攻牙一体机 | 深圳激光打标机_激光打标机_激光焊接机_激光切割机_同体激光打标机-深圳市创想激光科技有限公司 深圳快餐店设计-餐饮设计公司-餐饮空间品牌全案设计-深圳市勤蜂装饰工程 | 菲希尔FISCHER测厚仪-铁素体检测仪-上海吉馨实业发展有限公司 | 天津仓储物流-天津电商云仓-天津云仓一件代发-博程云仓官网 | 阿米巴企业经营-阿米巴咨询管理-阿米巴企业培训-广东键锋企业管理咨询有限公司 | 顶呱呱交易平台-行业领先的公司资产交易服务平台 | 高柔性拖链电缆_卷筒电缆_耐磨耐折聚氨酯电缆-玖泰特种电缆 | 天助网 - 中小企业全网推广平台_生态整合营销知名服务商_天助网采购优选 | Boden齿轮油泵-ketai齿轮泵-yuken油研-无锡新立液压有限公司 | 上海噪音治理公司-专业隔音降噪公司-中广通环保 | 伸缩器_伸缩接头_传力接头-巩义市润达管道设备制造有限公司 | 警方提醒:赣州约炮论坛真的安全吗?2025年新手必看的网络交友防坑指南 | Win10系统下载_32位/64位系统/专业版/纯净版下载| 北京律师事务所_房屋拆迁律师_24小时免费法律咨询_云合专业律师网 | 蜂窝块状沸石分子筛-吸附脱硫分子筛-萍乡市捷龙环保科技有限公司 | 净化车间_洁净厂房_净化公司_净化厂房_无尘室工程_洁净工程装修|改造|施工-深圳净化公司 | 活性炭厂家-蜂窝活性炭-粉状/柱状/果壳/椰壳活性炭-大千净化-活性炭 | R507制冷剂,R22/R152a制冷剂厂家-浙江瀚凯制冷科技有限公司 | 阿尔法-MDR2000无转子硫化仪-STM566 SATRA拉力试验机-青岛阿尔法仪器有限公司 | 电脑知识|软件|系统|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网 | 短信通106短信接口验证码接口群发平台_国际短信接口验证码接口群发平台-速度网络有限公司 | 低温柔性试验仪-土工布淤堵-沥青车辙试验仪-莱博特(天津)试验机有限公司 | 苏州同创电子有限公司 - 四探针测试仪源头厂家| 免费B2B信息推广发布平台 - 推发网 | 南京欧陆电气股份有限公司-风力发电机官网| 煤棒机_增碳剂颗粒机_活性炭颗粒机_木炭粉成型机-巩义市老城振华机械厂 | NBA直播_NBA直播免费观看直播在线_NBA直播免费高清无插件在线观看-24直播网 | 高压微雾加湿器_工业加湿器_温室喷雾-昌润空气净化设备 | 创客匠人-让IP变现不走弯路| 合肥角钢_合肥槽钢_安徽镀锌管厂家-昆瑟商贸有限公司 | 安徽集装箱厂-合肥国彩钢结构板房工程有限公司 | 台湾Apex减速机_APEX行星减速机_台湾精锐减速机厂家代理【现货】-杭州摩森机电 | 欧必特空气能-商用空气能热水工程,空气能热水器,超低温空气源热泵生产厂家-湖南欧必特空气能公司 |