目录
前言:
- 由于是保护客户端,所以使用的授权类型为客户端凭证(ClientCredentials)。
- 这篇博文的前提是已经安装了IdentityServer4的官方模板,安装官方模板在命令行中执行
dotnet new -i IdentityServer4.Templates
即可,前提是你已经安装了 .NET Core2.1+ 的版本。
一、创建项目
创建项目时用的命令:
$ mkdir Tutorial-Plus
$ cd Tutorial-Plus
$ mkdir src
$ cd src
$ dotnet new api -n Api
$ dotnet new is4inmem -n IdentityServer
$ dotnet new console -n ConsoleClient
$ cd ..
$ dotnet new sln -n Tutorial-Plus
$ dotnet sln add ./src/Api/Api.csproj
$ dotnet sln add ./src/IdentityServer/IdentityServer.csproj
$ dotnet sln add ./src/ConsoleClient/ConsoleClient.csproj
按顺序运行命令整个解决方案初始化创建完毕。
解决方案中有 Api 、ConsoleClient 、 IdentityServer 三个项目。
二、IdentityServer 项目
修改 IdentityServer 项目启动端口为 5000
1) 将 json config 修改为 code config
在 IdentityServer 项目的 Startup.cs 文件的 ConfigureServices 方法中,
找到以下代码:
// in-memory, code config
//builder.AddInMemoryIdentityResources(Config.GetIdentityResources());
//builder.AddInMemoryApiResources(Config.GetApis());
//builder.AddInMemoryClients(Config.GetClients());
// in-memory, json config
builder.AddInMemoryIdentityResources(Configuration.GetSection("IdentityResources"));
builder.AddInMemoryApiResources(Configuration.GetSection("ApiResources"));
builder.AddInMemoryClients(Configuration.GetSection("clients"));
将其修改为
// in-memory, code config
builder.AddInMemoryIdentityResources(Config.GetIdentityResources());
builder.AddInMemoryApiResources(Config.GetApis());
builder.AddInMemoryClients(Config.GetClients());
// in-memory, json config
//builder.AddInMemoryIdentityResources(Configuration.GetSection("IdentityResources"));
//builder.AddInMemoryApiResources(Configuration.GetSection("ApiResources"));
//builder.AddInMemoryClients(Configuration.GetSection("clients"));
以上修改的内容为将原来卸载配置文件中的配置,改为代码配置。
2) Config.cs 修改
在 Config.cs 文件中,有 GetIdentityResources、GetApis、GetClients 三个方法。
GetIdentityResources
方法是 被保护的 IdentityResource
GetApis
方法是 被保护的 ApiResource
GetClients
方法是用来配置客户端
将 GetClients 方法修改为:
public static IEnumerable<Client> GetClients()
{
return new[]
{
// client credentials flow client
new Client
{
ClientId = "client",
ClientName = "Client Credentials Client",
AllowedGrantTypes = GrantTypes.ClientCredentials,
ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
AllowedScopes = { "api1" }
}
};
}
在上面代码中,由于我们使用的是 ClientCredentials
授权方式。
在 Client Credentials - OAuth 2.0 中写到:当应用程序请求访问令牌访问其自己的资源而不是代表用户访问时,将使用客户端凭据授予。
也就是说,ClientCredentials
授权方式不代表任何用户,不代表任何用户也就是无法访问IdentityResource
资源,
所以当定义客户端时,如果设置为ClientCredentials
授权方法,那么AllowedScopes
属性只能为GetApis
中定义的 ApiResource。
三、Api 项目
修改 Api 项目启动端口为 5001
1) 配置 Startup.cs
将 Api 项目的 Startup.cs 修改为如下。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore().AddAuthorization().AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000"; // IdentityServer的地址
options.RequireHttpsMetadata = false; // 不需要Https
options.Audience = "api1"; // 和资源名称相对应
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
}
2) IdentityController.cs 文件
将 Controllers 文件夹中的 ValuesController.cs
改名为 IdentityController.cs
,
并将其中代码修改了如下:
[Route("[controller]")]
[ApiController]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
在授权方法为 ClientCredentials 时,上面代码中的 User
指的是 客户端应用。
四、ConsoleClient 项目
1) 修改ConsoleClient.csproj 文件
将 ConsoleClient 项目中的 ConsoleClient.csproj 文件修改为如下:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="IdentityModel" Version="3.10.10" />
</ItemGroup>
</Project>
新增的<LangVersion>latest</LangVersion>
表示支持C# 7.1 特性。
新增的<PackageReference Include="IdentityModel" Version="3.10.10" />
表示安装 NuGit 包 IdentityModel。
2) 修改Program.cs 文件
修改 Program.cs 文件为:
static async Task Main(string[] args)
{
// discovery endpoint
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
// request access token
var tokenResponse = await client.RequestClientCredentialsTokenAsync(
new ClientCredentialsTokenRequest
{
Address = disco.TokenEndpoint, // Token 端点
ClientId = "client",
ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",
Scope = "api1"
});
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
// call Identity Resource API
var apiClient = new HttpClient();
apiClient.SetBearerToken(tokenResponse.AccessToken);
var response = await apiClient.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
Console.WriteLine(response.StatusCode);
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
Console.ReadKey();
}