81

Я разрабатываю web-приложение MVC 5 с использованием Entity Framework 5 Database First. Я использую OWIN для аутентификации пользователей. Ниже показан мой метод входа в мой контроллер учетных записей.MVC 5 Access Claims Identity User Data

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/

Например, я попробовал это в моем коде контроллера в попытке получить доступ к значениям, переданным в Претензии, однако, user.Claims равен нулю

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

Возможно, мне что-то не хватает.

UPDATE

На основании ответа Дарин, я добавил свой код, но все-таки я не вижу, доступ к Требованиям. См. Снимок экрана ниже, показывающий, что я вижу, когда он зависает над личностью.

enter image description here

+0

Можете ли вы подтвердить, что файл cookie отправлен обратно браузером? Возможно, ваши настройки безопасности требуют SSL? – leastprivilege

+0

@leastprivilege Спасибо, я сейчас изучу это. Я нашел этот вопрос в Stackoverflow, http://stackoverflow.com/questions/20319118/i-cant-seem-to-get-a-very-basic-cookie-login-example-to-work-with-mvc5-and -owin? rq = 1 это то же самое, что у меня есть, но, к сожалению, нет ответа на него :( – tgriffiths

+0

Как инициализируются ваши компоненты OWIN? –

ответ

109

Попробуйте это:

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

Спасибо за вашу помощь. ваш предложенный ответ в действии в контроллере, чтобы попытаться получить доступ к значениям Претензий, однако, я удостоверяюсь.Claims по-прежнему NULL (см. обновленный вопрос со снимком экрана). Любые другие идеи? Я ценю вашу помощь. – tgriffiths

+0

Нет, извините, У меня есть другие идеи. Это всегда срабатывало для меня. –

+0

никаких проблем, спасибо в любом случае. – tgriffiths

27

Вы также можете сделать это:

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

Update

Для обеспечения дальнейшего объяснения, как в комментариях.

Если вы создаете пользователей в вашей системе следующим образом:

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); 

Эта статья описывает это более подробно и конкретно к MVC 5, другие статьи я знаю направлены на MVC 4.

http://kevin-junghans.blogspot.co.uk/2013/12/using-claims-in-aspnet-identity.html

+0

Спасибо, но все же это не работает для меня. Вы можете увидеть мой обновленный вопрос? Кроме того, последний вопрос. Мне нужно создать свой собственный класс ClaimsAuthenticationManager и Application_PostAuthenticateRequest() в Global.asax, как этот http://dotnetcodr.com/2013/02/25/claims-based-authentication-in-mvc4-with-net4-5- c-part-1-Claim-transform/до того, как мой код выше будет работать? В очередной раз благодарим за помощь. – tgriffiths

+0

Привет, я посмотрю, когда вернусь на компьютер. – hutchonoid

+0

спасибо, очень признательны. На этапе, где это начинает взламывать меня :) – tgriffiths

10

Вы также можете сделать это.

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

Для дальнейшего прикосновения ответа Дарин, вы можете добраться до ваших конкретных требований, используя FindFirst метода:

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

Или этот тоже string myValue = identity.FindFirstValue ("MyClaimType"); –

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

Однако лучше добавлять претензии внутри " GenerateUserIdentityAsync ", особенно если включена функция регенерации в Startup.Auth.cs.

+0

«GenerateUserIdentityAsync» было потрясающим предложением, я полностью его не замечал. Большое спасибо Василий. – timmi4sa

13

Это альтернатива, если вы не хотите постоянно использовать требования. Взгляните на это tutorial от Ben Foster.

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(); 
    } 
} 
5

Помните, что для того, чтобы выполнить запрос на IEnumerable вам нужно ссылаться на System.Linq.
Это даст вам объект расширения, необходимые, чтобы сделать:

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

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

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() 
+4

'return Claim? .Value;' потому что почему бы и нет – Halter

2

В соответствии с классом ControllerBase вы можете получить претензии для пользователя, выполняющего действие.

enter image description here

вот как вы можете это сделать в 1 линии.

var claims = User.Claims.ToList(); 
4

короткий и упрощенный вариант @Rosdi Kasim'd ответ является

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

Claimname является утверждение, вы хотите получить я.e, если вы ищете претензию «StreedAddress», то вышеуказанный ответ будет таким:

string claimvalue = ((System.Security.Claims.ClaimsIdentity)User.Identity). 
    FindFirst("StreedAddress").Value; 
Смежные вопросы