1. 程式人生 > >前後端分離-跨域會話如何保持?

前後端分離-跨域會話如何保持?

開篇

因為CORS的出現,大大降低了跨域的難度,另到AJAX有了更大的發揮空間,也導致了前後端更加容易實現。但是今天在實現前後端的時候發現了一個問題。在進行session會話管理的時候,前端無法傳送cookie到後端,前端每次訪問後端都相當於一次新的會話,這樣就導致登入後的資訊是無法儲存的。客戶端每一次訪問都需要重新登入。

原因

對於前端來說,seesion欄位是存在cookie中的。在跨域過程中,Cookie是預設不傳送的。就算後端返回set-Cookie欄位,前端也不會儲存Cookie,更不會在下一次訪問的時候傳送到後端了。
因此只要前端可以把cookie傳送到後端,後端就可以根據cookie拿到seeion欄位進行會話驗證。
進過重新對CORS的學習,只要通過3步,就可以讓會話保持。

第一步

在ajax中設定,withCredentials: true。
例如:

$.ajax({
   url: a_cross_domain_url,
   xhrFields: {
      withCredentials: true
   }
});

預設情況下,跨源請求不提供憑據(cookie、HTTP認證及客戶端SSL證明等)。通過將withCredentials屬性設定為true,可以指定某個請求應該傳送憑據。

第二步

服務端的Access-Control-Allow-Origin 不可以設定為”*”,必須指定明確的、與請求網頁一致的域名

第三步

服務端的 Access-Control-Allow-Credentials: true,代表伺服器接受Cookie和HTTP認證資訊。因為在CORS下,是預設不接受的。

PS:
- 在spring boot 中,可以寫一個配置類來實現

@Configuration
public class CORSConfiguration {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public
void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedHeaders("*") .allowedMethods("*") .allowCredentials(true); } }; } }
  • 在SSM中可以寫一個Filter實現。
public class AjaxFilter extends OncePerRequestFilter{  

    @Override  
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)  
            throws ServletException, IOException {  

        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin")); 
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, If-Modified-Since");  
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");  
        response.setHeader("Access-Control-Max-Age", "3600");  
        response.addHeader("Access-Control-Allow-Credentials", "true");  
        response.setCharacterEncoding("UTF-8");  
        response.setContentType("application/json");  
        //此行程式碼確保請求可以繼續執行至Controller  
        filterChain.doFilter(request, response);   
    }  
}  

web.xml

<filter>  
    <filter-name>ajaxFilter</filter-name>  
    <filter-class>xxxx.AjaxFilter</filter-class><!-- 自定義過濾器 -->  
  </filter>  
  <filter-mapping>  
    <filter-name>ajaxFilter</filter-name>  
    <url-pattern>/*</url-pattern>