ASP.NET MVC单点登录和角色

我使用基于以下方法的内容在2个MVC站点(称为SiteA和SiteB)上进行基本单点登录:

http://forums.asp.net/p/1023838/2614630.aspx

它们位于同一域的子域中,并在web.config中共享hash \ encryption键等。 我已经修改了cookie,因此可以访问同一域中的所有站点。 所有这一切似乎都运作正常。

这些站点位于不同的服务器上,无法访问同一个SQL数据库,因此只有SiteA实际上拥有用户登录详细信息。 SiteB有一个成员资格数据库,但用户空白。

这适用于我所需的场景,即:

1)用户登录SiteA

2)应用程序从SiteA(通过AJAX)和SiteB(通过AJAX使用JSONP)加载数据

我在SiteA的AccountController上有以下LogOn Action,这是“魔术”发生的地方:

[HttpPost] public ActionResult LogOn(LogOnModel model, string returnUrl) { if (ModelState.IsValid) { if (MembershipService.ValidateUser(model.UserName, model.Password)) { FormsService.SignIn(model.UserName, model.RememberMe); //modify the Domain attribute of the cookie to the second level of domain // Add roles string[] roles = Roles.GetRolesForUser(model.UserName); HttpCookie cookie = FormsAuthentication.GetAuthCookie(User.Identity.Name, false); FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(cookie.Value); // Store roles inside the Forms cookie. FormsAuthenticationTicket newticket = new FormsAuthenticationTicket(ticket.Version, model.UserName, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, String.Join("|", roles), ticket.CookiePath); cookie.Value = FormsAuthentication.Encrypt(newticket); cookie.HttpOnly = false; cookie.Domain = ConfigurationManager.AppSettings["Level2DomainName"]; Response.Cookies.Remove(cookie.Name); Response.AppendCookie(cookie); if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "The user name or password provided is incorrect."); } } 

这做了一些我最初的场景并不严格需要的东西,但与我的问题有关。 它将登录到SiteA的用户的角色列表插入到身份validation票证的UserData中。 然后通过global.asax中的以下内容在SiteB上“恢复”:

 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); } } 

上面的所有内容都有效,直到我将Roles添加到组合中。 如果我只使用[Authorize]属性修饰SiteB上的Controllers \ Actions,那么事情就可以了。 但是只要我添加[Authorize(roles =“TestAdmin”)],用户就无法再访问该控制器操作。 显然,我已将用户添加到TestAdmin角色。

如果我调试SiteB上的global.asax代码,它看起来没问题,因为我留下了global.asax代码,但是当我在控制器本身中遇到断点时,Controller.User和Controller.HttpContext.User现在是一个系统。 Web.Security.RolePrincipal不再设置角色。

所以我的问题是:有没有人知道如何恢复SiteB上的角色或其他方式来做到这一点?

你已经解决了,但我们走了:

让它工作:关闭角色管理器。 这不是asp.net正在做的奇怪行为,因为你明确告诉它使用指定的配置来查找用户的角色。

另一种方法:在两者中启用角色管理器。 使用配置可以像在自定义代码中一样共享cookie。 根据您的描述,您不必担心尝试为用户获取角色,只要您使用匹配的身份validationcookie配置即可

你应该使用Application_AuthorizeRequest来设置角色cookie吗? imho早期的观点(Authenticate)是最好的,我总是这样做,从不遇到问题。

由于这似乎停滞不前,我可以用一些额外的发现来部分回答这个问题。 经过调试\测试这一点后,似乎MVC2在离开Application_AuthenticateRequest之后但在进入我的Controller之前做了一些奇怪的事情。 更多细节在这里:

http://forums.asp.net/t/1597075.aspx

解决方法是使用Application_AuthorizeRequest而不是Application_AuthenticateRequest。

编辑:我相信我找到了问题的原因。 在我的MVC1项目中,我禁用了roleManager,但我的测试MVC2项目启用了roleManager。 一旦我在MVC1测试项目中启用了我的roleManager,MVC1和MVC2之间的行为是相同的。 我还向一个MVC微软团队提出了一个问题,如果Application_AuthorizeRequest是从身份validation票证cookie中恢复角色的正确位置,那么将在此处回复…