目錄
前言:
- 由於是保護客戶端,所以使用的授權類型爲客戶端憑證(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();
}