使用角色授权属性不起作用?

时间:2014-11-10 15:23:34

标签: c# asp.net asp.net-mvc asp.net-web-api oauth

我试图让这个工作,但到目前为止没有运气。我的Authorize属性可以自行运行,但是一旦我声明了一个用户必须分开的角色,那么我从webapi返回以下消息

{"message":"Authorization has been denied for this request."}

Startup.cs

public void Configuration(IAppBuilder app)
{
    //HttpConfiguration config = new HttpConfiguration();

    ConfigureOAuth(app);

    // simple injector
    SimpleInjectorConfig.Register();

    AutoMapperConfig.RegisterMappings();
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
}

public void ConfigureOAuth(IAppBuilder app)
{
    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString("/token"),
        AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
        Provider = new SimpleAuthorizationServerProvider(new AccountService(new DataContext()))
    };

    // Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

}

SimpleAuthorizationServerProvider.cs

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
{
    private AccountService _service;

    public SimpleAuthorizationServerProvider(AccountService service)
    {
        _service = service;
    }

    public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
    }


    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        User user = await _service.FindUserAsync(context.UserName, context.Password);

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


        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("sub", context.UserName));
        //identity.AddClaim(new Claim("role", "user"));

        context.Validated(identity);

    }
}

装饰控制器方法,我使用

[Authorize(Roles="CanViewCompany")]

如果我只使用它,它可以工作并返回我期望的数据

[Authorize]

我的基本用户类

public class User : IdentityUser<long, UserLogin, UserRole, UserClaim>, IUser<long>
{
    public User()
        : base()
    {
        this.Groups = new HashSet<UserGroup>();
    }

    public virtual ICollection<UserGroup> Groups { get; set; }

}

我确信我错过了一些东西,但我不确定是什么。任何帮助非常感谢

3 个答案:

答案 0 :(得分:3)

似乎这个函数导致了错误。我没有设置用户名(它没有让它中断,但是User属性没有一个,我相信将来我还需要它。)

此外,我没有添加任何角色。我不确定这是否是解决此问题的正确方法,但它确实有效。

如果有人知道更好/正确的方法,请告诉我。

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        User user = await _service.FindUserAsync(context.UserName, context.Password);

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

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
        identity.AddClaim(new Claim(ClaimTypes.Role, "CanViewCompany"));
        identity.AddClaim(new Claim(ClaimTypes.Role, "CanAddCompany"));
        identity.AddClaim(new Claim(ClaimTypes.Role, "CanEditCompany"));
        identity.AddClaim(new Claim(ClaimTypes.Role, "CanDeleteCompany"));

        context.Validated(identity);

    }

答案 1 :(得分:1)

如果您有更新的角色,则无法扩展,您需要动态创建此角色,请检查my answer此SO问题,该问题与您的案例非常相似,但请检查您如何从DB获取用户角色对它们进行硬编码,您目前正在做的是为所有经过身份验证的用户分配相同的角色,这是没有意义的。

我想这段代码来自http://bitoftech.net有关授权的帖子,如果是这种情况,那么请删除下面的LOC,这对您的情况也没有意义。

 identity.AddClaim(new Claim("sub", context.UserName));

答案 2 :(得分:0)

我认为你的aproach有点问题。任何用户都将拥有所有角色......

我的解决方案如下:

1)通过CreateIdentityAsync函数获取声明数组:

    var claims = await _service.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

2)将claim数组添加到标识对象:

identity.AddClaims(claims.Claims);

一起显示代码......

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {

        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });

        User user = await _service.FindUserAsync(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }
        var claims = await _service.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);

        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaims(claims);

        context.Validated(identity);
    }

这就是全部。