MVC 5 Erişim İddiaları Kimlik Kullanıcı Verileri


119

Entity Framework 5 Database First yaklaşımını kullanarak bir MVC 5 web uygulaması geliştiriyorum. Kullanıcıların kimlik doğrulaması için OWIN kullanıyorum . Aşağıda Hesap Denetleyicimdeki Oturum Açma yöntemimi gösteriliyor.

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

Gördüğünüz gibi bir ClaimsIdentity oluşturuyorum ve ona birkaç talep ekliyorum, ardından oturum açma işlemini gerçekleştirmek için AuthenticationManager'ı kullanarak OWIN'e iletiyorum .

Yaşadığım sorun, uygulamamın geri kalanında, Denetleyicilerde veya Razor Görünümlerinde taleplere nasıl erişeceğimi bilmememdir.

Bu öğreticide listelenen yaklaşımı denedim

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

Örneğin, bunu Kontrolör kodumda Taleplere aktarılan değerlere erişme girişiminde denedim, ancak kullanıcı.Claims eşittir null

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

Belki de burada bir şey eksik.

GÜNCELLEME

Darin'in cevabına dayanarak, kodunu ekledim ama yine de Taleplere erişimi göremiyorum. Lütfen kimliğin üzerine geldiğimde gördüklerimi gösteren aşağıdaki ekran görüntüsüne bakın.

görüntü açıklamasını buraya girin


Çerezin tarayıcı tarafından geri gönderildiğini onaylayabilir misiniz? Belki güvenlik ayarlarınız SSL gerektiriyor?
lessprivilege

@leastprivilege Teşekkürler, şimdi buna bakacağım. Bu soruyu Stackoverflow'da buldum, stackoverflow.com/questions/20319118/… bu benim yaşadığım sorunla aynı, ancak maalesef yanıt yok :(
tcode

OWIN bileşenleriniz nasıl başlatılır?
Derek Van Cuyk

Son zamanlarda böyle bir sorun yaşadım; Umarım bu çözüm yardımcı olur: stackoverflow.com/questions/34537475/…
Alexandru

Yanıtlar:


172

Bunu dene:

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

Yardımınız için teşekkürler. Talepler değerlerini denemek ve bunlara erişmek için bir Denetleyici içindeki bir Eylemde önerilen cevabınızı kullandım, ancak kimliğim. Talepler hala NULL (ekran görüntüsü ile güncellenmiş soruya bakın). Başka fikrin var mı? Yardımın için minnettarım.
2014

Hayır, üzgünüm başka fikrim yok. Bu her zaman benim için çalıştı.
Darin Dimitrov

Üzgünüm, son bir soru. Yukarıdaki kodum çalışmadan önce bu dotnetcodr.com/2013/02/25/… gibi Global.asax içinde kendi özel ClaimsAuthenticationManager sınıfımı ve Application_PostAuthenticateRequest () 'i oluşturmam gerekir mi? Tekrar teşekkürler.
2014

7
İlk kez Yetkilendirene kadar, oturum açma yönteminizden sonrasına kadar buna erişiminiz olmayacaktır, bu yüzden OP bunu o anda görmez. Giriş yönteminde istiyorsanız, şu anda manuel olarak yüklemeniz gerekir.
Adam Tuliper - MSFT

Asp.net core ile çalışıyorum ve 2 saatten fazla bir süre boyunca LinkedIn profil resmini almanın yolunu arıyorum. Sıkıştım, yorgunum, cevabını görene kadar pes etmek istiyorum. Milyonlarca kez teşekkür etmek istiyorum ... +1
Vayne

36

Bunu da yapabilirsiniz:

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

Güncelleme

Yorumlara göre daha fazla açıklama sağlamak için.

Sisteminizde aşağıdaki gibi kullanıcılar oluşturuyorsanız:

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

Kimliğinizle ilgili olarak bazı Talepler otomatik olarak doldurulmalıdır.

Bir kullanıcının kimliğini doğruladıktan sonra özelleştirilmiş talepler eklemek için bunu aşağıdaki şekilde yapabilirsiniz:

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

İddialar, Darin'in yukarıda cevapladığı veya benim cevapladığım gibi tekrar okunabilir.

Aşağıdaki kimliği girdiğinizde iddialar devam eder:

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

Teşekkürler, ama yine de bu benim için çalışmıyor. Güncellenen sorumu görebiliyor musunuz? Ayrıca son bir soru. Yukarıdaki kodum çalışmadan önce bu dotnetcodr.com/2013/02/25/… gibi Global.asax içinde kendi özel ClaimsAuthenticationManager sınıfımı ve Application_PostAuthenticateRequest () 'i oluşturmam gerekir mi? Yardımın için tekrar teşekkürler.
2014

Merhaba, PC'ye geri döndüğümde bir göz atacağım.
hutchonoid

teşekkürler, gerçekten minnettarım. Bunun beni
kırmaya başladığı

@tgriffiths Merhaba, sizin için bir güncelleme ekledim. Umarım biraz daha fazla bilgi sağlar. İyi şanslar. :)
hutchonoid

ne yazık ki ben yerleşik Entity Framework Code First, örneğin UserManager vb. kullanmıyorum. Ancak girdiniz için teşekkürler. Şerefe.
2014

30

Neye ihtiyacım olduğunu görmek için kendi genişletilmiş sınıfımı yapıyorum, bu nedenle denetleyicime veya Görünümüme ihtiyacım olduğunda, kullanımı ad alanıma yalnızca şu şekilde eklerim:

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 ....
    {
      .....
    }
}

Denetleyicimde:

using XXX.CodeHelpers.Extended;

var claimAddress = User.GetAddress();

Tıraş makinemde:

@using DinexWebSeller.CodeHelpers.Extended;

@User.GetFullName()

8
return claim?.Value;çünkü neden olmasın
Halter

17

Her zaman hak taleplerini kullanmak istemiyorsanız bu bir alternatiftir. Ben Foster tarafından hazırlanan bu eğiticiye bir göz atın .

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

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

}

Daha sonra bir temel kontrolör ekleyebilirsiniz.

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

Kontrol cihazınızda şunları yaparsınız:

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

12

Darin'in cevabına daha fazla değinmek için, FindFirst yöntemini kullanarak özel iddialarınıza ulaşabilirsiniz :

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

Veya bu çok string myValue = kimlik.FindFirstValue ("MyClaimType");
Juan Carlos Porto

FindFirst "rol" türünde herhangi bir iddia bulamazsa ne olur? null istisna?
Phil

10

Bunu da yapabilirsiniz.

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

8

IEnumerable'ı sorgulamak için system.linq'e başvurmanız gerektiğini unutmayın.
Size yapmanız gereken uzantı nesnesini verecektir:

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

7

@Rosdi Kasim'in en kısa ve basitleştirilmiş hali

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

Claimname geri almak istediğiniz hak talebi, yani "StreedAddress" talebini arıyorsanız, yukarıdaki cevap şu şekilde olacaktır

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

"talep değeri" örneğini sağlamak zaman kazandırdı. Teşekkürler
Nour Lababidi

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

Ancak talepleri "GenerateUserIdentityAsync" yönteminin içine eklemek, özellikle de Startup.Auth.cs dosyasında regenerateIdentity etkinleştirilmişse daha iyidir.


GenerateUserIdentityAsyncTamamen bunu gözardı, müthiş bir öneriydi. Çok teşekkürler Basil.
timmi4sa

2

ControllerBase sınıfına göre, eylemi yürüten kullanıcı için talepleri alabilirsiniz.

görüntü açıklamasını buraya girin

işte bunu 1 satırda nasıl yapacağınız.

var claims = User.Claims.ToList();


0

Bunu temel kontrol cihazımda böyle kullandım. Sadece kullanıma hazır olarak paylaşın.

    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();
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.