2013-10-28 2 views
7

내 WebAPI 2 응용 프로그램에는 액세스 토큰을 확인하는 사용자 지정 인증 필터가 있습니다. 토큰이 있고 API에 속성이있는 경우 해당 토큰에 매핑되는 사용자가 있는지 확인합니다.사용자 개체의 주체/사용자 컨텍스트 설정

API의 특성상 대부분의 메소드는 특정 사용자의 컨텍스트 (즉, 사용자 프로필을 업데이트하는 "POST API/프로필")에서 실행됩니다. 이를 위해서는 액세스 토큰에서 얻은 대상 사용자에 대한 정보가 필요합니다.

if(myDBContext.MyUsers.Count(x => x.TheAccessToken == clientProvidedToken)){ 
    IPrincipal principal = new GenericPrincipal(new GenericIdentity(myAccessToken), new string[] { "myRole" }); 
    Thread.CurrentPrincipal = principal; 
    HttpContext.Current.User = principal; 
    return true; 
} 

이 잘 작동 [현재 구현, 유형 AuthorizeAttribute의 속성 내에서 발생], 나는 그 방법에 두 번째 조회를 수행 할 액세스 토큰을 사용할 수 있어요. 하지만 이미 인증 시간에 조회를 했으므로 다른 DB 호출을 낭비하고 싶지 않습니다.

[내가하고 싶은 (그러나 분명히 작동하지 않습니다) 어떤]

MyUser user = myDBContext.MyUsers.FirstOrDefault(x => x.TheAccessToken == clientProvidedToken); 
if(user != null){ 
    // Set *SOME* property to the User object, such that it can be 
    // access in the body of my controller method 
    // (e.g. /api/profile uses this object to load data) 
    HttpContext.Current.User = user; 
    return true; 
} 

답변

8

자신의 교장 수업을 사용할 수 있습니다. 어쩌면 같은 것을 :

public class MyPrincipal : GenericPrincipal 
{ 
    public MyPrincipal(IIdentity identity, string[] roles) 
     : base(identity, roles) 
    { 
    } 
    public MyUser UserDetails {get; set;} 
} 

그런 다음 액션 필터가 할 수있는 :

MyUser user = myDBContext.MyUsers.FirstOrDefault(x => x.TheAccessToken == clientProvidedToken); 
if(user != null) 
{ 
    MyPrincipal principal = new MyPrincipal(new GenericIdentity(myAccessToken), new string[] { "myRole" }); 
    principal.UserDetails = user; 
    Thread.CurrentPrincipal = principal; 
    HttpContext.Current.User = principal; 
    return true; 
} 
return false; 

그리고 이후를 실제 방법, 당신은 유형 MyPrincipal의 있는지 확인, 현재 사용자를 가지고 그래서 캐스팅 경우 수 ...

,369

... 
MyUser currentUser = null; 
MyPrincipal curPrincipal = HttpContext.Current.User as MyPrincipal; 
if (curPrincipal != null) 
{ 
    currentUser = curPrincipal.UserDetails; 
} 
... 

내가 actaully이 코드를 시도하지 않은, 그래서 오타가있을 수 있습니다 : 다음의 UserDetails에 액세스

+0

GenericPrincipal 확장을 생각하지 않은 이유를 모르겠다. 멋지게 일했습니다! 고맙습니다! – ShaneC

7

당신은 ClaimsIdentity/ClaimsPrincipal를 사용하고이 Claims 당신이 배우 예를 들어, 나중에 컨트롤러에 필요한 추가 할 수 있습니다 ID 또는 필요한 다른 값.

나는 액터에 클레임을 설정하는 예제를 만들었지 만, 더 잘 맞는 경우 클레임에서 현재 사용자에게 직접 설정할 수도 있습니다.

var identity = new ClaimsIdentity(HttpContext.Current.User.Identity); 
identity.Actor = new ClaimsIdentity(); 
identity.Actor.AddClaim(new Claim("Your", "Values")); 

var principal = new ClaimsPrincipal(identity); 
Thread.CurrentPrincipal = principal; 
HttpContext.Current.User = Thread.CurrentPrincipal; 
+1

클레임을 사용하면 작업하기보다는 프레임 워크와 정렬되기 때문에 클레임을 사용하는 것이 좋습니다. 또는 코드가 HttpContext에 의존한다면 어쨌든 HttpContext.Profile도 사용할 수 있습니다. http://msdn.microsoft.com/en-us/library/system.web.httpcontext.profile(v=vs.110).aspx – user3285954