IdentityServer4基于角色的授权

时间:2016-11-28 12:25:51

标签: asp.net-mvc asp.net-core identityserver4

我正在尝试使用IdentityServer4实现“基于角色的授权”,以根据用户角色访问我的API。

例如,我想为用户提供两个角色,即FreeUser和PaidUser,并希望通过授权属性使用[Authorize(Roles =“FreeUser”))]来访问API,请帮助我,怎么能我实现了这个目标。

我有以下解决方案结构:

  1. IdentityServer
  2. 的WebAPI
  3. Javascript客户端
  4. 我已经注册了我的Javascript客户端,如下所示:

     new Client
                {
                    ClientId = "js",
                    ClientName = "javascript client",
                    AllowedGrantTypes = GrantTypes.Implicit,
                    AllowAccessTokensViaBrowser= true,
                    RedirectUris = {"http://localhost:5004/callback.html"},
                    PostLogoutRedirectUris = {"http://localhost:5004/index.html"},
                    AllowedCorsOrigins = {"http://localhost:5004"},
    
                    AllowedScopes =
                    {
                        StandardScopes.OpenId.Name,
                        StandardScopes.Profile.Name,
                        "api1",
                        "role",
                        StandardScopes.AllClaims.Name
                    }
                }
    

    作用域

     return new List<Scope>
            {
                StandardScopes.OpenId,
                StandardScopes.Profile,
    
                new Scope
                {
                    Name = "api1",
                    Description = "My API"
                },
               new Scope
               {
                   Enabled = true,
                   Name  = "role",
                   DisplayName = "Role(s)",
                   Description = "roles of user",
                   Type = ScopeType.Identity,
                   Claims = new List<ScopeClaim>
                   {
                       new ScopeClaim("role",false)
                   }
               },
               StandardScopes.AllClaims
            };
    

    用户

     return new List<InMemoryUser>
            {
                new InMemoryUser
                {
                    Subject = "1",
                    Username = "alice",
                    Password = "password",
    
                    Claims = new List<Claim>
                    {
                        new Claim("name", "Alice"),
                        new Claim("website", "https://alice.com"),
                        new Claim("role","FreeUser")
                    }
                },
                new InMemoryUser
                {
                    Subject = "2",
                    Username = "bob",
                    Password = "password",
    
                    Claims = new List<Claim>
                    {
                        new Claim("name", "Bob"),
                        new Claim("website", "https://bob.com"),
                        new Claim("role","PaidUser")
                    }
                }
            };
    

    WebApi Startup.cs

      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();
    
    
            JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
            app.UseCors("default");
            app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
            {
                Authority = "http://localhost:5000",
                ScopeName = "api1",
                //  AdditionalScopes = new List<string> { "openid","profile", "role" },
                RequireHttpsMetadata = false
            });
    
            app.UseMvc();
        }
    

    Web Api控制器

    namespace Api.Controllers
    {
     [Route("[controller]")]
    
    public class IdentityController : ControllerBase
    {
        [HttpGet]
        [Authorize(Roles = "PaidUser")]
        public IActionResult Get()
        {
            return new JsonResult(from c in User.Claims select new { c.Type,    c.Value });
        }
    
        [Authorize(Roles = "FreeUser")]
        [HttpGet]
        [Route("getfree")]
        public IActionResult GetFreeUser()
        {
            return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
        }
    }
    }
    

    Javascript客户端app.js 在这里,我尝试通过IdentityServer登录用户并发出API请求。

    var mgr = new Oidc.UserManager(config);
    mgr.getUser().then(function (user) {
    if (user) {
        log("User logged in", user.profile);
    } else {
        log("User is not logged in.");
    }
    });
    
    function login() {
      mgr.signinRedirect();
     }
    
    function api() {
    mgr.getUser().then(function (user) {
        var url = "http://localhost:5001/identity/getfree";
    
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = function () {
            log(xhr.status, JSON.parse(xhr.responseText));
        };
    
        xhr.setRequestHeader("Authorization", "Bearer " + user.access_token);
        xhr.send();
      });
     }
    
     function logout() {
       mgr.signoutRedirect();
     }
    

    登录流程正常,我可以成功登录,我可以在访问令牌中收到该角色。

    enter image description here

    当我通过单击按钮(Call Api)向API发出请求时,我收到以下错误.. enter image description here

3 个答案:

答案 0 :(得分:11)

鉴于您没有为javascript客户端提供配置对象,我假设您的范围配置如下。

scope:"openid profile api1 role"

我认为您的问题的主要原因是您的访问令牌中不包含角色声明。

按如下方式将角色声明添加到api1范围,以将其包含在访问令牌中。

             new Scope
                {
                    Name = "api1",
                    DisplayName = "API1 access",
                    Description = "My API",
                    Type = ScopeType.Resource,
                    IncludeAllClaimsForUser = true,
                    Claims = new List<ScopeClaim>
                    {
                        new ScopeClaim(ClaimTypes.Name),
                        new ScopeClaim(ClaimTypes.Role)
                    }
                }

您可以在此处阅读我的答案,以帮助调试问题。 implementing roles in identity server 4 with asp.net identity

完整的工作解决方案就在这里。 https://github.com/weliwita/IdentityServer4.Samples/tree/40844310

答案 1 :(得分:5)

products.Sort((left, right) => { if (left.Price >= lower && left.Price <= upper) if (right.Price >= lower && right.Price <= upper) // both within range return direction == "asc" ? left.Price.CompareTo(right.Price) : -left.Price.CompareTo(right.Price) else return -1; // left within, right without range else if (right.Price >= lower && right.Price <= upper) return 1; // left without, right within range else return 0; // both left and right are without the range (arbitrary order) }); 更改为new Claim("role","FreeUser")

或者创建这样的政策:

new Claim(ClaimTypes.Role, "FreeUser")

并使用它:

services.AddAuthorization(options =>
{
    options.AddPolicy("FreeUser", policy => policy.RequireClaim("role", "FreeUser"));
});

答案 2 :(得分:1)

我在这篇文章上写了一个样本

Identity Server 4: adding claims to access token

我已经使用角色测试并声称我还可以在客户端网络应用和API应用中使用[授权(角色=&#34; SuperAdmin,管理员&#34;)]。