【IdentityServer4】分模块保护Api(4.x)
IdentityServer4
(下文统称Ids4
)官方已经从v3
更新升级到了v4
版本,最核心也最重要的一个更新,就是新增了ApiResourceScopes
表,进一步细化了对资源服务器的限制粒度。之前我们是一个客户端只能针对一个资源服务器来操作,那该资源服务器下的所有api都会被保护,当然也都会被控制。所以是面向整个ApiResources的。
但是现在做了细化以后,一个资源服务器可以分隔出多个作用域Scope,那这样的话,我们就可以定义多个客户端,分模块的去访问同一个统一的资源服务器。如:client1只有权限读订单信息,没有写订单权限,可以将Order.WebApi
API划分两个scope:Order.Read
、Order.Write
,权限校验需要在资源服务器中自己去实现。
Ids4
1、Config
public static class Config
{
public static IEnumerable<IdentityResource> IdentityResources=> new IdentityResource[]
{
new IdentityResources.OpenId()
};
// Defining an API Resource
public static IEnumerable<ApiResource> Apis =>
new List<ApiResource>{
new ApiResource("Order.WebApi", "订单服务"){
Scopes=new[]{ "Order.Read","Order.Write" }
},
new ApiResource("Product.WebApi", "产品服务")
};
//4.x新增ApiScope
public static IEnumerable<ApiScope> GetApiScopes=>new[] { new ApiScope("Order.Read") , new ApiScope("Order.Write") };
// Defining Client
public static IEnumerable<Client> Clients =>
new List<Client> {
new Client
{
//没有交互式用户,使用clientid/secret进行身份验证
AllowedGrantTypes=GrantTypes.ClientCredentials,
ClientId="client",
ClientSecrets={new Secret("secret".Sha256())},
//客户端可以访问的范围
AllowedScopes={ "Order.Read", "Order.Write" }
}
};
}
2、注册服务
builder.Services.AddIdentityServer()
.AddDeveloperSigningCredential()//在每次启动时,为令牌签名创建了一个临时密钥。在生成环境需要一个持久化的密钥。
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.GetApiScopes)//4.x新增
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients);
资源服务器
1、添加认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
//.AddIdentityServerAuthentication()
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, option =>
{
option.Authority = "http://localhost:5000";
option.RequireHttpsMetadata = false;
option.Audience = "Order.WebApi";
});
2、添加中间件
app.UseAuthentication();
app.UseAuthorization();
3、添加授权策略
builder.Services.AddAuthorization(options =>
{
#region 订单权限策略
//读权限
options.AddPolicy("ReadOrder", builder =>
{
//客户端Scope中包含Order.Read才能访问
builder.RequireClaim("scope", "Order.Read");
});
//写权限
options.AddPolicy("WriteOrder", builder =>
{
//客户端Scope中包含Order.Write才能访问
builder.RequireClaim("scope", "Order.Write");
});
#endregion
});
4、接口指定策略
[ApiController]
[Route("[controller]")]
public class OrderController : ControllerBase
{
[HttpGet]
[Authorize(Policy = "ReadOrder")]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
[HttpPost]
[Authorize(Policy = "WriteOrder")]
public IActionResult Post()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
客户端
// 仅申请了读订单权限,所有只能调用资源服务器中`ReadOrder`授权策略的接口,如果调用Post接口,会返回403
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "Order.Read"
}) ;
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("http://localhost:5001/order");
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了