授权角色WebAPI oauth owin

CaT*_*ist 22 c# authorization oauth asp.net-mvc-4 owin

我在ASP.NET Web API上使用OWIN中间件实现了一个令牌授权系统.我成功地可以使用REST客户端进行身份验证并获取授权令牌来调用API.如果我将[Authorize]属性放在我的控制器中的GET操作上,它也可以正常工作.如果我没有有效的令牌,它会拒绝带有401消息的资源,但如果我使用[Authorize(Roles="admins")]roles参数,它将无法识别用户的角色.我验证了数据库中的内容并检查了它usersinroles是否正确填充.

这是一段代码:

[Authorize(Roles = "admins")]
public IEnumerable<CompanyModel> Get()
{
    ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;
    bool isrole = principal.IsInRole("admins");
Run Code Online (Sandbox Code Playgroud)

我还检查了没有roles参数的动作,并且isrole总是布尔值false.我必须启用某些功能吗?

Xav*_*gea 45

您必须添加GrantResourceOwnerCredentials方法:

identity.AddClaim(new Claim(ClaimTypes.Role, "admins"));
Run Code Online (Sandbox Code Playgroud)

一步步

在StartUp.cs类中,您应该有一个自定义提供程序,如行

Provider = new CustomAuthorizationServerProvider()
Run Code Online (Sandbox Code Playgroud)

例如:

public void ConfigureOAuth(IAppBuilder app)
{
    OAuthAuthorizationServerOptions oAuthServerOptions = new OAuthAuthorizationServerOptions
    {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
        Provider = new CustomAuthorizationServerProvider()
    };

    // Token Generation
    app.UseOAuthAuthorizationServer(oAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());
}
Run Code Online (Sandbox Code Playgroud)

然后,继承自OAuthAuthorizationServerProvider类的CustomAuthorizationServerProvider 将覆盖GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext上下文).

然后,在检查用户具有正确的用户名和密码后,您必须添加

var identity = new ClaimsIdentity(context.Options.AuthenticationType);
...
// other claims
...
identity.AddClaim(new Claim(ClaimTypes.Role, "admins"));
...
var ticket = new AuthenticationTicket(identity, properties);
context.Validated(ticket);
Run Code Online (Sandbox Code Playgroud)

编辑

您可以从DB获取用户角色,而不是使用"admins"编码字符串:

var roles = await userManager.GetRolesAsync(userId);
Run Code Online (Sandbox Code Playgroud)

因此,您可以在存储库中添加以下方法:

public async Task<IList<string>> UserRoles(string userId)
{
    IList<string> roles = await userManager.GetRolesAsync(userId);

    return roles;
}
Run Code Online (Sandbox Code Playgroud)

然后从覆盖的GrantResourceOwnerCredentials中调用它,添加:

using (AuthRepository repository = new AuthRepository())
{
    IdentityUser user = await repository.FindUser(context.UserName, context.Password);

    if (user == null)
    {
        context.SetError("invalid_grant", "The user name or password is incorrect");
        return;
    }

    var roles = repository.UserRoles(user.Id);
}
Run Code Online (Sandbox Code Playgroud)