官方配图
Client Credentials
但其实Client不需要考虑用户,因此此处也不需要考虑测试用户的代码
官方案例,最好的参考资料永远在官方
https://github.com/IdentityServer/IdentityServer4
1.配置授权服务器
在Identity Server中配置Clinet和资源信息
public static IEnumerable<Client> Clients =>
new List<Client>
{
// machine to machine client
new Client
{
ClientId = "client",
ClientSecrets = { new Secret("secret".Sha256()) },
// 客户端模式
AllowedGrantTypes = GrantTypes.ClientCredentials,
// scopes that client has access to
AllowedScopes = { "api1" }
},
}
修改 Startup,添加 Authentication 服务,并将 Authentication 中间件添加到管道中
var builder = services.AddIdentityServer()
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
//与 OAuth 相比,OIDC(OpenID Connect) 中的 scopes 不仅代表 API,还代表了诸如 用户id、用户名 或 邮箱地址等身份数据。
.AddInMemoryIdentityResources(Config.IdentityResources);
builder.AddDeveloperSigningCredential();
这里说一下ApiScopes新版的类已经变成了new ApiScope,不是老版的ApiResource,没看最新官方文档的我吃了很多的亏
public static IEnumerable<ApiScope> ApiScopes =>
new List<ApiScope>
{
new ApiScope("api1", "My API")
};
2.配置资源服务器
// accepts any access token issued by identity server
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:49363";(IdentityServer的访问地址)
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateAudience = false
};
});
// adds an authorization policy to make sure the token is for scope 'api1'
services.AddAuthorization(options =>
{
options.AddPolicy("ApiScope", policy =>
{
// policy.RequireAuthenticatedUser();
policy.RequireClaim("scope", "api1");
});
});
// 给每个控制器都加上限制
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers()
.RequireAuthorization("ApiScope");
});
写一个测试方法
[HttpGet]
public IActionResult Get()
{
return new JsonResult(
from c in User.Claims select new { c.Type, c.Value });
}
3.在客户端调用
static async Task Main(string[] args)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:49363/");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
// 获取token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "client",
ClientSecret = "secret",
Scope = "api1"
});
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
var apiClient = new HttpClient();
// 通过设置token来获取受保护资源的方法
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("https://localhost:5007/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
Console.ReadKey();
}