Как связать роль с пользователем в MVC 5?

В WebForms я хранил роль в пользовательских данных FormsAuthenticationTicket, однако я попытался реализовать тот же метод в mvc 5, и это не сработало. По какой-то причине

User.Identity.IsAuthenticated

это возвращает ложь

var ticket = new FormsAuthenticationTicket(
    1,
    user.Id.ToString(),
    DateTime.Now,
    DateTime.Now.AddDays(5),
    model.RememberMe,
    user.Roles.Select(c => c.Nome).FirstOrDefault(),
    FormsAuthentication.FormsCookiePath
);

// Encrypt the ticket.
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
// Create the cookie.
HttpCookie authenticationCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket); // Name of auth cookie (it's the name specified in web.config) // Hashed ticket
authenticationCookie.Expires = DateTime.Now.AddDays(7);
// Add the cookie to the list for outbound response
Response.Cookies.Add(authenticationCookie);

так как это не работает, я использовал вместо этого

FormsAuthentication.SetAuthCookie(user.Id.ToString(), model.RememberMe);

проблема в том, что это не позволяет мне иметь легкий доступ к роли пользователя, чтобы я мог делать это в представлении

if (User.IsInRole("Admin"))

Я пытаюсь избежать Asp Net Identity, потому что он требует много настроек, и мне не нужны ни все дополнительные поля, ни пароль, потому что мы аутентифицируемся с помощью ldap.

Если есть другой вариант, посоветуйте.


person Jackal    schedule 10.04.2019    source источник
comment
Пожалуйста, поделитесь кодом Application_AuthenticateRequest в своем проекте или там, где вы установили Context.User из файла cookie авторизации.   -  person Alexander    schedule 10.04.2019
comment
У меня еще не реализована эта функция, потому что я думал, что она не нужна только для аутентификации пользователя.   -  person Jackal    schedule 10.04.2019


Ответы (1)


Проверка подлинности с помощью форм сама по себе не поддерживает роли. Поэтому вам нужно установить IPrincipal запроса с ролями вручную. Вы можете сделать это, «подписавшись» на событие аутентификации публикации в Global.asax и обновив зарегистрированную информацию о пользователе. Добавьте следующий метод внутри класса MvcApplication в Global.asax.cs

protected void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

    if (authCookie != null)
    {
        //get the forms authentication ticket
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        string userData = authTicket.UserData;
        //here we suppose userData contains roles joined with ","
        string[] roles = userData.Split(',');

        //at this point we already have Context.User set by forms authentication module
        //we don't change it but add roles
        var principal = new GenericPrincipal(Context.User.Identity, roles);

        // set new principal with roles
        Context.User = principal;
    }
}

Также вам необходимо обновить код входа в систему, чтобы создать правильные FormsAuthenticationTicket, содержащие роли, соединенные с помощью ","

var roles = user.Roles.Select(c => c.Nome);
var ticket = new FormsAuthenticationTicket(
    1,
    user.Id.ToString(),
    DateTime.Now,
    DateTime.Now.AddDays(5),
    model.RememberMe,
    string.Join(",", roles), //or you can serialize complex class as json or whatever
    FormsAuthentication.FormsCookiePath
);

Другой вариант — переопределить аутентификацию с помощью форм, добавив метод FormsAuthentication_OnAuthenticate в Global.asax.cs

public void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs args)
{
    if (FormsAuthentication.CookiesSupported)
    {
        HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            try
            {
                //get the forms authentication ticket
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
                string userData = authTicket.UserData;
                //here we suppose userData contains roles joined with ","
                string[] roles = userData.Split(',');

                //we have to create identity since it's not created yet
                var identity = new FormsIdentity(authTicket);
                var principal = new GenericPrincipal(identity, roles);

                args.User = principal;
            }
            catch (Exception e)
            {
                // Decrypt method failed.
            }
        }
    }
    else
    {
        throw new HttpException("Cookieless Forms Authentication is not " +
                                "supported for this application.");
    }
}

Оба решения очень похожи, поэтому вам решать, какое из них выбрать.

person Alexander    schedule 10.04.2019