背景
最近在做sso單點登入,sso登入成功後後端需要把token和使用者資訊以cookie的方式傳送給前端,由於專案是前後端分離的,這就涉及到了前後端跨域共享cookie的問題,下面就說說我在專案中的解決思路。
解決思路一 —— 通過二級域名共享cookie
一開始在網上看了很多的跨域共享cookie的方法,使用最多的是jsonp和cors這兩種,今天我介紹的是另外一種—基於二級域名共享cookie,原因是簡單…(注意:使用二級域名共享cookie有一個限制條件,就是兩個域名的二級域名必須相同)
二級域名
先來介紹一下什麼是二級域名,拿www.baidu.com做例子,com是這個域名的一級域名,baidu.com是這個域名的二級域名,www.baidu.com是這個域名的三級域名,以此類推…
二級域名共享就是兩個域名的的二級域名必須相同,只有符合這個條件它們之間的cookie才能共享。(例如:a.XXX.test.io和b.test.io,這兩個域名的二級域名就是相同的)
程式碼實現(基於JDK1.8)
//新增cookie cookieName
Cookie cookieName = new Cookie("user_name", userName);
cookieName.setDomain("test.io"); //通過二級域名共享cookie
cookieName.setPath("/");
cookieName.setMaxAge(Integer.MAX_VALUE);
cookieName.setSecure(false);
response.addCookie(cookieName);
//新增cookie token
Cookie token = new Cookie("token", token);
token.setDomain("test.io"); //通過二級域名共享cookie
token.setPath("/");
token.setMaxAge(Integer.MAX_VALUE);
token.setSecure(false);
response.addCookie(token);
//關閉瀏覽器時刪除cookie
Cookie token = new Cookie("token", null);
token.setDomain("test.io");
token.setPath("/");
token.setSecure(false);
token.setMaxAge(0); //0代表關閉瀏覽器刪除cookie,負數則關閉瀏覽器cookie失效(沒有刪除)
response.addCookie(token);
引數介紹
domain:需要設定的二級域名(至少是二級域名,可以是三級域名、四級域名…)
path:設定可以訪問cookie的路徑。假如cookie1的path為/test/,cookie2的path為/test/t/,那麼test路徑下的所有頁面都可以訪問到cookie1,而cookie2只有/test/t/下的頁面才能訪問。
maxAge:過期時間(時間單位為秒),設定為負數關閉瀏覽器該cookie失效,設定為0表示刪除該cookie,整數則設定時間過後cookie失效
secure:是否加密方式傳輸,預設false,為true的話只能使用https協議(因為https協議是加密協議,而HTTP不是)。
解決思路二 —— 通過設定response的header
直接上程式碼
@RequestMapping(value = "/test.do")
public void testHandler(HttpServletRequest request, HttpServletResponse response){
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, accept, content-type, xxxx");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Origin", "http://localhost:8080");
Cookie cookieName = new Cookie("user_name", "test");
cookieName.setPath("/");
cookieName.setMaxAge(Integer.MAX_VALUE);
response.addCookie(cookieName);
}
解釋:
“Access-Control-Allow-Headers”:可選欄位,XMLHttpRequest物件的getResponseHeader()方法只能拿到6個基本欄位:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他欄位,就必須在Access-Control-Expose-Headers裡面指定。
“Access-Control-Allow-Methods”:可選欄位,允許請求該介面的方法型別。
“Access-Control-Allow-Credentials”:可選欄位。它的值是一個布林值,表示是否允許傳送Cookie。預設情況下,Cookie不包括在CORS請求之中。設為true,即表示伺服器明確許可,Cookie可以包含在請求中,一起發給伺服器。這個值也只能設為true,如果伺服器不要瀏覽器傳送Cookie,刪除該欄位即可。
“Access-Control-Allow-Origin”:必填欄位。它的值要麼是請求時Origin欄位的值(如示例中http://localhost:8080),要麼是一個*,表示接受任意域名的請求。
解決思路三 —— 設定@CrossOrigin
先看程式碼實現
@CrossOrigin(origins = "http://localhost:8080", maxAge = 3600, methods = {RequestMethod.OPTIONS, RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE})
@RequestMapping(value = "/test.do")
public void testHandler(HttpServletRequest request, HttpServletResponse response){
Cookie cookieName = new Cookie("user_name", "test");
cookieName.setPath("/");
cookieName.setMaxAge(Integer.MAX_VALUE);
response.addCookie(cookieName);
}
@CrossOrigin註解是被註解的方法具備接受跨域請求的功能。預設情況下,它使方法具備接受所有域,所有請求訊息頭的請求。。。。這個例子中,我們僅接受
http://localhost:8080傳送來的跨域請求。