开发者社区> 问答> 正文

cookie跨域的问题!

原来登录自家页面,cookie什么的问题,也没关心过它工作细节,现在多出来个网站,要在这个网站也登录我站的号,用ajax跨域登录,能登录成功,但cookie传递有问题了,我站后端无法靠cookie辨认身份了,不知道怎么办

展开
收起
小旋风柴进 2016-03-09 09:50:31 3774 0
1 条回答
写回答
取消 提交回答
  • Cookie是一个伟大的发明,它允许Web开发者保留他们的用户的登录状态。但是当你的站点有一个以上的域名时就会出现问题了。在Cookie规范上说,一个cookie只能用于一个域名,不能够发给其它的域名。因此,如果在浏览器中对一个域名设置了一个cookie,这个cookie对于其它的域名将无效。如果你想让你的用户从你的站点中的其中一个进行登录,同时也可以在其它域名上进行登录,这可真是一个大难题。
    跨二级域名

     我们知道cookie是可以跨二级域名来访问,这个很好理解,例如你 www.test1.com 在的web应用程序创建了一个cookie,要想在bbs.test1.com这样的二级域名对应的应用程序中访问,就必须你在创建cookie的时候设置domain参数domain=test1.com。 以asp.net为例 代码如下:
    [csharp] view plaincopy 
    HttpCookie cookie = new HttpCookie("name", "www.Admin10000.com");  
    cookie.Domain = "test1.com";  
    cookie.Path = "/";  
    Response.Cookies.Add(cookie);  

    跨顶级域名

      如果我不是二级域名而是完全在不同顶级域名中,例如 www.test1.com 所在的web应用程序创建了一个cookie,想要在 www.test2.com 或其二级域名的应用程序中访问,改怎么办呢?我们知道靠常规反的方法是访问不了的,关键我们就是看看有没有方法可以访问。事实是Cookie可以在一定条件下跨域,而不是随心所欲的实现跨域。

      我们来做个测试,看看两个站点 www.test1.com 和 www.test2.com 如何实现cookie跨域访问。 按照常规我们需要有2个顶级域名,并且有DNS服务器才能够配置域名,否则我们是无法验证的,但是这里我们也没有必要那么麻烦,我们可以通过修改hosts文件来模拟。在 c:windowssystem32driversetc 中有 hosts文件,在末尾添加上

    127.0.0.1 www.test1.com
    127.0.0.1 www.test2.com
    两行,就可以将本机用上面的域名访问本机回环地址了。我们只需要在IIS上部署一套程序,ip为本机回环地址,用两个域名分别访问就可以了。

      我们新建三个页面,分别是 Default.aspx、SSO.ashx、GetCookie.aspx。

      其中Default.aspx是 www.test1.com 的页面,访问的地址是 http://www.test1.com/Default.aspx。看一下前台代码,它没有任何后台代码

    [html] view plaincopy 
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Admin10000.Web.Default" %>  
       
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
    <html xmlns="http://www.w3.org/1999/xhtml">  
    <head runat="server">  
        <title></title>  
    </head>  
    <body>  
        <form id="form1" runat="server">  
        <div>  
       
            <script type="text/javascript">  
                var _frm = document.createElement("iframe");  
                _frm.style.display = "none";  
                _frm.src = "http://www.test2.com/SSO.ashx";  
                document.body.appendChild(_frm);     
            </script>  
       
        </div>  
        </form>  
    </body>  
    </html>  

    另外一个是 SSO.ashx 页面,我们认为它是 www.test2.com 的页面,前台没有任何代码,后台代码如下:

    [csharp] view plaincopy 
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.Services;  
    using System.Web.SessionState;  
       
    namespace Admin10000.Web  
    {  
        /// <summary>  
        /// $codebehindclassname$ 的摘要说明  
        /// </summary>  
        [WebService(Namespace = "http://tempuri.org/")]  
        [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]  
        public class SSO : IHttpHandler  
        {  
       
            public void ProcessRequest(HttpContext context)  
            {  
                HttpCookie cookie = new HttpCookie("name", "www.Admin10000.com");  
                cookie.Domain = "test2.com";  
                cookie.Path = "/";  
                cookie.Expires = DateTime.Now.AddMinutes(10000);  
                context.Response.Cookies.Add(cookie);  
       
                context.Response.ContentType = "text/plain";  
                context.Response.AddHeader("P3P", "CP=CAO PSA OUR");  
                context.Response.Write("");  
            }  
       
            public bool IsReusable  
            {  
                get  
                {  
                    return false;  
                }  
            }  
        }  
    }  

    最后是 GetCookie.aspx 页面,它同样是www.test2.com下的页面,没有前台代码,只有后台代码:

    [csharp] view plaincopy 
    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Web;  
    using System.Web.UI;  
    using System.Web.UI.WebControls;  
       
    namespace Admin10000.Web  
    {  
        public partial class GetCookie : System.Web.UI.Page  
        {  
            protected void Page_Load(object sender, EventArgs e)  
            {  
                if (Request.Cookies["name"] != null)  
                {  
                    Response.Write(Request.Cookies["name"].Value);  
                }  
            }  
        }  
    }  

    好了,现在我们访问测试,通过访问 ttp://www.test1.com/Default.aspx 之后,这时会通过iframe载入调用SSO.ashx这个页面,执行后台代码创建cookie,然后访问 http://www.test2.com/GetCookie.aspx 我们得到了相应的cookie。说明在www.test1.com下创建的cookie在www.test2.com下是可以访问到的。

    要注意的地方:

      admin10000.com 提示 SSO.ashx 的后台代码中有一句:context.Response.AddHeader("P3P", "CP=CAO PSA OUR"); 是用来设置P3P响应头。是因为IE浏览器支持的P3P导致iframe跨站点时cookie被阻止,无法创建cookie。(FireFox目前还不支持P3P安全特性,FireFox自然也不存在此问题。不需要添加P3P响应头。)

      通过iframe的src属性将test1.com域下的cookie值作为get参数重定向到test2.com域下SSO.ashx页面上,SSO.ashx获取test1.com域中所传过来的cookie值,并将所获取到值写入cookie中,这样就简单的实现了cookie跨域的访问。

      另外Default.aspx页面也可改为JS调用形式:

    [html] view plaincopy 
    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Admin10000.Web.Default" %>  
       
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
       
    <html xmlns="http://www.w3.org/1999/xhtml" >  
    <head runat="server">  
        <title></title>  
    </head>  
    <body>  
        <form id="form1" runat="server">  
        <div>  
            <script type="text/javascript" src="http://www.test2.com/SSO.ashx"></script>  
        </div>  
        </form>  
    </body>  
    </html>  
    2019-07-17 18:55:25
    赞同 展开评论 打赏
问答分类:
问答标签:
问答地址:
问答排行榜
最热
最新

相关电子书

更多
低代码开发师(初级)实战教程 立即下载
冬季实战营第三期:MySQL数据库进阶实战 立即下载
阿里巴巴DevOps 最佳实践手册 立即下载