1. 程式人生 > >關於ajax跨域訪問導致session失效,cookie無法在本地儲存問題分析

關於ajax跨域訪問導致session失效,cookie無法在本地儲存問題分析

       大家可能遇到過,做登入時需要使用session來維護使用者與伺服器之前的關係,可能好多小夥伴不是很清楚session維護的原理,我簡單講一下session的原理,tomcat中session和cookie有著很密切的關聯如下圖

簡單理解就是客戶端和伺服器之間傳遞著一個sessionID,來維護使用者的會話狀態,伺服器端session生命週期為30min,客戶端cookie生命週期也為30min,但是當瀏覽器關閉時客戶端cookie也會隨之消失,伺服器端session不會消失,只能等待30分鐘之後,或者呼叫session.invalidate();可以銷燬session。(另外提醒可以使用firefox的firebug可以檢視網路cookie)

      上述情況是同域時的情況,那麼下面就是關於跨域請求的問題了,首先理解一下什麼情況下是跨域,跨域、跨協議和跨埠都是跨域,我之前沒注意到跨埠也是跨域。那麼回到ajax這個問題上,ajax跨域有方式包括JSONP和CORS(跨域資源共享),我們知道ajax實現的核心是XMLHttpRequest介面,在XHR1中是不支援跨域(同域限制)的,但是XHR2中增加了對CORS的支援,使其能夠支援跨域,不過CORS預設是不攜帶cookie的。CORS是一種需要伺服器和前端配合的跨域技術,首先伺服器必須允許跨域請求,另外客戶端也需要新增響應的欄位才可以攜帶cookie。我是用的是jquery的的ajax,我們看看前端配置

$.ajax({
      type:"POST",
      url:url,
      data:{data,data},
      dataType:"json",
      xhrFields: {withCredentials: true},     //與伺服器配合使用標識允許攜帶cookie
      success:function(data){

      },
      error:function(XMLHttpRequest){

      },
    });

伺服器端我添加了CORSFilter.java

package com.chenhai.educationsystem.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class CrossFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException {
        HttpServletResponse response=(HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest)req;
        
        response.setHeader("Access-Control-Allow-Credentials", "true");  //支援跨域訪問,跨域訪問中cookie是預設忽略的,需要配合前端xhr的Credentials屬性使用,該屬性為true標識允許攜帶cookie
        //response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));  //控制那些源可以訪問如:a.com
        response.setHeader("Access-Control-Allow-Headers", "content-type,authorization,x-requested-with");  //響應首部 Access-Control-Allow-Headers 用於 preflight request (預檢請求)中,列出了將會在正式請求的 Access-Control-Expose-Headers 欄位中出現的首部資訊。
        response.setHeader("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,OPTIONS"); //響應首部 Access-Control-Allow-Methods 在對 preflight request.(預檢請求)的應答中明確了客戶端所要訪問的資源允許使用的方法或方法列表。
        filterChain.doFilter(req, res);
    }

    @Override
    public void destroy() {

    }
}

此處我列出一些相關網站