Ответ 1
Хороший вопрос. Даже заставлял меня немного экспериментировать.Эта строка:
AuthenticationManager.SignIn(
new AuthenticationProperties { IsPersistent = true }, identity );
Не установлен файл cookie. Только устанавливает объект Identity
для последующего обратного вызова.
Cookie устанавливается только тогда, когда элемент управления передается промежуточному программному средству и некоторому внутреннему методу OWIN под названием Response.OnSendingHeaders
.
Таким образом, ваш код просто добавляет claim2
в объект Identity
, который хранится в памяти для более позднего пользователя. В теории вы даже можете установить claim1
после выполнения AuthenticationManager.SignIn
. И все равно он будет сохранен в файле cookie.
Если вы попытаетесь добавить такой климат в контроллер:
public ActionResult AddNonPersistedClaim()
{
var identity = (ClaimsIdentity)ClaimsPrincipal.Current.Identity;
identity.AddClaim(new Claim("Hello", "World"));
return RedirectToAction("SomeAction");
}
Эта претензия не будет установлена в файле cookie, и вы не увидите ее в следующем запросе.
Если вы хотите получить более глубокий вид, как все это работает, посмотрите исходный код проекта Katana, посмотрите Microsoft.Owin.Security
и Microsoft.Owin.Security.Cookies
проекты. Наряду с AuthenticationManager
в Microsoft.Owin.Net45
проекте.
Обновление
Чтобы ответить на ваше Редактирование 1 - IdentityUserClaim
, действительно сохраняется в базе данных, и таким образом вы можете назначать пользователю постоянные претензии. Вы добавляете их пользователю через UserManager
await userManager.AddClaimAsync(userId, new Claim("ClaimType", "ClaimValue"));
Это создает записи в вашей таблице базы данных, которая представляет IdentityUserClaim. Когда в следующий раз пользователь войдет в систему, эти претензии считываются из базы данных и добавляются к идентификатору и доступны в ClaimsIdentity.Current
через свойство .Claims
или методом .HasClaim()
.
IdentityUserClaim
не делает ничего другого - просто способ сериализации объекта Claim
в базу данных. Обычно вы не обращаетесь к ним напрямую, если вы не хотите идти "голой суставы" и сами пишете на этот стол, за пределами UserManager
.
Иными словами, Identity не устанавливает cookie. OWIN создает файл cookie. Посмотрите этот фрагмент кода:
public async Task SignInAsync(IAuthenticationManager authenticationManager, ApplicationUser applicationUser, bool isPersistent)
{
authenticationManager.SignOut(
DefaultAuthenticationTypes.ExternalCookie,
DefaultAuthenticationTypes.ApplicationCookie,
DefaultAuthenticationTypes.TwoFactorCookie,
DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
DefaultAuthenticationTypes.ExternalBearer);
var identity = await this.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);
identity.AddClaim(new Claim(ClaimTypes.Email, applicationUser.Email));
authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
}
Здесь менеджер аутентификации является частью OWIN. Identity
является частью System.Security.Claims
. Все, что принадлежит проекту Identity, - это метод CreateIdentityAsync
, который в основном преобразует пользователя из базы данных в ClaimsIdentity
со всеми сохраненными ролями и претензиями.
Чтобы ответить на свое Редактирование 2: вы правы, AspNet Identity не является частью проекта Katana, но Identity использует OWIN (часть Катаны) для обработки и авторизации файлов cookie. Проект идентичности в основном касается стойкости пользователя/ролей/претензий и управления пользователями, таких как блокировка, создание пользователей, отправка писем с сбросом пароля, 2FA и т.д.
Для меня было неожиданностью, что ClaimsPrincipal вместе с ClaimsIdentity и Claim являются частью .Net-структуры, доступной вне OWIN или Identity. Они используются не только в Asp.Net, но и в приложениях Windows. Хорошо, что .Net теперь имеет открытый исходный код, и вы можете просматривать все это - дает вам лучшее представление о том, как все это работает. Кроме того, если вы выполняете модульное тестирование, неоценимо знать внутренности, поэтому вы можете отключить все функции без использования mocks.