2010-10-28 99 views
2

我有一个单点登录解决方案,它在我们的测试环境中工作得很好。它使用跨子域cookie在2个Web应用程序之间共享身份验证票据。仅在其中一个应用程序上进行登录,而在第二个站点上,用户通过由第一个站点创建的Cookie进行身份验证。ASP.NET跨子域单点登录Cookies

问题是,当我将其转移到生产环境中时,单一登录不再起作用。我正在寻找关于为什么这可能是任何想法。详细信息如下:

1)这两个应用程序使用ASP.NET MVC2

2)在我们的测试环境这两个网站都坐在一台服务器上实现,以用于服务于在IIS不同的网站和主机头2个Web应用程序。在生产中,这些站点位于不同的地理位置上分开的服务器上。不过,他们使用相同的子域。

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

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

5)如果网站是site1.example.com和site2.example.com,以下是web.config中的1和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都是完全相同的。

6)在站点1的用户在角色使用也插入cookie中的以下内容:

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 

回答

4

是的。加密是服务器特定的。或者更精确地依赖于机器密钥是相同的。

  1. 尝试和使用相同的机器密钥在两个网页配置
  2. 如果该dosent帮助。 删除加密和尝试,如果作品则

如果不删除安全/加密工作后,完全有不兼容的加密没什么待办事项。让我们知道。

UPDATE 这是从我们的web.config中提取的。当然,删除网站的细节。尽量明确指定的一切,尤其是路径

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

如何使用同一台机器的关键?在我上面的示例web.config中,validationKey和decryptionKey是明确设置的,并且在两台服务器上都是相同的。我需要在另一个地方设置另一个关键位置还是这些关键位置? – mutex 2010-10-28 20:49:04

+0

没有那个人,只是我没有仔细观察。您是否尝试删除身份验证过程的所有加密? – ntziolis 2010-10-28 21:04:59

+0

是的,删除了所有的加密和东西的工作!非常困惑,为什么当密钥相同时它不能与加密一起工作。它是否将某种特定于服务器的信息添加到组合中? – mutex 2010-10-28 21:17:21