APIControler 中的 Request.GetOwinContext().Get<T> return null

Request.GetOwinContext().Get<T> return null in APIControler

我无法从 OwinContext 环境中检索我在通过令牌验证后存储的数据。

这是代码:
[验证客户端身份验证] 在代码中,我验证了用户的 ClientID,然后将 ApplicationClient 的数据存储在这一行的 OwinContext 中

public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        ...
        ApplicationClient App = new ApplicationClient();
        App.Id = clientId;
        App.ClientSecretHash = clientSecret;
        // Storing Client Data
        context.OwinContext.Set<ApplicationClient>("oauth:client", App);
        context.Validated(clientId);
    }

[GrantResourceOwnerCredentials] 在这里,我验证用户凭据并将气候添加到令牌

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    ...
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    if (Membership.ValidateUser(username, password))
    {          
        identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
        identity.AddClaim(new Claim(ClaimTypes.Name, username));
        context.Validated(identity);
    }
    else
    {
        context.SetError("Login Field", "Error username or password");
    }
}

[ControlerCode] 现在这是我的问题

[Authorize]
public class MyController : ApiController
{
    public IEnumerable<SelectedMenu> GetAllMenus() // Resturants ID
    {
        // client is Null
        ApplicationClient client = HttpContext.Current.GetOwinContext().Get<ApplicationClient>("oauth:client");
    }
}

您真的应该只在您的令牌中添加 clientId,这样您就可以在登录过程后随时取回它。

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    // ...
    var identity = new ClaimsIdentity(context.Options.AuthenticationType);
    if (Membership.ValidateUser(username, password))
    {          
        identity.AddClaim(new Claim(ClaimTypes.Role, "admin"));
        identity.AddClaim(new Claim(ClaimTypes.Name, username));
        identity.AddClaim(new Claim("oauth-client", context.ClientId));
        context.Validated(identity);
    }
    else
    {
        context.SetError("Login Field", "Error username or password");
    }
}

您还可以创建一个扩展方法来帮助您检索 clientId:

public static class PrincipalExtensions
{
    public static string GetClientId(this IPrincipal principal)
    {
        return (principal.Identity as ClaimsIdentity)?
            .Claims
            .FirstOrDefault(c => c.Type == "oauth-client")?
            .Value;
    }    
}

在你的控制器中:

[Authorize]
public class MyController : ApiController
{
    public IEnumerable<SelectedMenu> GetAllMenus() // Resturants ID
    {
        var clientId = User.GetClientId();
    }
}

关于令牌大小:如果您的 clientId 字符串太长,我建议您使用另一个字符串并将任何其他客户端信息(如果需要,包括更长的 ID)存储在数据库中。客户端标识符应该是一个小而独特的字符串,易于传输。