记一次iphone 微信内置浏览器跨域无法获取cookie问题的解决方法

http前两天刚完成了一个账号打通的需求,两个站点不是一个域名(暂且用A.com和B.com代替两个站点域名),因此采用了jsonp跨域请求的方式来获取不同域名下的cookie值。jsonp跨域请求在这里就不赘述了,百度一搜一大把。

项目上线两天,被公司一同事发现一个Bug,就是苹果手机的微信账号登出后,再登录微信。在A站点进行登录后,会反复跳转登录页面。通过本地的fiddler进行抓取跳转路径后发现,A站点登录后,通过jsonp请求去B站点下cookie中获取用户的登录状态是未登录。但是我们在B站点的cookie中却有用户的登录信息。(在这里要说明一下,A站点的登录页面集成的是B站的登录控件,因此虽然是在A站点登录,但是用户的登录信息却是写在B站点域名下的cookie中)这样就有问题了,为了检验这个问题是代码逻辑问题还是个例?我们用苹果手机和安卓手机分别对安装的浏览器优先进行了测试,发现A站点登陆后,可以通过jsonp请求拿到B站点cookie中的用户登陆状态。因此可以判定应该不是代码逻辑的问题。

然后进一步验证是不是微信内置的浏览器的问题,我们发现在未退出微信账号的情况下,苹果手机和安卓手机均不会出现上述问题。然后分别退出微信账号,再登录。安卓手机不会出现无法登陆成功的情况,可以直接进行后续的操作。所以确定这种问题只有在苹果手机的微信端入口有这种问题。

我们查资料的得知,安卓版微信内置的是QQ浏览器的X5内核,而苹果不允许其他浏览器内核,好像用的是苹果的内核。(但我们不确定是不是这个内核原因造成的。)微信登出后,此时会将所有的cookie信息清空。

我们通过本地的fiddler拦截请求发现,微信IOS客户端,cookie清空后,发起jsonp跨越请求,无法写入cookie,但是我们用微信浏览器访问一下B站点的主页后(这个过程会在B站点cookie中写部分cookie值),再在A站点登录后,就可以通过jsonp请求获取B站点域名下cookie中的用户登录状态了。

此时我们初步认定IOS系统的微信清空cookie后,不能直接用jsonp跨域写cookie,我们查找资料发现别人也遇到过类似的情况,但是没有很好的解决办法。

但是通过前面的测试方法,发现只要B站点域名下有cookie值(随意的cookie,只要有内容就行),我们这时候在A站点登录,然后通过jsonp请求B站点域名下的cookie值,就可以获取到用户的登录状态(cookie值完全为空则写不进去cookie值)。我们就采取了一个折中的解决办法,在页面上判断只要是IOS微信客户端访问页面,我们就让其增加一次跳转(目前只有苹果手机微信客户端有该问题),让其先访问一个和B站点域名一样的一个中间站点,随意写一些cookie值,然后再重定向到之前实际要访问的页面,这样就在A站点进行登陆后,通过jsonp请求就可以获取到B站点域名下cookie中的用户登录态了。

前端代码如下:

function GetQueryString(name)
{
     var reg = new RegExp("(^|&)"+ name +"=([^&]*)(&|$)");
     var r = window.location.search.substr(1).match(reg);
     if(r!=null)return  unescape(r[2]); return "";
}



$(function(){
    var isJump = GetQueryString("isJump");
    console.debug(isJump);
    if (typeof(isJump) == "undefined" || isJump == ""){
    //先跳一个中间站点,进行写cookie动作
        location.href="http://www.jump.B.com/testurl?infoid=" + __Global.infoid;
    }
});

后端代码如下:

@Path("/testurl")
    public ActionResult redirecturl(){
        //写入cookie
        long infoid = ParamUtil.getLong(beat.getRequest(), "infoid", 0L);
        HttpServletResponse response = beat.getResponse();
        Cookie c = new Cookie("isJump", "from");
        c.setDomain(".B.com");
        c.setPath("/");
        c.setMaxAge(20000);
        response.addCookie(c);
        //重定向
        String url = "http://A.com/detail/"+infoid+"/?isJump=1";
        System.out.println("url="+url);
        return ActionResult.redirect(url);
    }

重定向回到投递页面时,在执行jsonp请求,即可正常进行后续的流程,前端发jsonp代码如下:

 //在线报名回调函数
    function onlineApply(){
        //jsonp远程请求加密字符串
        $.ajax({
            url: 'http://www.jump.B.com/get/userid',
            type: 'get',
            dataType: 'jsonp',
            success: function(res){
                var par = {};
                var success = res.success;
                par.infoid = __Global.infoid;
                par.baseStr = res.data;
                //如果用户登录
                if(success){
                    //投递操作
                    applyHandle(par);
                }else{
                    location.href = domain+"/login?cityid="+__Global.cityid+"&cateid="+__Global.cateid+"&infoid="+__Global.infoid;
                }    
            },
            error: function(){
                $(".scheme_fail .dialog_header").html("网络错误");
                popShow(".scheme_fail");
            }
        });
    }

以上其实没有真正解决了IOS微信内置浏览器不能通过Jsonp写cookie的问题,只是用取巧的方式解决了上面出现的问题。在此写下这篇文章记录一下解决问题的方法。希望以后有别人遇到类似的问题,可以提供一点参考的思路。
如果有人解决了上面类似的问题,欢迎留言,一起探讨一下。

个人博客地址:http://www.zhaoxhit.com
公众号:技术小白猿

你可能感兴趣的:(技术类)