MVC 5 เข้าถึงการอ้างสิทธิ์ข้อมูลตัวตนของผู้ใช้


119

ฉันกำลังพัฒนาเว็บแอปพลิเคชันMVC 5โดยใช้แนวทางแรกของฐานข้อมูล Entity Framework 5 ฉันใช้OWINสำหรับการรับรองความถูกต้องของผู้ใช้ ด้านล่างนี้แสดงวิธีการเข้าสู่ระบบของฉันภายใน Account Controller ของฉัน

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เพื่อทำการลงชื่อเข้าใช้

ปัญหาที่ฉันพบคือฉันไม่แน่ใจว่าจะเข้าถึงการอ้างสิทธิ์ในส่วนที่เหลือของแอปพลิเคชันของฉันได้อย่างไรทั้งในตัวควบคุมหรือในมุมมองมีดโกน

ฉันได้ลองใช้แนวทางที่ระบุไว้ในบทช่วยสอนนี้แล้ว

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

ตัวอย่างเช่นฉันลองใช้สิ่งนี้ในรหัสคอนโทรลเลอร์ของฉันเพื่อพยายามเข้าถึงค่าที่ส่งผ่านไปยังการอ้างสิทธิ์อย่างไรก็ตามผู้ใช้การอ้างสิทธิ์มีค่าเท่ากับ null

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

บางทีฉันอาจจะพลาดอะไรบางอย่างที่นี่

UPDATE

จากคำตอบของดารินฉันได้เพิ่มรหัสของเขา แต่ฉันก็ยังไม่เห็นการเข้าถึงการอ้างสิทธิ์ โปรดดูภาพหน้าจอด้านล่างที่แสดงสิ่งที่ฉันเห็นเมื่อวางเมาส์เหนือตัวตนการอ้างสิทธิ์

ใส่คำอธิบายภาพที่นี่


คุณสามารถยืนยันได้หรือไม่ว่าเบราว์เซอร์ส่งคุกกี้กลับมา บางทีการตั้งค่าความปลอดภัยของคุณอาจต้องการ SSL?
น้อยที่สุด

@leastprivilege ขอบคุณฉันจะตรวจสอบในตอนนี้ ฉันพบคำถามนี้ใน Stackoverflow, stackoverflow.com/questions/20319118/…มันเป็นปัญหาเดียวกันกับที่ฉันพบ แต่น่าเสียดายที่ไม่มีคำตอบ :(
tcode

ส่วนประกอบ OWIN ของคุณเริ่มต้นอย่างไร
Derek Van Cuyk

ฉันเพิ่งมีปัญหาเช่นนี้ ฉันหวังว่าโซลูชันนี้จะช่วยได้: stackoverflow.com/questions/34537475/…
Alexandru

คำตอบ:


172

ลองสิ่งนี้:

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

ขอบคุณสำหรับความช่วยเหลือของคุณ. ฉันใช้คำตอบที่คุณแนะนำในการดำเนินการภายในคอนโทรลเลอร์เพื่อลองและเข้าถึงค่าการอ้างสิทธิ์อย่างไรก็ตามฉันระบุการอ้างสิทธิ์ยังคงเป็นโมฆะ (ดูคำถามที่อัปเดตพร้อมภาพหน้าจอ) ความคิดอื่น ๆ ? ฉันขอขอบคุณสำหรับความช่วยเหลือของคุณ
tcode

ไม่ขอโทษฉันไม่มีความคิดอื่น สิ่งนี้ได้ผลสำหรับฉันมาตลอด
Darin Dimitrov

ขออภัยคำถามสุดท้าย ฉันจำเป็นต้องสร้างคลาส ClaimsAuthenticationManager ที่กำหนดเองและ Application_PostAuthenticateRequest () ใน Global.asax เช่นนี้dotnetcodr.com/2013/02/25/…ก่อนที่โค้ดด้านบนจะใช้งานได้หรือไม่ ขอบคุณอีกครั้ง.
tcode

7
จนกว่าคุณจะอนุญาตเป็นครั้งแรกคุณจะไม่สามารถเข้าถึงสิ่งนี้ได้จนกว่าจะใช้วิธีการเข้าสู่ระบบของคุณซึ่งเป็นสาเหตุที่ OP ไม่เห็นในเวลานั้น คุณต้องโหลดด้วยตนเองในขณะนี้หากคุณต้องการในวิธีการเข้าสู่ระบบ
Adam Tuliper - MSFT

ฉันกำลังทำงานกับ asp.net core และกำลังมองหาวิธีรับรูปโปรไฟล์ 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));

การอ้างสิทธิ์สามารถอ่านย้อนหลังได้ตามที่ Darin ได้ตอบไว้ข้างต้นหรือตามที่ฉันมี

การอ้างสิทธิ์จะยังคงอยู่เมื่อคุณโทรด้านล่างโดยส่งข้อมูลประจำตัวใน:

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

ขอบคุณ แต่ยังไม่ได้ผลสำหรับฉัน คุณสามารถดูคำถามที่อัปเดตของฉันได้ไหม นอกจากนี้คำถามสุดท้าย ฉันจำเป็นต้องสร้างคลาส ClaimsAuthenticationManager ที่กำหนดเองและ Application_PostAuthenticateRequest () ใน Global.asax เช่นนี้dotnetcodr.com/2013/02/25/…ก่อนที่โค้ดด้านบนจะใช้งานได้หรือไม่ ขอขอบคุณอีกครั้งสำหรับความช่วยเหลือของคุณ
tcode

สวัสดีฉันจะดูเมื่อฉันกลับมาใช้พีซี
hutchonoid

ขอบคุณจริงๆขอบคุณมาก ในขั้นตอนที่สิ่งนี้เริ่มทำให้ฉันแตก :)
tcode

@tgriffiths สวัสดีฉันได้เพิ่มการอัปเดตสำหรับคุณแล้ว หวังว่าจะให้ข้อมูลเพิ่มเติมอีกเล็กน้อย โชคดี. :)
hutchonoid

น่าเสียดายที่ฉันไม่ได้ใช้ Entity Framework Code First ในตัวเช่น 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;เพราะเหตุใดจึงไม่
Halter

17

นี่เป็นอีกทางเลือกหนึ่งหากคุณไม่ต้องการใช้การอ้างสิทธิ์ตลอดเวลา ดูบทช่วยสอนนี้โดย 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();
    }
}

12

หากต้องการสัมผัสคำตอบของ Darin เพิ่มเติมคุณสามารถเข้าถึงข้อเรียกร้องเฉพาะของคุณได้โดยใช้วิธีFindFirst :

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

หรืออันนี้ก็สตริง myValue = identity.FindFirstValue ("MyClaimType");
Juan Carlos Puerto

จะเกิดอะไรขึ้นหาก FindFirst ไม่พบการอ้างสิทธิ์ในประเภท "บทบาท" ข้อยกเว้นว่าง?
ฟิลิป


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เป็นข้อเสนอแนะที่น่ากลัวฉันได้มองข้ามมันทั้งหมด ขอบคุณมาก Basil.
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();
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.