Identity 2.0: Создание пользовательского ClaimsIdentity, например: User.Identity.GetUserById‹int›(int id) для проверки каждого запроса

См. аналогичный вопрос: Нужен доступ к дополнительным свойствам пользователя в User.Identity

Я хотел бы создать собственные методы проверки подлинности для использования с моими представлениями Razor, которые обеспечивают легкий доступ к свойствам IdentityUser, связанным с объектом User.Identity, но я не уверен, как это сделать. Я хочу создать несколько пользовательских расширений, похожих на User.Identity.GetUserName(), User.Identity.GetUserById() и т. д., вместо использования этого ViewContextExtension. Мой тип аутентификации в настоящее время является типом по умолчанию DefaultAuthenticationTypes.ApplicationCookie из шаблона VS2013 MVC5. Как заявил Shoe, мне нужно, чтобы это утверждение было вставлено после того, как пользователь войдет в систему.

Мои вопросы:

Как и где вы создаете пользовательское утверждение с параметром out this IIdentity в IPrincipal?

Это позволило бы мне получить доступ к свойствам пользователя через CookieAuthentication в представлении для сущностей в настройке DDD, где у меня есть несколько DbContexts в одном приложении с использованием Identity 2.0. Со временем я буду использовать WebAPI, но сейчас я хочу, чтобы он был максимально простым. Я нашел это SO Q&A, но он ориентирован на Интернет Формы с использованием Тикетов. Тоже не уверены в разнице между билетами и жетонами?

Это текущий подход, который использует ViewContext из базового контроллера:

Просмотр:

    @using Microsoft.AspNet.Identity
    @using Globals.Helpers
    @using Identity //custom Identity for Domain
    @using Microsoft.AspNet.Identity.Owin
    
    @if (Request.IsAuthenticated)
    {
          var url = @ViewContext.BaseController().GetAvatarUrlById(User.Identity.GetUserId<int>());
  
        //...
    }

BaseController.cs

        public string GetAvatarUrlById(int id)
        {

            var user = UserManager.FindById(id);

            return "../../" + user.ImageUrl;
        }

Extensions.cs

    public static class ViewContextExtension
    {
        public static BaseController BaseController(this ViewContext view)
        {
            var baseController = (BaseController)view.Controller;
            return baseController;
        }
    }

Я ищу, но где и как?

Просмотр:

<img src="@User.Identity.GetAvatarUrl()" alt="User.Identity.GetAvatarUrl()" />

РЕШЕНИЕ

Я просто отредактировал файл Extension.cs и использовал наследование для базового контроллера, который используется для _LoginPartial.cshtml, и отредактировал класс ViewContextExtension:

#region ViewContextExt
public static class ViewContextExtension
{
    public static BaseController BaseController(this ViewContext view)
    {
        var baseController = (BaseController)view.Controller;
        return baseController;
    }

    public static string GetAvatarUrl(this IIdentity identity)
    {
        return ((ClaimsIdentity)identity).Claims.First(c => c.Type == "AvatarUrl").Value;
    }
}

}

эндрегион


person yardpenalty.com    schedule 29.12.2014    source источник


Ответы (2)


Объект IIdentity в MVC будет выпущенным токеном, который соответствует личности пользователя. Это отличается от любого объекта или метода, который вы используете на бэкэнде, который представляет пользователя (скажем, класс User). Если вы хотите использовать удостоверение пользователя для получения пользовательского значения, вам необходимо поместить его в его объект утверждений (т. е. токен удостоверения), когда они входят в систему (или в какой-либо другой момент времени).

Вы можете добавить претензию в любое время, предоставив пользователю удостоверение.

AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim("PhoneNumber", "123-456-7890"));
AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);

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

public static string GetPhoneNumber(this IIdentity identity)
{
    return ((ClaimsIdentity)identity).FindFirstValue("PhoneNumber");
}

Бритва

@using MyProject.Web.Extensions

<img src="@User.Identity.GetPhoneNumber()" />
person James Sampica    schedule 29.12.2014
comment
Как только я получу решение с примером, я отмечу ответ :-) - person yardpenalty.com; 02.01.2015
comment
Спасибо. Shoe. На самом деле я читал PerRequest Validation до вашего ответа, так что я был почти готов. Итак, вы говорите, что если я хочу перенаправить анонимных пользователей, которые пытаются просматривать страницы, которые его ActionResult возвращает модель, использующую параметр == User.Identity.GetUserId, простого if(User.Identity.IsAuthenticated) будет недостаточно? Мне нужно проверить, что идентификатор модели равен User.Identity.GetUserId? Я понимаю, что было бы разумнее не передавать какой-либо идентификатор, когда речь идет о предотвращении анонимных пользователей, но ради аргументов. Спасибо еще раз! - person yardpenalty.com; 02.01.2015
comment
Если вы хотите перенаправить анонимных пользователей, вы должны сделать это на уровне контроллера, хотя правильно размещенный атрибут Authorize, как правило, лучше, если только это не страница, которую могут просматривать как анонимные, так и аутентифицированные пользователи. Вам не нужно сверять идентификатор модели с идентификатором, потому что они должны быть одинаковыми. Я имел в виду, что Identity пользователя (User.Identity) — это другой объект с другими свойствами, чем ваш класс User, и вы не можете просто получить свойства User, не помещая их сначала в объект Identity (через утверждения ). - person James Sampica; 02.01.2015
comment
Итак, атрибут [Authorize] на самом деле проверяет утверждение/токен, а не только пользователь находится в роли (если не указано иное). Было любопытно, потому что шаблон по умолчанию в VS2013 для MVC 5 не реализует аутентификацию. Теперь, снова взглянув на ManageController, он использует атрибут [Authorize]. Похоже, мне нужно много прочитать об Identity 2.0, чтобы создать необходимый шаблонный код как для Web API, так и для использования MVC. Еще раз спасибо за вашу помощь. - person yardpenalty.com; 02.01.2015
comment
Да, это правильно. Шаблон представляет собой небольшой загрузочный проект, но на самом деле он не предназначен для использования в качестве учебного пособия. - person James Sampica; 02.01.2015
comment
Чтобы добавить к вашему ответу Shoe, вместо использования утверждений мы можем переопределить HttpContext.User, реализовав IPrincipal вместо IIdentity, я думаю? В любом случае мы создаем эти объекты внутри контроллера, что теперь имеет смысл. Придется изучить разницу между претензиями и LukeP's подход с использованием IPrincipal. - person yardpenalty.com; 15.01.2015

Я действительно нашел решение, используя ответ на этот вопрос SO от LukeP, но, как отмечает Shoe, это pre-MVC5, и вместо этого мы могли бы просто подать претензию.

Я сделал следующие изменения:

    interface IDomainPrincipal : IPrincipal
    {
        int Id { get; set; }
        string UserName { get; set; }
        string AvatarUrl { get; set; }
    }

    public class DomainPrincipal : IDomainPrincipal
    {
        public IIdentity Identity { get; private set; }
        public bool IsInRole(string role) { return false; }

        public DomainPrincipal(string email)
        {
            this.Identity = new GenericIdentity(email);
        }

        public int Id { get; set; }
        public string UserName { get; set; }
        public string AvatarUrl { get; set; }
    }

Затем я использовал @User.Id, @User.UserName, @User.AvatarUrl в своих представлениях @Razor соответственно.

person yardpenalty.com    schedule 15.01.2015
comment
Ответ, на который вы ссылаетесь, предшествует MVC5. Ты усложняешь себе задачу. У MVC 5 уже есть претензии. Расширение IPrincipal для достижения той же цели не требуется. - person James Sampica; 15.01.2015
comment
Хорошо, спасибо Шу. Я получаю это сейчас. Я предложу свое решение, используя ваш подход. В конце концов, цель — использовать MVC5. - person yardpenalty.com; 15.01.2015