У меня есть базовая единая регистрация, работающая через 2 MVC сайты (назовите их SiteA и SiteB), используя что-то вроде следующего метода:
http://forums.asp.net/p/1023838/2614630.aspx
Они находятся на поддоменах одного и того же доменный и общий хэш \ ключи шифрования и т. д. в web.config. Я изменил файл cookie, чтобы он был доступен для всех сайтов в одном домене. Кажется, что все это работает нормально.
Сайты находятся на отдельных серверах без доступа к одной и той же базе данных SQL, поэтому только SiteA фактически содержит данные для входа пользователя. SiteB имеет базу данных о членстве, но с пустыми пользователями.
Это прекрасно работает для моего необходимого сценария:
1) Пользователь входит в SiteA
2) Приложение загружает данные из SiteA (от AJAX) и SiteB (от AJAX с использованием JSONP)
У меня есть следующее действие LogOn на моем AccountController для SiteA, где происходит «волшебство»:
[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 в UserData билета аутентификации. Затем это «восстанавливается» на SiteB с помощью следующего в global.asax:
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);
}
}
Все вышеперечисленное работает, пока я не добавлю роли в микс. Все работает хорошо, если я только украшаю свои Controllers \ Actions на SiteB атрибутами [Authorize]. Но как только я добавлю [Authorize (role = "TestAdmin")], пользователи больше не смогут получить доступ к этому действию контроллера. Очевидно, что я добавил пользователя в роль TestAdmin.
Если я отлаживаю код global.asax на SiteB, он выглядит нормально, когда я оставляю код global.asax, НО затем, когда я достигаю точки останова в самом контроллере, Controller.User и Controller.HttpContext.User теперь являются System.Web.Security.RolePrincipal без установленных ролей.
Итак, мой вопрос: Кто-нибудь знает, как я могу восстановить роли на SiteB или другим способом сделать это?
Поскольку это, похоже, застопорилось, я могу частично ответить на этот вопрос некоторыми дополнительными выводами. После отладки\тестирования этого немного больше, кажется, что MVC2 делает что-то странное после выхода из Application_AuthenticateRequest, но до входа в мой контроллер. Подробности здесь:
http://forums.asp.net/t/1597075.aspx
Обходной путь — использовать Application_AuthorizeRequest вместо Application_AuthenticateRequest.
РЕДАКТИРОВАТЬ: Я считаю, что нашел причину своих проблем. В моем проекте MVC1 у меня был отключен roleManager, но в моем тестовом проекте MVC2 был включен roleManager. Как только я включил свой roleManager в тестовом проекте MVC1, поведение между MVC1 и MVC2 было таким же. У меня также есть вопрос к одной из открытых команд MVC Microsoft по этому поводу, и я сообщу здесь, если Application_AuthorizeRequest является правильным местом для восстановления ролей из файла cookie билета аутентификации...