前段时间,被一个问题整了一天。没错,整整一天,后来我感冒了,不知道是不是和这个事情有关。
问题缘由
因为需求,所以不得不做这样的一件事。前端跨域访问,有很多的解决方案。比如,让本域的服务端作一个代理转发就好啦。又比如,改造这个需求,不跨域也能访问。但我是一个比较执着的人,到后来,我已经抛开需求了。心里就只有一件事,我要跨域,我要解决这个问题。
分析
一开始。程序老是出错,说该用户不存在。我没有留住这个问题,知道后来,发现每一次跨域,都会出现这个问题。debug一下,果然,cookie是空的。这个时候想起以前也看过这方面的资料,前浏览器跨域的时候,默认不带上cookie的!我兴奋了好一阵,以为这个问题就此就绝了。当时还怪自己为什么这样的想不起这个问题。可是,很可惜,还是一样的报错。至于为什么报错,我想不起来了,反正是用了一种不合规的手段。
进阶
查了一下文档,发现有两个地方需要注意。一个是 Access-Control-Allow-Origin
, 一个是 Access-Control-Allow-Credentials
。 前者是允许跨域的来源,后者则是是否允许浏览器带上其cookie。如果允许浏览器跨域访问的话,这两个值需要一起用。
怎么用
Access-Control-Allow-Origin: <origin> | *
Access-Control-Allow-Credentials: true
可是,这里又有一个关键的问题。如果设置 Access-Control-Allow-Credentials
的值为true的时候,Access-Control-Allow-Origin
就不能设为*
号了。至于为什么,估计是安全问题吧。不管怎样,反正现实就是不支持,浏览器会直接报错了。这个时候,该如何是好?我既要允许所有客户端能访问我的服务,又要它们能带上cookie过来。如果仔细一看,会发现 Access-Control-Allow-Origin
的值可以为特定的origin。如果我们在每一个用户访问我们服务的时候,动态地设置为用户当前域,不就行了吗?具体的做法是
1、对于用户A, 每次来的时候,直接设置 Access-Control-Allow-Credentials: true
。
2、获取该用户的origin(用户当前浏览器域名),然后将这个值赋值给Access-Control-Allow-Origin
。
思考
这里有一个比较好的实现思路---动态设置允许当前访问者跨域,而不是粗暴地设置为*
.一开始因为思路打不开,一直在纠结这个问题,设置一度认为此题无解。实际上,如果换一下思路,可能会有意想不到的收获。