MVC 5 액세스 클레임 신원 사용자 데이터


119

Entity Framework 5 Database First 접근 방식을 사용하여 MVC 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를 만들고 여기에 여러 클레임을 추가 한 다음 AuthenticationManager 를 사용하여 OWIN에 전달 하여 로그인을 수행합니다.

내가 가진 문제는 컨트롤러 또는 Razor 뷰에서 내 애플리케이션의 나머지 부분에서 클레임에 액세스하는 방법을 잘 모르겠다는 것입니다.

이 튜토리얼에 나열된 접근 방식을 시도했습니다.

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;

아마도 여기에 뭔가 빠진 것 같습니다.

최신 정보

Darin의 답변에 따라 그의 코드를 추가했지만 여전히 클레임에 대한 액세스를 볼 수 없습니다. ID 위로 마우스를 가져 갔을 때 표시되는 내용을 보여주는 아래 스크린 샷을 참조하십시오.

여기에 이미지 설명 입력


브라우저에서 쿠키가 다시 전송되었는지 확인할 수 있습니까? 보안 설정에 SSL이 필요할까요?
leastprivilege

@leastprivilege 감사합니다. 지금 살펴 보겠습니다. 나는 Stackoverflow, stackoverflow.com/questions/20319118/ 에서이 질문을 발견 했습니다… 그것은 내가 가지고있는 똑같은 문제이지만, 불행히도 그것에 대한 대답이 없습니다 :(
tcode

OWIN 구성 요소는 어떻게 초기화됩니까?
Derek Van Cuyk

최근에 이와 같은 문제가 발생했습니다. 이 솔루션이 도움이
Alexandru

답변:


172

이 시도:

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

당신의 도움을 주셔서 감사합니다. 컨트롤러 내의 작업에서 제안 된 답변을 사용하여 클레임 값에 액세스하려고 시도했지만 I identity. 클레임은 여전히 ​​NULL입니다 (스크린 샷으로 업데이트 된 질문 참조). 다른 아이디어가 있습니까? 도와 주셔서 감사합니다.
tcode 2014 년

아니요, 다른 생각이 없어서 죄송합니다. 이것은 항상 나를 위해 일했습니다.
Darin Dimitrov 2014 년

죄송합니다. 마지막 질문입니다. 위의 코드가 작동하기 전에이 dotnetcodr.com/2013/02/25/… 와 같이 Global.asax에서 고유 한 사용자 지정 ClaimsAuthenticationManager 클래스 및 Application_PostAuthenticateRequest ()를 만들어야 합니까? 다시 한 번 감사드립니다.
tcode

7
처음으로 인증 할 때까지 로그인 방법이 끝날 때까지이 항목에 액세스 할 수 없기 때문에 OP가 해당 시점에이를 볼 수 없습니다. 로그인 방법에서 원할 경우 이때 수동으로로드해야합니다.
Adam Tuliper-MSFT 2014 년

저는 asp.net core와 함께 일하고 있으며 2 시간 이상 동안 LinkedIn 프로필 사진을 얻을 수있는 방법을 찾고 있습니다. 갇혀 피곤해 답을 볼 때까지 포기하고 싶어 백만 번 감사합니다 ... +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이 위에서 대답했거나 내가 가진 것처럼 다시 읽을 수 있습니다.

아래에서 ID를 전달하면 클레임이 유지됩니다.

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

고마워요,하지만 여전히이게 저에게 효과가 없습니다. 업데이트 된 질문을 볼 수 있습니까? 또한 마지막 질문입니다. 위의 코드가 작동하기 전에이 dotnetcodr.com/2013/02/25/… 와 같이 Global.asax에서 고유 한 사용자 지정 ClaimsAuthenticationManager 클래스 및 Application_PostAuthenticateRequest ()를 만들어야 합니까? 도와 주셔서 다시 한 번 감사드립니다.
tcode

안녕하세요. PC로 돌아 오면 살펴 보겠습니다.
hutchonoid

감사합니다. 정말 감사합니다. 이것이 나를 부수기 시작하는 단계에서 :)
tcode

@tgriffiths 안녕하세요, 업데이트를 추가했습니다. 조금 더 많은 정보를 제공하기를 바랍니다. 행운을 빕니다. :)
hutchonoid 2014 년

안타깝게도 기본 제공 Entity Framework Code First (예 : UserManager 등)를 사용하지 않습니다.하지만 입력 해 주셔서 감사합니다. 건배.
tcode

30

필요한 것을 확인하기 위해 자체 확장 클래스를 만들었으므로 컨트롤러 또는 뷰에 필요할 때 다음과 같이 내 네임 스페이스에만 using을 추가합니다.

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;

또는 이것도 string myValue = identity.FindFirstValue ( "MyClaimType");
Juan Carlos Puerto

FindFirst가 "역할"유형의 클레임을 찾지 못하면 어떻게됩니까? null 예외?
Phil

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;

"claimvalue"예제를 제공하면 시간이 절약되었습니다. 감사합니다
Nour Lababidi

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

그러나 특히 Startup.Auth.cs에서 regenerateIdentity가 활성화 된 경우 "GenerateUserIdentityAsync"메서드 내부에 클레임을 추가하는 것이 좋습니다.


GenerateUserIdentityAsync나는 완전히 그것을 간과 한 멋진 제안했다. 고마워요 바질.
timmi4sa 2014-06-28

2

ControllerBase 클래스에 따르면 작업을 실행하는 사용자에 대한 클레임을 얻을 수 있습니다.

여기에 이미지 설명 입력

여기에 한 줄로 할 수있는 방법이 있습니다.

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.