11

我的 WebAPI 2 应用程序有一个自定义授权过滤器,用于检查访问令牌。如果令牌存在,并且 API 具有该属性,那么我检查是否存在映射到该令牌的用户。

由于 API 的性质,大多数方法在特定用户的上下文中运行(即“POST api/profile”以更新用户的配置文件)。为此,我需要从访问令牌中获得的目标用户信息。

[当前实现,发生在 AuthorizeAttribute 类型的属性中]

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

这工作正常,然后我可以使用访问令牌在方法中进行第二次查找。但是由于我已经在身份验证时进行了查找,所以我不想浪费另一个 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;
}
4

2 回答 2

11

您可以使用自己的主要课程。也许是这样的:

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,如果是,则对其进行转换,然后访问 UserDetails:

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

我还没有实际尝试过这段代码,所以可能有错别字......

于 2013-10-29T11:33:48.773 回答
8

您可以使用 aClaimsIdentity/ClaimsPrincipal并稍后在控制器中添加Claims您需要的,例如您需要的演员 ID 或其他值。

我已经做了一个示例,它为 Actor 设置声明,但如果它更适合您,您也可以在 Claims 处直接对当前用户。

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;
于 2013-10-29T09:22:57.570 回答