代码之家  ›  专栏  ›  技术社区  ›  mutex

ASP.NET跨子域单点登录Cookie

  •  2
  • mutex  · 技术社区  · 15 年前

    我有一个单点登录解决方案,它在我们的测试环境中工作得很好。它使用跨子域cookies在两个web应用程序之间共享身份验证票证。登录仅在其中一个应用程序上完成,在第二个站点上,用户通过第一个站点创建的cookie进行身份验证。

    问题是,当我将其滚动到生产环境中时,单点登录不再工作。我想知道为什么会这样。更多详情如下:

    1) 两个应用程序都是使用ASP.NET MVC2实现的

    3) 两个站点都有SSL设置并通过https进行访问;这是在测试和生产中使用相同的自签名通配符证书完成的。

    4) 用户登录到site1,然后应用程序使用AJAX和JSONP自动从site2检索数据。

    ...
    <authentication mode="Forms">
      <forms name=".myapp" domain=".example.com" slidingExpiration="true" loginUrl="~/Account/LogOn" timeout="30"/>
    </authentication>
    ...
    <machineKey validationKey="KEY1..." decryptionKey="KEY2..."
      validation="SHA1" decryption="AES" />
    ...
    

    注意:我想知道的一件事是,身份验证票证是否以只能在同一服务器上解密的方式进行加密/散列?这可以解释我的问题;但如果是这种情况,我如何确保site1和site2的服务器都可以解密我的身份验证cookie?KEY1和KEY2在这两个站点/服务器上绝对相同。

    public ActionResult LogOn(string userName, string password, bool rememberMe, string returnUrl)
        {
            if (!ValidateLogOn(userName, password))
            {
                ViewData["rememberMe"] = rememberMe;
                return View(new SiteViewModel(this));
            }
    
            FormsAuth.SignIn(userName, rememberMe);
    
            // Add roles to cookie
            string[] roles = Roles.GetRolesForUser(userName);
            HttpCookie cookie = FormsAuthentication.GetAuthCookie(User.Identity.Name, rememberMe);
            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value);
            // Store roles inside the Forms cookie.  
            FormsAuthenticationTicket newticket = new FormsAuthenticationTicket(ticket.Version, userName,
                ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, String.Join("|", roles), ticket.CookiePath);
            cookie.Value = FormsAuthentication.Encrypt(newticket);
            cookie.HttpOnly = false;
            Response.Cookies.Remove(cookie.Name);
            Response.AppendCookie(cookie);
    
            if (!String.IsNullOrEmpty(returnUrl))
            {
                return Redirect(returnUrl);
            }
            return RedirectToAction("Index", "Home");
        }
    

    7) 使用以下命令在站点2上还原角色:

            protected void Application_AuthenticateRequest(Object sender, EventArgs e)
        {
            if (Context.Request.IsAuthenticated)
            {
                FormsIdentity ident = (FormsIdentity)Context.User.Identity;
                string[] arrRoles = ident.Ticket.UserData.Split(new[] { '|' });
                Context.User = new System.Security.Principal.GenericPrincipal(ident, arrRoles);
            }
        }
    

    8) 这是两台服务器上的应用程序引用的程序集的打印输出:

            mscorlib: 2.0.0.0
        System: 2.0.0.0
            System.Configuration: 2.0.0.0
                System.Xml: 2.0.0.0
        System.ComponentModel.DataAnnotations: 3.5.0.0
            System.Core: 3.5.0.0
        System.Data: 2.0.0.0
            System.EnterpriseServices: 2.0.0.0
                System.Transactions: 2.0.0.0
        System.Data.Entity: 3.5.0.0
            System.Runtime.Serialization: 3.0.0.0
                SMDiagnostics: 3.0.0.0
        System.Web: 2.0.0.0
            System.Drawing: 2.0.0.0
            System.Web.RegularExpressions: 2.0.0.0
            System.Web.Services: 2.0.0.0
        System.Web.Abstractions: 3.5.0.0
        System.Web.Extensions: 3.5.0.0
            System.Data.Linq: 3.5.0.0
                System.Xml.Linq: 3.5.0.0
            System.ServiceModel: 3.0.0.0
                System.IdentityModel: 3.0.0.0
            System.ServiceModel.Web: 3.5.0.0
        System.Web.Mvc: 1.0.0.0
            System.Web.Routing: 3.5.0.0
        xVal: 1.0.0.0
    
    1 回复  |  直到 15 年前
        1
  •  4
  •   ntziolis    15 年前

    对。加密是特定于服务器的。或者更精确地说依赖于 一模一样。

    1. 尝试使用 两个web配置中的相同计算机密钥 .
    2. 如果那有帮助的话。 删除加密 如果有用就试试

    如果在完全删除安全性/加密之后它无法工作,则它与不兼容的加密无关。告诉我们。

    更新 这是从我们的web.config中提取的。当然是在删除网站细节之后。尝试明确地指定所有内容,特别是 :

    <forms name=".ASPNET" protection="All" loginUrl="~/Account/LogOn" timeout="2880"
            path="/" domain=".example.com"/>