IdentityServer 基于scope给接口做授权,实现多范围


前言

接了一个要针对具体的接口进行权限限制,但我刚接触IdentityServer没多长时间,理解了简单的授权和验证操作。只会在管道中添加认证处理程序,只能限制单范围访问请求。不得不开始新的学习。

实现

?本文采用的客户端授权模式。在identityServer授权服务器端,我们会配置ApiResource、Client、ApiScope等内容。

public static IEnumerable GetApis()
{
    return new List
    {
        new ApiResource("api1", "My API"){ 
            Scopes = { "AK47", "channel" }
        },
    };
}

public static IEnumerable GetClients()
{
    return new List
    {
        new Client
        {
            ClientId = "client",
            AllowedGrantTypes = GrantTypes.ClientCredentials,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = { "AK47" }
        },
        new Client
        {
            ClientId = "client1",
            AllowedGrantTypes = GrantTypes.ClientCredentials,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            AllowedScopes = { "channel" }
        }
    };
}

public static IEnumerable GetScopes()
{
    return new List
    {
        new ApiScope("AK47", "My API"),
        new ApiScope("channel", "My API"),
    };
}

IdentityServer需要在Startup.cs中进行注册中间件。比较简单,就不写了(不会随便找一篇文章就有)
在ASP.NET Core WebApi的Start.up中注册服务和配置认证处理。

services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
        //指向identityServer授权服务器端地址
        options.Authority = "http://localhost:5000";
        options.RequireHttpsMetadata = false;
        //指向ApiResource中的"api1"资源,限制Scopes
        //为"AK47"或"channel"才能访问范围能的接口
        options.ApiName = "api1";
    });

//通过“授权策略系统”实现多范围
services.AddAuthorization(options =>
    {
        options.AddPolicy("Channel",builder => 
        {
            //需要Scope包含"channel",才能通过
            builder.RequireScope("channel");
        });
    });

通过“授权策略系统”实现多范围,可以创建多个Policy,就能实现基于Scope划分多个范围作用域了。

第一个[Authorize],限制Scope需要为“AK47”或“channel”才能访问Controller。
第二个[Authorize(Policy = "Channel")],限制Scope为“channel”才能访问Post接口。

[Authorize]
[ApiController]
[Route("api/[controller]")]
public class IdentityController : Controller
{
    [HttpGet]
    [Route("GetInfo")]
    public IActionResult Get()
    {
        return new JsonResult(new { Name = "旺強" });
    }

    [HttpPost]
    [Route("PostInfo")]
    [Authorize(Policy = "Channel")]
    public IActionResult Post()
    {
        return new JsonResult(new { Name = "旺強" });
    }
}

扩展 and与or 的关系

services.AddAuthorization(options =>
{
    options.AddPolicy("myPolicy", builder =>
    {
        // require scope1
        builder.RequireScope("scope1");
        // and require scope2 or scope3
        builder.RequireScope("scope2", "scope3");
    });
});

参考资料

https://github.com/thinksjay/IdentityServer4/blob/master/第三部分 主题/第29章 保护API.md
https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/policies?view=aspnetcore-5.0