第三方支付過程中session失效問題


        問題產行於公司p2c交易平台的一個用戶充值模塊。

 

        平台簡介:該平台通過第三方支付(以下使用“支付寶”代替)完成與各大銀行的交易(充值、投資、轉帳、提現等操作),並將數據保存在我司的服務器數據庫中,服務器使用tomcat,數據庫Mysql

 

        平台充值流程:用戶登陸系統----點擊充值-----跳轉到支付寶----登陸支付寶------選擇銀行------充值完畢-----redrect到用戶中心(平台中的action為"preurl:/user/center"),問題來了,

 

當用戶充值完成后轉回用戶中心時平台轉回了登陸界面,需要用戶重新輸入一次用戶名和密碼才能到達用戶中心。

 

        談到此種現象,但凡搞過java開發的軟件工程師應該都能想到是session問題,好吧,讓我們來一起研究一下從點擊充值到支付完成過程中session的變化。

 

        1、用戶使用username 和 password登陸后會將用戶信息保存在session中,並且在客戶端瀏覽器的cookie中添加一個cookie(key:JSESSIONID,value:XXX);

 

        2、用戶點擊充值按鈕跳轉到支付寶---XX銀行進行充值,由於XX銀行充值網站也是使用tomcat,那么cookie中默認的session key 也為 JSESSIONID,這樣以來充值完畢便修改了cookie中session的值;

 

        3、平台使用spring security的用戶登陸校驗,攔截所有需要用戶登陸的界面,這樣以來,當充值完成返回preurl:/user/center的時候被spring攔截,並取出cookie中JSESSIONID所對應的值再去session里查找用戶信息;

 

        4、由於XX銀行修改過的session與原session並非同一session,於是spring將其攔截到用戶登陸界面;

 

        以上便是一個很常見的跨域訪問session失效問題,但是問題並非想象中那么簡單,至少筆者在此問題上費了很大的力氣,並尋問“眾大神”以及幾千人的技術群,無一人知曉(或許真正的大神不屑一顧吧),現解決辦法及說明總結如下:

 

        1、總體思路

              在用戶點擊充值時將sessionid保存下來,充值成功后再將sessionid取出來替換

 

        2、具體實現

 

               支付寶接口說明中有一個字段叫做merpri(私有域),官方解釋:“用戶自定義字段,可以將自己需要

的信息保存在里面,接口調用完成后原樣返回”,那么正好是我們需要的,在向支付寶write數據時,我將sessionid取到並放入merpri中,然后在回調時將merpri中的值取出,通過遍歷cookie數組將數組中名為JSESSIONID的cookie替換為之前的,關鍵代碼如下:

 

 

//說明:以下代碼為直接在博客中手寫如有錯誤請留言,以便及時更正
//從jsf中獲取
HttpServletRequest request = FacesUtil.getHttpServletRequest ();
HttpServletResponse response = FacesUtil.getHttpServletResponse();
//從支付寶返回參數中獲取之前保存的sessionid
String finalSession = request.getParameter("merpri");
Cookie[] cookies = request.getCookies();
for(Cookie c : cookies){
     if(c.getName.equals("JSESSIONID")){
         //如果是帶域名的網站需要配置,因為現在的問題是跨域session失效
         c.setDomain(".alibaba.com");     
          //刪除cookie
         c.setMaxAge(0);
         //設置路徑(域名后面的主路徑)
         c.setPath("/alibaba");
         response.addCookie(c);
         c.setDomain(".alibaba.com");
         Cookie cookie = new Cookie("JSESSIONID",finalSession);
         //設置生命周期為20分
         cookie .setMaxAge(20);
         cookie .setPath("/");
         response.addCookie(cookie);
     }
}

         3、容易出問題的地方總結:

 

 

             1)  不要將代碼放在耦合性較強的代碼邏輯中

 

             2) cookie中sessionid的操作一定要在返回/user/center 之前最近位置(否則將無法刪除cookie)

 

             3) cookie生命周期和路徑一定要注意匹配,應當使用調試工具查看cookie實時的一個值

 

             4) 設置domain時需要特別注意,經本人測試以下四種瀏覽器:ie 9, firefox, 360安全, 獵豹

 

       其中ie 9 和 firefox域為 .alibaba.com  而360安全,獵豹 的域為www.alibaba.com這樣就會出現:使用不同的瀏覽器設置cookie的域不同而導致其中2個瀏覽器依然無法正常跳轉到用戶中心,解決辦法:在代碼中判斷其內核,根據不同的內核設定不同的域。

                          5) 若使用的第三方支付沒有私有域的概念,那么請使用數據庫代替吧,即:將sessionid放入數據庫中,這樣以來要保證事務的完整性了

 

題外話:

 

(談到瀏覽器的兼容問題,IE瀏覽器不得不讓人大跌眼鏡,眾所知周,所謂“瀏覽器兼容”無非就是IE這個“笨重的家伙”,解析js速度慢到極點,並且效果看上去極差,這一點應該向谷歌和火狐學習),360有個新功能是這樣描述的:

 

         我們新增加了一個控制手段:內核控制Meta標簽。只要你在自己的網站里增加一個Meta標簽,告訴360瀏覽器這個網址應該用哪個內核渲染,哪么360瀏覽器就會在讀取到這個標簽后,立即切換對應的內核。並將這個行為應用於這個二級域名下所有網址。

目前該功能已經在所有的360安全瀏覽器實現。我們也建議其它瀏覽器廠商一起支持這個實現。讓這個控制標簽成為行業標准。

在head標簽中添加一行代碼:

 

<html>
  <head>
    <meta name="renderer" content="webkit|ie-comp|ie-stand">
  </head>
  <body>
  </body>
</html>

 

 

        瀏覽器的兼容問題嚴重困擾了眾多的軟件工程師,不僅僅是前端開發,在此希望能夠出台一個瀏覽器標准將所有的瀏覽器內核規范處理,開發工程師使用這個規范去開發,以減少這種“由於瀏覽器間客戶流量競爭”而給開發者帶來的工作量。

            


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM