前後端分離-跨域會話如何保持?
阿新 • • 發佈:2019-01-25
開篇
因為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>