近期在做一个商城时,采用前后端分离开发,前端用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/order/** ==>
http://192.168.10.221:9980/
http://192.168.10.10:10022/product/** ==>
http://192.168.10.221:9980/
http://192.168.10.10:10022/pay/** ==>
http://192.168.10.221:9980/
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/