最近遇到一個需求,就是在單體架構的系統上要將系統中的文件資源分離到另一個資源系統中,這時候就需要考慮到跨域的問題了。網上解決方式有以下幾種:
網上跨域的解決方案
Java中解決跨域的方式主要有兩種:
1)第一種解決方法 后台代碼在被請求的Servlet中添加Header設置response.setHeader("Access-Control-Allow-Origin", "*");
2)通過jsonp跨域請求的方式(具體什么是jsonp跨域百度上可以搜索到很多資料,這里就不過多解釋)
但是java處理的跨域問題只是解決了前端可以正常調用跨域訪問不同后台的接口的問題,但是session還是會因為跨域的問題而失效。所以我又找了一下網上解決保證跨域session不失效的解決方案:
1、基於NFS的Session共享
2、基於數據庫的Session共享
3、基於Cookie的Session共享
4、基於Memcache或redis的Session共享
我需要的只是在跨域的時候session不失效就ok了,但是這幾種解決方式感覺代價太大,不太適合我們目前的小系統開發要求。於是我就想到先去了解cookie和session的執行流程
Cookie、session的交互原理
Cookie是保存在客戶端,session是保存在服務器端的,具體的詳細介紹百度有很多,這里就不用介紹了。首先我們需要處理cookie跨域的問題,保證都是共享一個cookie。Cookie跨域需要處理兩個屬性:
1、cookie.setDomain("www.baidu.com"); // 設置域名
2、cookie.setPath("/search"); // 設置路徑
一般我們需要把path設置為“/”代表根路徑。Domain設置為同一一個一級域名,如:aaa.hshkj.com/bbb.hshkj.com,我們就可以設置 COOKIE 的域為 .hshkj.com,這樣兩個子域名就可以訪問此COOKIE。這樣各個服務器共享同一客戶端 SESSION ID 的目的就達到了。一下是cookie跟session交互的流程圖:
理解的cookie與session的交互流程,我們就明白了session失效的原因,比如客戶端訪問A服務器的時候,生成的jsessionid的之為11111,但是當瀏覽器去調用B服務器的資源時,會攜帶這個jsessionid過去,發現B服務器上沒有與之對應的session,這時B服務器又會生成一個新的session,並通過set-cookie方法把與該新的session對應的jsessionid(如222)設置到cookie中,這時候瀏覽器的jsessionid就變為了222,當瀏覽器再訪問A服務器時,發現與222對應的沒有session,這時候A服務器又會重新生成新的session
解決cookie、session跨域問題,如何解決session因跨域而失效的問題
知道了問題的所在,那我們可以提出解決的方案了(方法一是我提出的解決方案,方法二是網上提供的方案):
1、保證jsessionid在兩個server的上都一致,這樣就不會重新生成session了
2、因為我用的是tomcat,所以我們可以讓自己的tomcat使用各自的jsessionid
第一種的解決方案的樣例代碼
在資源服務器中添加一個filter類,在doFilter方法中執行
String jsessionId = CookieUtils.getCookieValue(httpRequest, "JSESSIONID");
//將session獲取出來
HttpSession session = httpRequest.getSession();
//System.out.println("-----jsessionId------->>"+jsessionId);
CookieUtils.setCookie(httpRequest, response, "JSESSIONID", jsessionId);
第二種方法,tomcat的\conf\context.xml,修改session的別名
<Context sessionCookieName="SHGJSESSIONID" sessionCooliePath="/">
這樣在該tomcat下獲取jsessionid別名就是SHGJSESSIONID對應的值
注意:方法一的時候要先獲取session,然后再通過cookie修改JSESSIONID的值,這樣才能保證JSESSIONID的值沒有變。因為如果獲取session 的放在我們定義的cookie后面的話,系統在自動生成session時,調用setcookie方法就會在我們的setcookie的后面,這樣就達不到我們想要設計的效果了。
總結:其實很多時候,我們要解決問題時,我們都是需要先了解原理,然后再大膽的猜測解決方案,大膽的去嘗試,你就會收到意想不到的效果