最近剛接觸laravel框架,首先要寫一個跨域的單點登錄。被跨域的問題卡了兩三天,主要是因為對跨域這快不了解,就在剛才有點茅塞頓開的感覺,我做一下大概整理,主要給一些剛接觸摸不着頭腦的看,哪里寫得不對的,也請大神指點,言歸正傳:
1.先用通俗易懂的話說下原理和幾種跨域的方式,因為網上一搜都是追對某一種方式的專業性解答,我是消化不了多少。
第一種:jsonp 方式,這是什么方式呢,先要說一說JavaScript,在JavaScript中,有一個很重要的安全性限制,被稱為“Same-Origin Policy”(同源策略),也就是說JS只能訪問當前項目的頁面。AJAX是基於XMLHttpRequest(這個請自行百度了解)實現的,所以AJAX 一類的請求肯定也是不能跨域請求的。 然后jsonp方式呢,雖然一般是再$.ajax 方法里面設置dataType: 'jsonp',但是發送請求出去的時候,已經跟ajax 沒多少關系了,不管你設置type : get 還是 post ,它都是通過get發送請求的,可以說這個已經屬於 jsonp 協議了,這是個非官方協議。發一下代碼:
$.ajax({
url: 'http://lrz.laravel.com/auth/login',
type: 'get',
dataType: "jsonp",
jsonp: "callback",
data: {user_id:user_id,name:name},
success: function (data) {
console.log(data);
},
error:function()
{
alert("error");
}
})
當設置dataType 為 jsonp的時候就是jsonp請求了,然后 下面的 jsonp: "callback", 什么意思呢,jsonp方式會在客戶端注冊一個 js 的 callback方法,並通過GET方式發送到服務器,見連接:
jQuery21307739646233126818_1491549029207 這個方法就是客戶端注冊的。
然后服務器端怎么處理呢,接收 callback 的值,並返回一個JS方法的方式告知客戶端,就是 return jQuery21307739646233126818_1491549029207(json_encode([1,2])); 這樣的方式,客戶端才能通過success: function (data) {} 獲取到返回的值了,這就是通過JS注入的方式實現的 跨域請求,順便我發一下 laravel 的返回方式:
$callback = $request->input('callback');
$arr = array('status'=>'200');
$user_id = $request->input('user_id');
$name = $request->input('name');
return response($callback.'('.json_encode($arr).')')->withCookie(Cookie::forever('name', $name))->withCookie(Cookie::forever('user_id',$user_id));
這么寫是為了生成服務器端的cookie,用不着的小伙伴就忽略。
第二種方式就是通過html5 WebSocket標准 W3C方式,這個我一開始跟JSONP 弄混了,這個跟jsonp 又沒關系了,這種方式通過設置一下頭部信息就能實現跨域了,
Access-Control-Allow-Origin : 指明哪些請求源被允許訪問資源,值可以為 "*","null",或者單個源地址。
服務器端主要設置這個值就能讓其他的網址訪問他了,用AJAX就能拿到服務器的數據了。關於laravel的開啟跨域方式可以看這篇文章: http://www.tuicool.com/articles/3yEFVz2,我就不多說了。
我的需求是讓用戶中心在多個子站生成 cookie,然后cookie是服務器告知瀏覽器生成的,所以理論上講POST是不能讓其他網站生成cookie的,所以我這里必須使用jsonp擬跳轉的方式,比如淘寶的用戶登錄就是用這種方式。 還有一種方式是post+動態生成iframe 局部提交頁面,可以參考新浪的用戶登錄模式。不管哪種方式要想跨域生成cookie,就需要跳轉頁面。
有一篇文章說還有一種方法,跨域生成 cookie ,http://www.cnblogs.com/anai/p/4238777.html。 我沒試過,有興趣的朋友可以試試。
第一次寫總結,哈哈,就寫這么多了。