问题
我打开了 www.aaa.com 里面的一个页面(www.aaa.com/hello.php),其中这个 hello.php 里面包含一个 <img> 标签,里面的 src 来自于 www.bbb.com/get.php。
请问如果我已经在 aaa.com 里面登录了,那么访问 hello.php 时会不会把 cookie 发送给 www.bbb.com/get.php ?
实战
没有什么比实战测试更有说服力了!
新建 2 个独立的站点 A,B , 分别对应域名 aaa.com , bbb.com,其中在 A 里面制作一个登录功能,并且还有一直图片引用 bbb.com,登录后 aaa.com 会写入 cookie 到客户端,观察登录前后 bbb.com 是否能获取到 aaa.com 里面的 cookie。
1. A 站点的前台代码:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="CrossSiteCookieDemo_SiteA.WebUI.index" %> <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> </head> <body> <form id="form1" runat="server"> <div> <h1>跨域名 Cookie 传递测试</h1> </div> <br /><br /> <asp:Panel ID="pnLogin" runat="server" Visible="true"> 用户名:<asp:TextBox ID="txtUserName" runat="server"></asp:TextBox> 密码:<asp:TextBox ID="txtPassword" runat="server"></asp:TextBox> <asp:Button ID="btnLogin" runat="server" Text="登录" OnClick="btnLogin_Click"/> </asp:Panel> <asp:Panel ID="pnWelcomeInfo" runat="server" Visible="false"> 欢迎您,<asp:Literal ID="ltShowUserName" runat="server" EnableViewState="false"/> <asp:Button ID="btnLogout" runat="server" Text="注销" OnClick="btnLogout_Click" /> </asp:Panel> <br /><br /> 图片(这个图片是另一个域名下的图片): <img alt="这个图片是另一个域名下的图片" title="这个图片是另一个域名下的图片" src="http://www.bbb.com/index.ashx" /> <br /><br /> <div> <asp:Label ID="lblMessage" runat="server" EnableViewState="false"></asp:Label> </div> <br /><br /> </form> </body> </html>
2. A 站点的后台代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace CrossSiteCookieDemo_SiteA.WebUI { public partial class index : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { if(!IsPostBack) { InitData(); } } protected void InitData() { HttpCookie accountCookie = Request.Cookies["root_account_info"]; if (accountCookie != null) { this.pnWelcomeInfo.Visible = true; this.pnLogin.Visible = false; this.ltShowUserName.Text = HttpUtility.UrlDecode(accountCookie["username"]); } } protected void btnLogin_Click(object sender, EventArgs e) { string userName = this.txtUserName.Text.Trim(); string password = this.txtPassword.Text.Trim(); if (string.IsNullOrEmpty(userName)) { this.lblMessage.Text = "用户名不能为空!"; this.lblMessage.ForeColor = System.Drawing.Color.Red; return; } if (string.IsNullOrEmpty(password)) { this.lblMessage.Text = "密码不能为空!"; this.lblMessage.ForeColor = System.Drawing.Color.Red; return; } HttpCookie accountCookie = new HttpCookie("root_account_info"); accountCookie.Expires = DateTime.Now.AddDays(1d); accountCookie["username"] = HttpUtility.UrlEncode(userName); // 仅仅为了测试,省略了加密 accountCookie["password"] = HttpUtility.UrlEncode(password); // 仅仅为了测试,省略了加密 Response.AppendCookie(accountCookie); HttpCookie loginStatCookie = Request.Cookies["root_login_stat_info"]; if (loginStatCookie == null) { loginStatCookie = new HttpCookie("root_login_stat_info"); loginStatCookie.Expires = DateTime.Now.AddYears(100); loginStatCookie["firstLoginTime"] = HttpUtility.UrlEncode(DateTime.Now.ToString("yyyyMMddHHmmss")); // 仅仅为了测试,省略了加密 loginStatCookie["LoginCount"] = "1"; } else { string loginCountStr = loginStatCookie["LoginCount"]; int loginCount; int.TryParse(loginCountStr, out loginCount); loginCount++; loginStatCookie["LoginCount"] = loginCount.ToString(); } loginStatCookie["lastLoginTime"] = HttpUtility.UrlEncode(DateTime.Now.ToString("yyyyMMddHHmmss")); // 仅仅为了测试,省略了加密 Response.AppendCookie(loginStatCookie); this.pnWelcomeInfo.Visible = true; this.pnLogin.Visible = false; this.ltShowUserName.Text = userName; } protected void btnLogout_Click(object sender, EventArgs e) { HttpCookie accountCookie = Request.Cookies["root_account_info"]; if (accountCookie != null) { accountCookie.Expires = DateTime.Now.AddYears(-10); Response.AppendCookie(accountCookie); } this.pnWelcomeInfo.Visible = false; this.pnLogin.Visible = true; this.ltShowUserName.Text = string.Empty; } } }
3. B 站点的处理程序代码:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Text; namespace CrossSiteCookieDemo_SiteB.WebUI { /// <summary> /// index 的摘要说明 /// </summary> public class index : IHttpHandler { public void ProcessRequest(HttpContext context) { string cookieContent = new string('=', 25) + "时间:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + new string('=', 25) + " "; StringBuilder sbAppend = new StringBuilder(); foreach (HttpCookie cookieItem in context.Request.Cookies) { sbAppend.Append("cookieName: " + cookieItem.Name + " "); sbAppend.Append("cookieValue: "); if(cookieItem.Values != null && cookieItem.Values.AllKeys != null && cookieItem.Values.AllKeys.Length > 0) { foreach (string childCookieKey in cookieItem.Values.AllKeys) { sbAppend.AppendFormat(new string(' ', 4) + "{0}: {1} ", childCookieKey, cookieItem.Values[childCookieKey]); } } } cookieContent += sbAppend.ToString(); System.IO.File.AppendAllText(System.Web.Hosting.HostingEnvironment.MapPath("~/log/cookie.log"), cookieContent, System.Text.Encoding.UTF8); context.Response.ContentType = "image/jpeg"; context.Response.TransmitFile(System.Web.Hosting.HostingEnvironment.MapPath("~/images/01.jpg")); } public bool IsReusable { get { return false; } } } }
4. 运行截图:
01
02
03
04
05
结论:跨域 Cookie 是无法传递的,浏览器会阻止!
谢谢浏览!