ASP.NET MVC Single Sign-on и роли

У меня есть базовая единая регистрация, работающая на 2 сайтах MVC (назовите их SiteA и SiteB), используя что-то вроде следующего метода:

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

Они находятся на поддоменах одного и того же домена и совместно используют ключи хэширования / шифрования и т. Д. В файле web.config. Я изменил файл cookie, чтобы он был доступен для всех сайтов в одном домене. Все это работает нормально.

Сайты находятся на отдельных серверах без доступа к одной и той же базе данных SQL, поэтому только SiteA фактически содержит данные для входа пользователя. SiteB имеет членскую базу данных, но с пустыми пользователями.

Это прекрасно работает для моего необходимого сценария, который:

1) Пользователь заходит на сайт А

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 теперь являются Системой.Web.Security.RolePrincipal без установленных ролей.

Итак, мой вопрос: кто-нибудь знает, как я могу восстановить роли на SiteB или каким-либо другим способом сделать это?

2 ответа

Решение

Вы уже решили это, но здесь мы идем:

заставить это работать: выключите менеджер ролей. Это не странное поведение, которое делает asp.net, так как вы явно указываете ему использовать поиск ролей пользователя с указанной конфигурацией.

Другой способ сделать это: включить диспетчер ролей в обоих. Используйте конфигурацию, чтобы поделиться куки, как вы делаете в своем пользовательском коде. Основываясь на вашем описании, вам не нужно беспокоиться о том, что он пытается получить роли для пользователя, если вы используете соответствующую конфигурацию для файла cookie аутентификации.

Вы должны использовать Application_AuthorizeRequest, чтобы установить файлы cookie ролей? мнение imho ранее (Authenticate) лучше, я всегда так делал и никогда не сталкивался с проблемами.

Поскольку это, похоже, застоялось, я могу частично ответить на этот вопрос с некоторыми дополнительными выводами. После отладки \ тестирования немного больше, кажется, что MVC2 делает что-то странное после выхода из Application_AuthenticateRequest, но до входа в мой контроллер. Подробнее здесь:

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

Обходной путь должен использовать Application_AuthorizeRequest вместо Application_AuthenticateRequest.

РЕДАКТИРОВАТЬ: Я считаю, что я нашел причину своих проблем. В моем проекте MVC1 у меня был отключен roleManager, но в моем тестовом проекте MVC2 был включен roleManager. После включения моего roleManager в тестовом проекте MVC1 поведение между MVC1 и MVC2 остается прежним. У меня также есть вопрос к одной из открытых команд Microsoft MVC по этому поводу, и я вернусь сюда, если Application_AuthorizeRequest - это правильное место для восстановления файла cookie с запросом ролей из проверки подлинности...

Другие вопросы по тегам