Forms身份认证在IE11下无法保存Cookie的问题

ASP.NET中使用Forms身份认证常见的做法如下:

1. 网站根目录下的Web.config添加authentication节点
复制代码 代码如下:
authentication mode="Forms"
forms name="MyAuth" loginUrl="manager/Login.aspx" defaultUrl="manager/default.aspx" protection="All" timeout="60" /
/authentication

2. 在manager子目录下添加Web.config文件并加入下面的内容:
复制代码 代码如下:
?xml version="1.0"?
configuration
system.web
authorization
allow roles="Admin" /
deny users="*" /
/authorization
/system.web
/configuration

这样 , 用户在没有Forms认证的情况下访问manager子目录下的任何页面均会自动跳转到manager/Login.aspx页面 。如果认证成功 , 则会默认回到manager/default.aspx页面 。认证有效期为60分钟 。

3. 添加认证代码 。登录按钮中添加下面的代码:
复制代码 代码如下:
if (!snCheckCode.CheckSN(txt_ValidateCode.Text))
{
snCheckCode.Create();
Utility.ShowMessage("校验码错误!");
return;
}

string strUserName = txt_Username.Text.Trim();
string md5Pwd = Helper.MD5ForPHP(Helper.MD5ForPHP(txt_Password.Text));
lc_admin admin = null;
bool logined = false;

using (var context = new dbEntities())
{
admin = context.tb_admin.Where(n = n.username == strUserName).FirstOrDefault();

if (admin != null)
{
if (admin.checkadmin != "true")
{
snCheckCode.Create();
Utility.ShowMessage("抱歉 , 该账号被禁止登录!");
return;
}

if (admin.password == md5Pwd)
{
// Update Admin Info
admin.loginip = Request.UserHostAddress.ToString();
admin.logintime = CndingUtility.DateTimeToUnixTimeStamp(DateTime.Now);
context.SaveChanges();

logined = true;
}
}
}

if (logined)
{
// Login
FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
1,
admin.id.ToString(),
DateTime.Now,
DateTime.Now.AddMinutes(60),
false,
"Admin",
FormsAuthentication.FormsCookiePath
);
string hashTicket = FormsAuthentication.Encrypt(ticket);
HttpCookie userCookie = new HttpCookie(FormsAuthentication.FormsCookieName, hashTicket);
HttpContext.Current.Response.Cookies.Add(userCookie);

if (Request["ReturnUrl"] != null)
{
Response.Redirect(HttpUtility.HtmlDecode(Request["ReturnUrl"]));
}
else
{
Response.Redirect("/manager/default.aspx");
}
}
else
{
snCheckCode.Create();
CndingUtility.ShowMessage("用户名或密码不正确!");
}

MD5加密代码:
复制代码 代码如下:
public static string MD5ForPHP(string stringToHash)
{
var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] emailBytes = Encoding.UTF8.GetBytes(stringToHash.ToLower());
byte[] hashedEmailBytes = md5.ComputeHash(emailBytes);
StringBuilder sb = new StringBuilder();
foreach (var b in hashedEmailBytes)
{
sb.Append(b.ToString("x2").ToLower());
}
return sb.ToString();
}

认证成功后默认会将用户登录信息以Cookie的形式存放到客户端 , 有效期为60分钟 。UserData被设置为用户的角色 , 在判断用户是否登录时会用到 。如下面的代码:
复制代码 代码如下:
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
int adminId = -1;
FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;
FormsAuthenticationTicket ticket = identity.Ticket;
string userData = https://www.rkxy.com.cn/dnjc/ticket.UserData;
if (userData =https://www.rkxy.com.cn/dnjc/="Admin")
{
// To do something
}
}

上述代码在Visual Studio中运行一切正常!但是将网站发布到服务器的IIS (可能会是较低版本的IIS , 如IIS 6)后 , 发现登录功能异常 。输入用户名和密码后点击登录按钮 , 页面postback但并不能正确跳转 , 尝试手动访问受保护的页面会被自动跳转回登录页面 。更奇怪的是该问题只出现在IE11浏览器上 , 尝试用Firefox或Chrome访问登录功能运行正常 。初步怀疑是IIS设置的问题 , 可是IIS 6上并没有与Cookie相关的设置 , 好像记得IIS 7上倒是有这个设置 。但因为只有IE 11存在该问题 , 所以可以否定代码本身存在任何问题 。

推荐阅读