快速入門介紹了使用IdentityServer保護API的最基本方案。 我們將定義一個API和一個想要訪問它的客戶端。 客戶端將通過提供 在IdentityServer請求訪問令牌, 充當客戶端和IdentityServer都知道的秘密,並且它將使用該令牌來訪問API。 9.1設置ASP.NET核心 ...
快速入門介紹了使用IdentityServer保護API的最基本方案。 我們將定義一個API和一個想要訪問它的客戶端。 客戶端將通過提供ClientCredentials
在IdentityServer請求訪問令牌,ClientCredentials
充當客戶端和IdentityServer都知道的秘密,並且它將使用該令牌來訪問API。
9.1設置ASP.NET核心應用程式
首先為應用程式創建一個目錄 - 然後使用我們的模板創建一個包含基本IdentityServer設置的ASP.NET Core應用程式,例如:
md quickstart
cd quickstart
md src
cd src
dotnet new is4empty -n IdentityServer
這將創建以下文件:
- IdentityServer.csproj- 項目文件和Properties\launchSettings.json文件
- Program.cs和Startup.cs- 主要的應用程式入口點
- Config.cs - IdentityServer資源和客戶端配置文件
您現在可以使用自己喜歡的文本編輯器來編輯或查看文件。如果您希望獲得Visual Studio支持,可以添加如下解決方案文件:
cd ..
dotnet new sln -n Quickstart
然後讓它添加你的IdentityServer項目(記住這個命令,因為我們將在下麵創建其他項目):
dotnet sln add .\src\IdentityServer\IdentityServer.csproj
註意
此模板中使用的協議是http
,當在Kestrel
上運行時,埠設置為5000
或IISExpress
上的隨機埠。您可以在Properties\launchSettings.json
文件中更改它。但是,所有快速入門指令都假定您使用Kestrel
上的預設埠以及http
協議,該協議足以進行本地開發。
9.2 定義API資源
API是您要保護的系統中的資源。
資源定義可以通過多種方式載入,模板使用“代碼作為配置”appproach。在Config.cs文件中,您可以找到一個名為GetApisAPI 的方法,如下所示:
public static IEnumerable<ApiResource> GetApis()
{
return new List<ApiResource>
{
new ApiResource("api1", "My API")
};
}
9.3 定義客戶端
下一步是定義可以訪問此API的客戶端。
對於此方案,客戶端將不具有互動式用戶,並將使用IdentityServer的所謂客戶端密鑰進行身份驗證。將以下代碼添加到Config.cs文件中:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{
new Client
{
ClientId = "client",
// no interactive user, use the clientid/secret for authentication
AllowedGrantTypes = GrantTypes.ClientCredentials,
// secret for authentication
ClientSecrets =
{
new Secret("secret".Sha256())
},
// scopes that client has access to
AllowedScopes = { "api1" }
}
};
}
9.4 配置IdentityServer
在Startup.cs
載入資源和客戶端定義 - 模板已經為您執行此操作:
public void ConfigureServices(IServiceCollection services)
{
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients());
// rest omitted
}
就是這樣 - 如果您運行伺服器並瀏覽瀏覽器 http://localhost:5000/.well-known/openid-configuration
,您應該會看到所謂的發現文檔。客戶端和API將使用它來下載必要的配置數據。
首次啟動時,IdentityServer將為您創建一個開發人員簽名密鑰,它是一個名為的文件tempkey.rsa
。您不必將該文件檢入源代碼管理中,如果該文件不存在,將重新創建該文件。
9.5 添加API
接下來,為您的解決方案添加API。
您可以使用Visual Studio中的ASP.NET Core Web API(或空)模板,也可以使用.NET CLI來創建API項目。從src
文件夾中運行以下命令:
dotnet new web -n Api
然後通過運行以下命令將其添加到解決方案中:
cd ..
dotnet sln add .\src\Api\Api.csproj
將API應用程式配置為http://localhost:5001
僅運行。您可以通過編輯Properties文件夾中的launchSettings.json
文件來完成此操作。將應用程式URL設置更改為:
"applicationUrl": "http://localhost:5001"
9.6 控制器
在API項目中添加一個新文件夾Controllers和一個新控制器IdentityController
:
[Route("identity")]
[Authorize]
public class IdentityController : ControllerBase
{
[HttpGet]
public IActionResult Get()
{
return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
}
}
這個控制器將在後面被用於測試授權需求,同時通過API的眼睛(瀏覽工具)來可視化身份信息。
9.7 配置
最後一步是將身份驗證服務添加到DI和身份驗證中間件到管道。這些將:
- 驗證輸入的令牌以確保它來自可信任的發佈者(IdentityServer)
- 驗證令牌是否可用於該 api(也就是 Scope)。
將Startup
更新為如下所示:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvcCore()
.AddAuthorization()
.AddJsonFormatters();
services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "http://localhost:5000";
options.RequireHttpsMetadata = false;
options.Audience = "api1";
});
}
public void Configure(IApplicationBuilder app)
{
app.UseAuthentication();
app.UseMvc();
}
}
AddAuthentication
將身份驗證服務添加到DI並配置"Bearer"
為預設方案。 UseAuthentication
將身份驗證中間件添加到管道中,以便在每次調用主機時自動執行身份驗證。
http://localhost:5001/identity
在瀏覽器上導航到控制器應返回401狀態代碼。這意味著您的API需要憑證,現在受IdentityServer保護。
9.8 創建客戶端
最後一步是編寫請求訪問令牌的客戶端,然後使用此令牌訪問API。為此,在您的解決方案中添加一個控制台項目,請記住在以下位置創建它src:
dotnet new console -n Client
然後和以前一樣,使用以下方法將其添加到您的解
cd ..
dotnet sln add .\src\Client\Client.csproj
打開Program.cs並將內容從這裡複製到它。
客戶端程式非同步調用Main
方法以運行非同步http
調用。 從C#7.1
開始,此功能可用,一旦您編輯Client.csproj以將以下行添加為PropertyGroup
,它就可用:
<LangVersion>latest</LangVersion>
IdentityServer的令牌端點實現OAuth 2.0協議,您可以使用原始HTTP來訪問它。但是,我們有一個名為IdentityModel
的客戶端庫,它將協議交互封裝在易於使用的API中。
將IdentityModel
NuGet包添加到您的客戶端。這可以通過Visual Studio的nuget對話框,手動添加到Client.csproj文件,或使用CLI來完成:
dotnet add package IdentityModel
IdentityModel包括用於發現端點的客戶端庫。這樣您只需要知道IdentityServer的基地址 - 可以從元數據中讀取實際的端點地址:
// discover endpoints from metadata
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync("http://localhost:5000");
if (disco.IsError)
{
Console.WriteLine(disco.Error);
return;
}
接下來,您可以使用發現文檔中的信息向IdentityServer請求令牌以訪問api1:
// request 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;
}
Console.WriteLine(tokenResponse.Json);
註意
將訪問令牌從控制台複製並粘貼到https://jwt.io/以檢查原始令牌。
9.9 調用
要將訪問令牌發送到API,通常使用HTTP Authorization
標頭。這是使用SetBearerToken
擴展方法完成的:
// call api
var client = new HttpClient();
client.SetBearerToken(tokenResponse.AccessToken);
var response = await client.GetAsync("http://localhost:5001/identity");
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
}
else
{
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(JArray.Parse(content));
}
輸出應如下所示:
註意
預設情況下,訪問令牌將包含有關範圍(scope),生命周期(nbf和exp),客戶端ID(client_id)和頒發者名稱(iss)的聲明。
9.10 進一步的實驗
本演練重點介紹了迄今為止的成功之路
- 客戶端能夠請求令牌
- 客戶端可以使用令牌來訪問API
你現在可以嘗試引發一些錯誤來學習系統的相關行為,比如:
- 嘗試在未運行時連接到IdentityServer(不可用)
- 嘗試使用無效的客戶端ID或密碼來請求令牌
- 嘗試在令牌請求期間請求無效範圍
- 嘗試在API未運行時調用API(不可用)
- 不要將令牌發送到API
- 將API配置為需要與令牌中的範圍不同的範圍