MVC 5 Доступ до претензій на особисті дані користувача


119

Я розробляю веб-додаток MVC 5, використовуючи перший підхід до бази даних Entity Framework 5 . Я використовую OWIN для автентифікації користувачів. Нижче показаний метод мого входу в контролер акаунта.

public ActionResult Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var user = _AccountService.VerifyPassword(model.UserName, model.Password, false);
        if (user != null)
        {
            var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, model.UserName), }, DefaultAuthenticationTypes.ApplicationCookie, ClaimTypes.Name, ClaimTypes.Role);

            identity.AddClaim(new Claim(ClaimTypes.Role, "guest"));
            identity.AddClaim(new Claim(ClaimTypes.GivenName, "A Person"));
            identity.AddClaim(new Claim(ClaimTypes.Sid, user.userID)); //OK to store userID here?

            AuthenticationManager.SignIn(new AuthenticationProperties
            {
                IsPersistent = model.RememberMe
            }, identity);

            return RedirectToAction("Index", "MyDashboard");
        }
        else
        {
            ModelState.AddModelError("", "Invalid username or password.");
        }
    }
    // If we got this far, something failed, redisplay form
    return View(model);
}

Як ви бачите, я створюю ClaimsIdentity і додаю до нього кілька претензій, а потім передаю його OWIN, використовуючи AuthenticationManager для виконання входу.

Проблема, яка у мене виникає, полягає в тому, що я не знаю, як отримати доступ до претензій в решті моєї програми, як у контролерах, так і в представленнях Razor Views.

Я спробував підхід, перелічений у цьому підручнику

http://brockallen.com/2013/10/24/a-primer-on-owin-cookie-authentication-middleware-for-the-asp-net-developer/

Наприклад, я спробував це у своєму коді контролера, намагаючись отримати доступ до значень, переданих у формулу заявки, однак, користувач. Претензії дорівнює нулю

var ctx = HttpContext.GetOwinContext();
ClaimsPrincipal user = ctx.Authentication.User;
IEnumerable<Claim> claims = user.Claims;

Можливо, мені щось тут не вистачає.

ОНОВЛЕННЯ

На основі відповіді Даріна я додав його код, але все ще не бачу доступу до претензій. Перегляньте знімок екрана нижче, де відображається те, що я бачу, коли наближається над особистістю.

введіть тут опис зображення


Чи можете ви підтвердити, що cookie повертається браузером? Можливо, ваші налаштування безпеки вимагають SSL?
найменшепривілей

@leastprivilege Спасибі, я зараз перегляну це питання. Я знайшов це питання на Stackoverflow, stackoverflow.com/questions/20319118 / ... це та ж сама проблема , яку я маю, але , до жаль , немає відповіді на нього :(
TCode

Як ініціалізуються ваші компоненти OWIN?
Дерек Ван Куйк

Нещодавно у мене була така проблема; Я сподіваюся, що це рішення допоможе: stackoverflow.com/questions/34537475/…
Олександру

Відповіді:


172

Спробуйте це:

[Authorize]
public ActionResult SomeAction()
{
    var identity = (ClaimsIdentity)User.Identity;
    IEnumerable<Claim> claims = identity.Claims;
    ...
}

Спасибі за вашу допомогу. Я використав вашу запропоновану відповідь в дії в контролері, щоб спробувати отримати доступ до значень претензій, однак, я посвідчував особистість. Претензії все ще NULL (див. Оновлене запитання зі скріншотом). Будь-які інші ідеї? Я вдячний за твою допомогу.
tcode

Ні, вибачте, що я не маю інших ідей. Це завжди працювало для мене.
Дарин Димитров

Вибачте, останнє запитання. Чи потрібно мені створити власний власний клас ClaimsAuthenticationManager та Application_PostAuthenticateRequest () у Global.asax, як цей dotnetcodr.com/2013/02/25/…, перш ніж мій код буде працювати вище? Знову дякую.
tcode

7
Поки Ви не авторизуєтесь вперше, Ви не матимете доступу до цього лише до того моменту, як Ваш метод входу, тому ОП не бачить цього часу. У цей час ви повинні завантажити вручну, якщо ви хочете, щоб це було в методі входу.
Адам Туліпер - MSFT

Я працюю з ядром asp.net і шукаю спосіб отримати зображення профілю LinkedIn протягом більше 2 годин. Я застряг, я втомився, хочу здатися, поки не побачу вашої відповіді. Хочу сказати подяку мільйон разів ... +1
Vayne

36

Ви також можете зробити це:

//Get the current claims principal
var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;
var claims = identity.Claims;

Оновлення

Надати подальше пояснення відповідно до коментарів.

Якщо ви створюєте користувачів у своїй системі:

UserManager<applicationuser> userManager = new UserManager<applicationuser>(new UserStore<applicationuser>(new SecurityContext()));
ClaimsIdentity identity = userManager.CreateIdentity(user, DefaultAuthenticationTypes.ApplicationCookie);

Ви повинні автоматично заповнити претензії, що стосуються вашої особи.

Щоб додати спеціальні претензії після автентифікації користувача, ви можете зробити це наступним чином:

var user = userManager.Find(userName, password);
identity.AddClaim(new Claim(ClaimTypes.Email, user.Email));

Претензії можна прочитати, як Дарин відповів вище або як я.

Претензії зберігаються, коли ви телефонуєте нижче, передаючи особу:

AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = persistCookie }, identity);

Дякую, але все одно це не працює для мене. Ви можете бачити моє оновлене запитання? Також, останнє питання. Чи потрібно мені створити власний власний клас ClaimsAuthenticationManager та Application_PostAuthenticateRequest () у Global.asax, як цей dotnetcodr.com/2013/02/25/…, перш ніж мій код буде працювати вище? Ще раз дякую за вашу допомогу.
tcode

Привіт, я погляну, коли я знову на ПК.
хутоноїд

дякую, дуже ціную це. На етапі, коли це починає
ламати

@tgriffiths Привіт, я додав оновлення для вас. Сподіваємось, надаємо трохи більше інформації. Удачі. :)
хутоноїд

на жаль, спочатку я не використовую вбудований Entity Framework Code, наприклад, UserManager тощо. Але дякую за ваш внесок. Ура.
tcode

30

Я створюю власний розширений клас, щоб побачити, що мені потрібно, тому, коли мені потрібно в свій контролер або мій погляд, я додаю лише використання в свій простір імен приблизно так:

public static class UserExtended
{
    public static string GetFullName(this IPrincipal user)
    {
        var claim = ((ClaimsIdentity)user.Identity).FindFirst(ClaimTypes.Name);
        return claim == null ? null : claim.Value;
    }
    public static string GetAddress(this IPrincipal user)
    {
        var claim = ((ClaimsIdentity)user.Identity).FindFirst(ClaimTypes.StreetAddress);
        return claim == null ? null : claim.Value;
    }
    public ....
    {
      .....
    }
}

У моєму контролері:

using XXX.CodeHelpers.Extended;

var claimAddress = User.GetAddress();

У моїй бритві:

@using DinexWebSeller.CodeHelpers.Extended;

@User.GetFullName()

8
return claim?.Value;бо чому б ні
Холтер

17

Це альтернатива, якщо ви не хочете постійно використовувати претензії. Погляньте на цей підручник Бена Фостера.

public class AppUser : ClaimsPrincipal
{
    public AppUser(ClaimsPrincipal principal)
        : base(principal)
    {
    }

    public string Name
    {
        get
        {
            return this.FindFirst(ClaimTypes.Name).Value;
        } 
    }

}

Потім можна додати базовий контролер.

public abstract class AppController : Controller
{       
    public AppUser CurrentUser
    {
        get
        {
            return new AppUser(this.User as ClaimsPrincipal);
        }
    }
}

У своєму контролері ви зробите:

public class HomeController : AppController
{
    public ActionResult Index()
    {
        ViewBag.Name = CurrentUser.Name;
        return View();
    }
}

12

Щоб додатково торкнутися відповіді Даріна, ви можете дійти до конкретних претензій, використовуючи метод FindFirst :

var identity = (ClaimsIdentity)User.Identity;
var role = identity.FindFirst(ClaimTypes.Role).Value;

Або цей занадто рядок myValue = identitet.FindFirstValue ("MyClaimType");
Хуан Карлос Пуерто

Що станеться, якщо FindFirst не знайде жодних претензій з типом "роль"? нульовий виняток?
Філ

10

Ви також можете це зробити.

IEnumerable<Claim> claims = ClaimsPrincipal.Current.Claims;

8

Пам'ятайте, що для того, щоб запитувати IEnumerable вам потрібно посилатись на system.linq.
Це дасть вам об’єкт розширення, необхідний для виконання:

CaimsList.FirstOrDefault(x=>x.Type =="variableName").toString();

7

найкоротша і спрощена версія відповіді @Rosdi Kasim'd така

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity).
    FindFirst("claimname").Value;

Claimname це претензія, яку ви хочете отримати, тобто якщо ви шукаєте претензію "StreedAddress", то вищевказана відповідь буде такою

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity).
    FindFirst("StreedAddress").Value;

наведення прикладу "претензійна ціна" заощадило мій час. Дякую
Nour Lababidi

6
Request.GetOwinContext().Authentication.User.Claims

Однак краще додавати претензії всередину методу "GenerateUserIdentityAsync", особливо якщо ввімкнено regenerateIdentity в Startup.Auth.cs.


Це GenerateUserIdentityAsyncбуло приголомшливою пропозицією, я цілком його не помітив. Велике спасибі Василю.
timmi4sa

2

Відповідно до класу ControllerBase, ви можете отримати претензії до користувача, який виконує дію.

введіть тут опис зображення

ось як ви можете це зробити в 1 рядку.

var claims = User.Claims.ToList();


0

Я використовував це так у своєму базовому контролері. Просто поділитися готовим до використання.

    public string GetCurrentUserEmail() {
        var identity = (ClaimsIdentity)User.Identity;
        IEnumerable<Claim> claims = identity.Claims;
        var email = claims.Where(c => c.Type == ClaimTypes.Email).ToList();
        return email[0].Value.ToString();
    }

    public string GetCurrentUserRole()
    {
        var identity = (ClaimsIdentity)User.Identity;
        IEnumerable<Claim> claims = identity.Claims;
        var role = claims.Where(c => c.Type == ClaimTypes.Role).ToList();
        return role[0].Value.ToString();
    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.