具有基于角色的授权的ASP.NET Web Api

dna*_*non 8 c# asp.net owin

我使用Web API 2与基于OWIN令牌的身份验证.只有不起作用的是基于角色的授权.

在我的AuthorizationServerProvider.GrantResourceOwnerCredentials的实现中,这是我分配角色的方式:

identity.AddClaim(client.ApplicationType == ApplicationTypes.WebClient
            ? new Claim(ClaimTypes.Role, "user")
            : new Claim(ClaimTypes.Role, "admin"));
Run Code Online (Sandbox Code Playgroud)

但是在Controller中使用[Authenticate(Roles ="user")]只是向客户端返回授权拒绝消息.我检查了变量,这是什么内部 在此输入图像描述

所以角色似乎存在,但user.Claims为空,IsInRole("user")也返回负数.

我在stackoverflow和逻辑方面发现了几个问题,我没有看到我错过了什么.我想到的只是覆盖授权命令,但由于基于角色的授权似乎已经集成,所以这是不必要的......

编辑:这是我的workig方法的样子:

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
    var allowedOrigin = context.OwinContext.Get<string>("as:clientAllowedOrigin") ?? "*";
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });

    Client client;
    using (var repo = new AuthRepository())
    {
        client = repo.FindClient(context.ClientId);
        if (client.ApplicationType != ApplicationTypes.Service)
        {
            var user = await repo.FindUser(context.UserName, context.Password);

            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect." + context.UserName);
                return;
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

Vi1*_*100 5

不要直接添加角色声明,而是使用UserManager:

UserManagerInstance.AddToRole(userId, "admin");
Run Code Online (Sandbox Code Playgroud)

这样,角色将被持久化(到AspNetUserRoles或您配置的任何内容),因此它将用于后续请求.如果您直接添加声明,则不会发生这种情况,因为您将其添加到用户身份的"实例"中,该实例会因当前请求而死亡.

回答您的进一步要求:

如果您希望在票证上编制索赔,那么您必须按照您的方式添加索赔(在GrantResourceOwnerCredentials中):

var props = new AuthenticationProperties(new Dictionary<string, string>
        {
            { "userId", "blah,blah" },
            { "role", "admin" }
        });

var ticket = new AuthenticationTicket(identity, props);
context.Validated(ticket);
Run Code Online (Sandbox Code Playgroud)

这样您就不必"坚持"这类用户

当然,您必须覆盖OAuthAuthorizationServerProvider的TokenEndpoint方法,以便在以后的请求/响应中检索这些数据.

    public override Task TokenEndpoint(OAuthTokenEndpointContext context)
    {
        foreach (KeyValuePair<string, string> property in context.Properties.Dictionary)
        {
            context.AdditionalResponseParameters.Add(property.Key, property.Value);
        }

        return Task.FromResult<object>(null);
    }
Run Code Online (Sandbox Code Playgroud)