一文了解跨域問(wèn)題

什么是跨域

不同域名之間的資源訪問(wèn)

解決方法

JSONP,CROS

JSONP

  • 原理:html帶src屬性的標(biāo)簽都可以跨域引用,jsonp通過(guò)寫入和讀取src文件內(nèi)容來(lái)實(shí)現(xiàn)跨域。

  • 用法

前端:

$.ajax({
      type: 'GET',
      url: captchaUrl,
      dataType:'jsonp',
      jsonp:'jsoncallback',
      success: function(res){
            $('#captcha').attr('src', res.url);
      }
    });

后端:

$jsoncallback = Yii::$app->request->get('jsoncallback', '');
if ($jsoncallback) {
    Yii::$app->response->format = Response::FORMAT_JSONP;
    $result = ['callback' => $jsoncallback, 'data' => $result];
}
  • 優(yōu)點(diǎn):
  1. 支持較舊的瀏覽器

  2. 可以向不支持CORS的網(wǎng)站請(qǐng)求數(shù)據(jù)

  • 缺點(diǎn):

只支持get請(qǐng)求,導(dǎo)致傳輸文本長(zhǎng)度受限

CROS

  • 原理:請(qǐng)求header添加Access-Control-Allow-Origin相關(guān)屬性

  • 用法:

前端

$.ajax({
      type:"POST",
      url: url,
      data: data,
      xhrFields: {
        withCredentials: true  //需要寫入cookie時(shí)設(shè)置為true,后端也要相應(yīng)設(shè)置
      },
      crossDomain: true,  //允許跨域
      success:function(res){
        success(res);
      },
      error: function(res){
        error(res);
      }
    })

后端

設(shè)置header里的cros屬性,下面是yii2的方法

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors["cors"] = [
        'class' => Cors::className(),
        'cors' => [
            'Origin' => ['http://www.xxxxxx.com', '  //允許的域名,設(shè)置為'*'表示全部允許 
            'Access-Control-Request-Method' => ['POST', 'GET'],  //允許的請(qǐng)求方式
            'Access-Control-Allow-Credentials' => true,   //需要寫入cookie的時(shí)候要設(shè)置為true,前端也要相應(yīng)設(shè)置
        ],
    ];
    return $behaviors;
}

寫入cookie時(shí),如果是簡(jiǎn)單請(qǐng)求,可能有第一次請(qǐng)求無(wú)法寫入,第二次請(qǐng)求才能寫入的問(wèn)題,需要進(jìn)一步實(shí)驗(yàn)。

深入原理請(qǐng)參考:

http://www.ruanyifeng.com/blog/2016/04/cors.html

圖片的跨域問(wèn)題

首先圖片受到url長(zhǎng)度限制不能使用get請(qǐng)求傳輸,所以不能使用jsonp方式跨域。

如果遇到不支持cros的瀏覽器要跨域圖片可以使用flash方式跨域,webuploader,ueditor等都支持配置使用swf文件進(jìn)行圖片傳輸。

服務(wù)器web目錄要添加一個(gè)跨域文件crossdomain.xml,內(nèi)容如下:

<?xml version="1.0" encoding="UTF-8"?>
<cross-domain-policy>
<allow-access-from domain="www.xxxx.com" />
</cross-domain-policy>

簡(jiǎn)單請(qǐng)求和復(fù)雜請(qǐng)求

簡(jiǎn)單請(qǐng)求response直接添加跨域信息

Access-Control-Allow-Origin: http://api.xxx.com

Access-Control-Allow-Credentials: true(可選)

Access-Control-Expose-Headers: FooBar(可選)

復(fù)雜請(qǐng)求會(huì)有一次OPTIONS預(yù)請(qǐng)求,在預(yù)請(qǐng)求中返回:

Access-Control-Allow-Origin: http://api.xxx.com

Access-Control-Allow-Methods: GET, POST, PUT

Access-Control-Allow-Headers: X-Custom-Header

Access-Control-Allow-Credentials: true

Access-Control-Max-Age: 86400 (緩存時(shí)間單位秒,在時(shí)間內(nèi)再次訪問(wèn)該接口就不會(huì)有options預(yù)請(qǐng)求了)

然后再進(jìn)行正式請(qǐng)求,返回內(nèi)容和簡(jiǎn)單請(qǐng)求一樣

laravel框架cros跨域?qū)崿F(xiàn):

laravel路由區(qū)分請(qǐng)求方式,options預(yù)請(qǐng)求要單獨(dú)處理。目前自己寫了一個(gè)中間件實(shí)現(xiàn)跨域。

<?php

namespace App\Http\Middleware;

use Closure;

class Cors
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request $request
     * @param  \Closure $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $response = $next($request);
        $allowOrigins = [
            'http://localhost:8080',
            'http://www.xxxxx.cn',
        ];
        $origin = $request->header('Origin');
        if (in_array($origin, $allowOrigins)) {
            if ($request->isMethod('OPTIONS')) {
                $response->header('Access-Control-Allow-Origin',$origin);
//                $response->header('Access-Control-Allow-Credentials','true');
                $response->header('Access-Control-Allow-Methods','POST, GET, PUT, DELETE');
                $response->header('Access-Control-Allow-Headers','Content-Type,Authorization');
                $response->header('Access-Control-Max-Age','86400');
            }else{
                $response->header('Access-Control-Allow-Origin', $origin);
//                $response->header('Access-Control-Allow-Credentials','true');
            }
        }
        return $response;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 跨域, 為什么需要跨域?跨域有什么不好?怎么實(shí)現(xiàn)跨域? 一、什么是跨域 只要協(xié)議、域名、端口有任何一個(gè)不同,都被當(dāng)...
    Lemon不怕酸啊閱讀 682評(píng)論 0 0
  • 跨域, 為什么需要跨域?跨域有什么不好?怎么實(shí)現(xiàn)跨域? 一、什么是跨域 只要協(xié)議、域名、端口有任何一個(gè)不同,都被當(dāng)...
    井皮皮閱讀 373評(píng)論 0 1
  • 昨天測(cè)試一個(gè)網(wǎng)頁(yè)聯(lián)調(diào)問(wèn)題時(shí)發(fā)送請(qǐng)求總是發(fā)送不成功,因?yàn)闀r(shí)IE8環(huán)境提示很有限,后來(lái)無(wú)奈開(kāi)啟IE調(diào)試模式發(fā)現(xiàn)報(bào)錯(cuò)信心...
    Maker在杭州閱讀 1,249評(píng)論 0 5
  • 1. 是什么? 同域:相同域名,端口相同,協(xié)議相同。 跨域:瀏覽器對(duì)于javascript的同源策略的限制,例如a...
    EmmaQin閱讀 474評(píng)論 0 0
  • 本地跨域與服務(wù)器跨域 前端頁(yè)面與后臺(tái)運(yùn)行在不同的服務(wù)器或不同的域名時(shí),就會(huì)出現(xiàn)跨域問(wèn)題。 本地跨域: 如果是同一臺(tái)...
    LittleTrue閱讀 1,353評(píng)論 0 1

友情鏈接更多精彩內(nèi)容