1. 程式人生 > >VUE+SpringCloud 跨域+Session管理解決辦法

VUE+SpringCloud 跨域+Session管理解決辦法

    近期在做一個商城時,採用前後端分離開發,前端用vue,後臺用SpringCloud微服務。業務流程為,商城前端通過跨域請求微服務閘道器(Zuul叢集),由閘道器路由到各個微服務節點。    遇到的問題:1.請求跨域,2.Session 需要共享,問題大家都知道,不多講,直接上解決辦法。    解決辦法:一.前端:

前端都採用POST方法請求後臺,在main.js中增加一個攔截器

Vue.http.options.emulateJSON = false;
// Vue.http.options.emulateJSON = true;
Vue.http.options.xhr = { withCredentials: true };
Vue.http.interceptors.push((request, next) => {
  request.credentials = true
  next()
});
目的是攔截每一個post請求,設定withCredentials: true屬性,以便客戶端請求強行上送Cookie資訊。二.後臺閘道器

1.跨域問題

在Zuul閘道器建立一個post型別的過濾器,增加以下程式碼:
RequestContext context = RequestContext.getCurrentContext();
HttpServletRequest request = context.getRequest();

String origin = request.getHeader("Origin");
        if(origin == null) {
            origin = request.getHeader("Referer");
        }
        context.addZuulResponseHeader("Content-Type","application/x-www-form-urlencoded");
        context.addZuulResponseHeader("Access-Control-Allow-Origin",origin);
        context.addZuulResponseHeader("Access-Control-Allow-Credentials","true");
2.Seesion管理微服務Seesion管理採用HttpSession。(1)pom.xml 增加依賴
<!-- spring session -->
		<dependency>
			<groupId>org.springframework.session</groupId>
			<artifactId>spring-session</artifactId>
		</dependency>
		<!-- redis -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-redis</artifactId>
			<version>1.4.7.RELEASE</version>
		</dependency>
(2)增加HttpSession全域性配置:
@EnableRedisHttpSession
public class HttpSessionConfig {
    @Bean
    public JedisConnectionFactory connectionFactory() {
        JedisConnectionFactory connection = new JedisConnectionFactory();
        connection.setHostName("192.168.10.10");
        connection.setPort(6379);
        return connection;
    }
}
(3)應用:在Zuul pre型別的過濾器中校驗使用者登入狀態
 RequestContext context = RequestContext.getCurrentContext();
 HttpSession session = request.getSession();
 UserInfo userInfo = (UserInfo) session.getAttribute("userInfo");
 if(userInfo==null){
	 // 需要校驗登入狀態
	context.setSendZuulResponse(false);
	context.setResponseStatusCode(200);
	Iresp_common iresp_common = new Iresp_common("2000","尚未登入");
	context.setResponseBody(gson.toJson(iresp_common));
	return null;
}
以上解決方案只針對安卓瀏覽器,和PC電腦瀏覽器。由於蘋果手機版safari和MAC版Safari預設是阻止向第三方網站請求Cookie資訊的,所以程式層面的跨域解決方案無法繞過IOS系統瀏覽器。如需相容IOS系統,本人想到的辦法是用nginx做代理,人為使前後端處於同一IP,埠環境下,騙過瀏覽器,這樣就不存在跨域問題了。具體辦法如下:通過nginx進行路由配置,凡是http://192.168.10.10:10022/userinfo/**型別的請求全部轉發至http://192.168.10.221:9980/ (Zuul叢集閘道器),以此類推完成如下配置(因目前微服務拆分了四個服務,所以只需配置四條資訊)
http://192.168.10.10:10022/userinfo/**  ==> http://192.168.10.221:9980/ (Zuul叢集閘道器)http://192.168.10.10:10022/開頭的其他請求都轉發至http://192.168.10.10:10020/(前端商城)以上配置完成,即可實現同源訪問。商城地址為:http://192.168.10.10:10020/ 後臺閘道器的IP和埠也為http://192.168.10.10:10020/第二種方案能徹底解決跨域問題,但是開發階段,不適合本地除錯,所以建議兩種方案結合使用,這樣既支援本地PC除錯,也可保證生產環境全面支援安卓和IOS系統。