Identity Resource
身份资源,里面的UserClaims是用户的一些属性,默认情况下,即使写再多的属性,token中也只会返回sub一个,我们需要在代码中加入
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.Apis)
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users)
.AddProfileService<ProfileService>();
// not recommended for production - you need to store your key material somewhere secure
builder.AddDeveloperSigningCredential();
然后去实现IProfileService
public class ProfileService : IProfileService
{
protected readonly TestUserStore Users;
public ProfileService(TestUserStore users)
{
Users = users;
}
public virtual Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var user = Users.FindBySubjectId(context.Subject.GetSubjectId());
if (user != null) {
//context.IssuedClaims = user.Claims.ToList();
context.IssuedClaims.AddRange(user.Claims);
}
return Task.CompletedTask;
}
public async Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = true;
}
}
这样就能将所有的claim返回在token中
有了包含claim的token可以去访问受保护的API,token中携带的不同的scope和Role,可以对同一个API server 中不同的API
进行不同的访问权限
在API在进行配置
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddAuthorization(options =>
{
options.AddPolicy("fullaccess", policy =>
policy.RequireClaim("scope", "api2.full_access"));
options.AddPolicy("readonly", policy =>
policy.RequireClaim("scope", "api2.read_only"));
});
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.Audience = "api1";
});
}
这里的policy是为了对不同的scope访问不同的api做限制,在IDS服务上可以这样配置
public static IEnumerable<ApiResource> Apis =>
new List<ApiResource>
{
new ApiResource("api1", "My API"),
new ApiResource
{
Name = "api2",
Scopes =
{
new Scope()
{
Name = "api2.full_access",
DisplayName = "Full access to API 2"
},
new Scope
{
Name = "api2.read_only",
DisplayName = "Read only access to API 2"
}
}
}
};
API的Controller如下配置
namespace Api
{
[Route("identity")]
[Authorize(Roles= "admin")]
public class IdentityController : ControllerBase
{
[Authorize(Policy = "fullaccess")]
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
[Authorize(Policy = "readonly")]
[HttpGet]
[Route("get1")]
public IActionResult Get1()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
}
[Authorize(Roles= "admin")]这样首先可以保证这个Controller只有admin才能访问
第一个API只有在token中scope为full_access的才能访问
第二个API只有在token中scope为read_only的才能访问
主要运用场景是给不同的客户端使用,但是客户端拿到token以后并不可以访问里面所有的API,做到相互隔离
参考:http://docs.identityserver.io/en/latest/topics/resources.html
https://docs.microsoft.com/zh-cn/aspnet/core/security/authorization/roles?view=aspnetcore-3.1
在Client中也有个Claims
Claims = new List<Claim>
{
new Claim(JwtClaimTypes.Role, "admin")
}
官网描述:
但其实默认情况下不会包含在access_token中,官网如下描述:
所以需要设置下这两个参数,最后解析token后发现
自动加了client_,没想好这个的使用场景
张峰AVA 发布了97 篇原创文章 · 获赞 14 · 访问量 5万+ 私信 关注