1 構(gòu)建IdentityServer4 服務(wù)
1.1 通過配置類配置類(Config)實例化IdentityServer4中間件
using IdentityServer4.Models;
namespace BuilderServer
{
///
/// 【配置--類】
///
/// 摘要:
///??? 通過該中類的方法成員,對過“IdentityServer4”中間件進行配置設(shè)定,并根據(jù)這些配置設(shè)定。實例化“IdentityServer4”服務(wù)。
/// 說明:
///???? 配置數(shù)據(jù)最好定義在“appsettings.json”文件中,而非直接嵌入定義在該配置類。
///
///
public static class Config
{
///
/// 【獲取標識資源數(shù)組】
///
/// 摘要:
///??? 獲取認證用戶的多個證件單元(Claims:包含:如用戶ID、賬戶、電子郵件地址等)實例,并把這些實例存儲到數(shù)組實例中,為通過“IdentityServer4”中間件實現(xiàn)身份認證服務(wù)提供數(shù)據(jù)支撐。
///
///
/// 返回:
///??? 數(shù)組實例,該數(shù)組實例中存儲著多個證件單元(Claims:包含:如用戶ID、賬戶、電子郵件地址等)實例。
///
///
public static IEnumerable
{
return new IdentityResource[]
{
???? new IdentityResources.OpenId(),
???? new IdentityResources.Profile(),
};
}
///
/// 【獲取作用數(shù)組】
///
/// 摘要:
///??? 獲取序中的Api控制器方法分類實例,并把這些實例存儲到數(shù)組實例中,為通過“IdentityServer4”中間件實現(xiàn)身份認證服務(wù)提供數(shù)據(jù)支撐。
/// 應用場景:
///???? 在由于前端版本迭代,而需要更新Api控制器方法時,為了兼容舊的前端就需要“Api版本”控制在不修改舊的Api控制器方法,而是定義新的Api控制器方法,來解決前端版本迭代的兼容性問題。
///
///
/// 返回:
????///??? 數(shù)組實例,該數(shù)組實例中存儲著Api控制器方法分類的多個實例。
///
///
public static IEnumerable GetApiScopeArray()
{
return new ApiScope[]
{
???? new ApiScope("api1"),
};
}
///
/// 【獲取客戶端數(shù)組】
///
/// 摘要:
///??? 通過“IdentityServer4”中間件,實例化多個客戶端實例(客戶端通過1個指定的客戶端實例獲取Token),并把實例存儲到數(shù)組實例中。
///
///
/// 返回:
///??? 數(shù)組實例,該數(shù)組實例中存儲著多個客戶端實例(客戶端通過1個指定的客戶端實例獲取Token)。
///
///
public static IEnumerable
{
return new Client[]
{
???? //客戶端以“client_credentials”方式獲取獲取Token。
???? new Client
???? {
???????? ClientId = "ClientCredential",
???????? ClientName = "客戶端憑證認證",
???????? //grant_type:ClientCredential
??????????//Postman->Body->x-www-form-urlencoded參數(shù):
???????? //client_id:ClientCredential
???????? //client_secret:511536EF-F270-4058-80CA-1C89C192F69A
???????? //grant_type:client_credentials
???????? AllowedGrantTypes = GrantTypes.ClientCredentials,
???????? ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
???????? AllowedScopes = { "api1" },
???????? AccessTokenLifetime = 120 //過期時間=2分鐘,默認值:3600秒=1小時。
???? },
????? //客戶端以“password”方式獲取獲取Token。
???? new Client
???? {
???????? ClientId = "PasswordClient",
???????? ClientName = "客戶端密碼認證",
???????? //grant_type:password
???????? //Postman->Body->x-www-form-urlencoded參數(shù):
???????? //client_id:PasswordClient
???????? //client_secret:511536EF-F270-4058-80CA-1C89C192F69A
???????? //grant_type:password
???????? //username:zz
???????? //password :123456,
???????? AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
???????? ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) },
???????? AllowedScopes = { "api1" },
???????? AccessTokenLifetime = 120 //過期時間=2分鐘,默認值3600秒=1小時。
???? },
? };
}
}
}
1.2 為“IdentityServer4”服務(wù)添加測試性用戶
using IdentityModel;
using IdentityServer4.Test;
using IdentityServer4;
using System.Security.Claims;
using System.Text.Json;
namespace BuilderServer
{
///
/// 【測試用戶--類】
///
/// 摘要:
///??? 通過該類中的方法成員,獲取測試用戶類的多個實例,并把實例存儲到列表實例中,為測試指定用戶通過“IdentityServer4”服務(wù)獲取Token,測試性的用戶。
///
///
public class TestUsers
{
///
/// 【獲取客戶列表】
///
/// 摘要:
///??? 獲取測試用戶類的多個實例,并把實例存儲到列表實例中,為測試指定用戶通過“IdentityServer4”服務(wù)獲取Token,測試性的用戶。
///
///
/// 返回:
///??? 列表實例,該列表實例中存儲著測試用戶類的多個實例。
///
///
public static List
{
var address = new
{
???? street_address = "金水區(qū)",
???? locality = "鄭州",
???? postal_code = 69118,//郵編。
???? country = "中國"
};
//把測試用戶類的多個實例存儲到列表實例中,為測試指定用戶通過“IdentityServer4”服務(wù)獲取Token,測試性的用戶。
return new List
{
???? new TestUser
???? {
???????? SubjectId = "1",
???????? Username = "zz",
???????? Password = "123456",
???????? //通過證件單元,構(gòu)建整個證件。
???????? Claims =
???????? {
???????????? new Claim(JwtClaimTypes.Name, "zz"),
???????????? new Claim(JwtClaimTypes.Email, "zz@email.com"),
???????????? new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
???????????? new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
???????? }
???? }
};
}
}
}
1.3 重構(gòu)Program類
//通過配置類中的數(shù)據(jù)實例,實例化過“IdentityServer4”中間件,最后把過“IdentityServer4”中間件依賴注入到內(nèi)置容器中,實現(xiàn)當前程序據(jù)這些配置設(shè)定,實例化“IdentityServer4”服務(wù)。
builder.Services.AddIdentityServer()
?.AddTestUsers(TestUsers.GetUserList())//為“IdentityServer4”服務(wù)添加測試性用戶。
?.AddInMemoryIdentityResources(Config.GetIdentityResourceArray()) // 為“IdentityServer4”服務(wù)添加測試性用戶。
?.AddInMemoryApiScopes(Config.GetApiScopeArray())//指定客戶端所調(diào)用Api控件器方法的作用域(版本)
?.AddInMemoryClients(Config.GetClientArray())//1個指定的客戶端實例獲取Token的認證方式。
?.AddDeveloperSigningCredential();//臨時生成的證書證書。
var app = builder.Build();
// 把“IdentityServer4”管道中間件集成到.Net7框架內(nèi)置管道中,以實現(xiàn)前程序?qū)Α癐dentityServer4”服務(wù)的支持。
app.UseIdentityServer();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
? app.UseSwagger();
? app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
//把內(nèi)置授權(quán)管道中間件集成到.Net7框架內(nèi)置管道中。
//注意:
//內(nèi)置授權(quán)管道中間件必須集成在“IdentityServer4”服務(wù)程序中,否則在使用Postman調(diào)試經(jīng)過認證特性標記的Api控制器方法時會出現(xiàn):“401Unauthorized”錯誤。
app.UseAuthentication();
1.4 通過Postman測試IdentityServer4服務(wù)
2 通過“IdentityServer4.AccessTokenValidation”中間件獲取IdentityServer4服務(wù)所發(fā)送的“JwtBearer”令牌(Token)實例
2.1 TestController控制器
using IdentityModel.Client;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace AccessToken.Controllers
{
///
/// 【登錄管Api控制器--類--無認證特性標記】
///
///
/// 摘要:
///???? 通過該類中的方法成員,用于對IdentityServer4服務(wù)驗證。
///
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
///
/// 【Swagger登錄--無認證特性標記】
///
///
/// 摘要:
///???? 獲取通過IdentityServer4服務(wù)所發(fā)送的“JwtBearer”令牌(Token)實例的字符串值。
///
///
/// 返回:
///??? 令牌(Token)實例的字符串值。
///
[HttpGet("GetToken")]
public async Task
{
//獲取IdentityServer4服務(wù)中的客戶端實例。
var client = new HttpClient();
var config = new DiscoveryDocumentRequest()
{
???? Address = "https://localhost:44360/",
???? Policy = new DiscoveryPolicy() { RequireHttps = false }
};? //忽略IP或域名時Https請求
var disco = await client.GetDiscoveryDocumentAsync(config);
//根據(jù)IdentityServer4服務(wù)中的客戶端實例,獲取“JwtBearer”令牌(Token)實例。
var tokenResponse = await client.RequestClientCredentialsTokenAsync(
???? new ClientCredentialsTokenRequest
???? {
???????? Address = disco.TokenEndpoint,
???????? ClientId = "ClientCredential",
???????? ClientSecret = "511536EF-F270-4058-80CA-1C89C192F69A",
???????? Scope = "api1",
???? });
if (tokenResponse.IsError)
????????{
???? return tokenResponse.Error;
}
//返回“JwtBearer”令牌(Token)實例的字符串值。
return tokenResponse.AccessToken;
}
///
/// 【Swagger登錄--有認證特性標記】
///
///
/// 摘要:
///??? 在通過IdentityServer4服務(wù)所發(fā)送的“JwtBearer”令牌(Token)實例認證并授權(quán)后,獲取當前Api方法的實例值。
///
///
/// 返回:
///??? 當前Api方法的實例值。
///
[Authorize("api1")]
[HttpGet("GetValue")]
public IEnumerable
{
return new string[] { "value1", "value2" };
}
}
}
2.2 重構(gòu)Program類
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using System.Reflection;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
//通過“IdentityServer4.AccessTokenValidation”中間件,把“JwtBearer”中間件注入.Net7框架內(nèi)置容器中,
builder.Services.AddAuthentication("Bearer")
? .AddIdentityServerAuthentication(options =>
? {
? options.Authority = "https://localhost:44360/";//鑒權(quán)(認證)服務(wù)地址
? options.RequireHttpsMetadata = false;
? //緩沖過期時間,“JwtBearer”令牌(Token)的總有效時間等于該時間加上jwt的過期時間,緩沖過期時間的默認值為“5分鐘”,
? //當前把緩沖過期時間設(shè)定為:0,指定令牌(Token)的總有效時間即為jwt的過期時間。
? //注意:
? //如果不設(shè)定“JwtBearer”緩沖過期時間設(shè)定為:0,即在IdentityServer4服務(wù)中的時間(120秒之后)過期后,經(jīng)過認證特性標記的Api控制器方法依然可以獲取其值,因為還“5分鐘”的緩沖過期。
? options.JwtValidationClockSkew = TimeSpan.FromSeconds(0);
? });
//通過.Net7框架內(nèi)置認證中間件,把"api1"策略注入.Net7框架內(nèi)置容器中,
builder.Services.AddAuthorization(option =>
{
? option.AddPolicy("Api1", builder =>
? {
? builder.RequireAuthenticatedUser();
? builder.RequireClaim("scope", "api1");
? });
});
//通過AddSwaggerGen依賴注入中間,獲取Api控制器方法的版本控制信息和注釋等數(shù)據(jù)信息,依賴注入.Net7框架的內(nèi)置容器中,為在“index.html”頁面上渲染顯示這些信息,作好預處理操作。
builder.Services.AddSwaggerGen(options =>
{
? options.SwaggerDoc("v1", new OpenApiInfo { Title = "IdentityServer4.AccessTokenValidation", Version = "v1" });
? //獲取"AccessToken.xml"文件的文件名。
? string _xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
? //獲取"SecondPracticeServer.xml"文件的絕對路徑。
? string _xmlFilePath = Path.Combine(AppContext.BaseDirectory, _xmlFileName);
? //把控件器行為方法中的注釋信息加載到"Swagger/index.html"頁面中的控件器行為方法進行渲染顯示。
? options.IncludeXmlComments(_xmlFilePath, true);
});
var app = builder.Build();
app.UseSwagger();
app.UseSwaggerUI();
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
2.3 通過Postman驗證“IdentityServer4”服務(wù)及其授權(quán)
2.3.1 先通過Postman獲取“JwtBearer”令牌(Token)
2.3.2 通過Headers授權(quán)認證特性標記的Api控制器方法
2.3.3通過Authorization授權(quán)認證特性標記的Api控制器方法
3 通過“IdentityModel”中間件獲取IdentityServer4服務(wù)所發(fā)送的“JwtBearer”令牌(Token)實例
1、通過Nuget引用:IdentityModel包。
2、通過Nuget引用:Microsoft.AspNetCore.Authentication.JwtBearer包。
3.1 重構(gòu)Program類
//通過“Microsoft.AspNetCore.Authentication.JwtBearer”中間件,把“JwtBearer”中間件注入.Net7框架內(nèi)置容器中,
builder.Services.AddAuthentication("Bearer")
? .AddJwtBearer("Bearer", options =>
? {
? options.Authority = "https://localhost:44360/";
? options.RequireHttpsMetadata = false;
? options.TokenValidationParameters = new TokenValidationParameters
? {
? //指示是否對指定令牌(Token)的過期時間進行限定,當前設(shè)定為:true,即限定。
? RequireExpirationTime = true,
? //指示是否對指定令牌(Token)的生命周期進行自動管理,當前設(shè)定為:true,即管理,
? //當前指定令牌(Token)的生命周期結(jié)束時,程序必須重新生成1個新的指定令牌(Token)才能方法授權(quán)頁面。
? //使用當前時間與Token的Claims中的NotBefore和Expires對比后,進行管理。
? ValidateLifetime = true,
? //緩沖過期時間,“JwtBearer”令牌(Token)的總有效時間等于該時間加上jwt的過期時間,緩沖過期時間的默認值為“5分鐘”,
? //當前把緩沖過期時間設(shè)定為:0,指定令牌(Token)的總有效時間即為jwt的過期時間。
? //注意:
? //如果不設(shè)定“JwtBearer”緩沖過期時間設(shè)定為:0,即在IdentityServer4服務(wù)中的時間(120秒之后)過期后,經(jīng)過認證特性標記的Api控制器方法依然可以獲取其值,因為還“5分鐘”的緩沖過期。
? ClockSkew = TimeSpan.FromSeconds(0),
? };
? });
//通過.Net7框架內(nèi)置認證中間件,把"api1"策略注入.Net7框架內(nèi)置容器中,
builder.Services.AddAuthorization(option =>
{
? option.AddPolicy("Api1", builder =>
? {
? builder.RequireAuthenticatedUser();
? builder.RequireClaim("scope", "api1");
? });
});
//通過AddSwaggerGen依賴注入中間,獲取Api控制器方法的版本控制信息和注釋等數(shù)據(jù)信息,依賴注入.Net7框架的內(nèi)置容器中,為在“index.html”頁面上渲染顯示這些信息,作好預處理操作。
builder.Services.AddSwaggerGen(options =>
{
? options.SwaggerDoc("v1", new OpenApiInfo { Title = "IdentityServer4.AccessTokenValidation", Version = "v1" });
? //獲取"AccessToken.xml"文件的文件名。
? string _xmlFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
? //獲取"SecondPracticeServer.xml"文件的絕對路徑。
? string _xmlFilePath = Path.Combine(AppContext.BaseDirectory, _xmlFileName);
? //把控件器行為方法中的注釋信息加載到"Swagger/index.html"頁面中的控件器行為方法進行渲染顯示。
? options.IncludeXmlComments(_xmlFilePath, true);
});
3.2 通過Postman驗證“IdentityServer4”服務(wù)及其授權(quán)
同上
4 注意:
4.1 啟動
把所有項目的啟動方式修改為:“IIS Express”
4.2 設(shè)定“JwtBearer”令牌(Token)緩沖過期時間為:0
4.2.1 通過“IdentityServer4.AccessTokenValidation”中間件設(shè)定
//通過“IdentityServer4.AccessTokenValidation”中間件,把“JwtBearer”中間件注入.Net7框架內(nèi)置容器中,
builder.Services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = "https://localhost:44360/";//鑒權(quán)(認證)服務(wù)地址
options.RequireHttpsMetadata = false;
//緩沖過期時間,“JwtBearer”令牌(Token)的總有效時間等于該時間加上jwt的過期時間,緩沖過期時間的默認值為“5分鐘”,
//當前把緩沖過期時間設(shè)定為:0,指定令牌(Token)的總有效時間即為jwt的過期時間。
//注意:
//如果不設(shè)定“JwtBearer”緩沖過期時間設(shè)定為:0,即在IdentityServer4服務(wù)中的時間(120秒之后)過期后,經(jīng)過認證特性標記的Api控制器方法依然可以獲取其值,因為還“5分鐘”的緩沖過期。
options.JwtValidationClockSkew = TimeSpan.FromSeconds(0);
});
4.2.2 通過“Microsoft.AspNetCore.Authentication.JwtBearer”中間件設(shè)定
//通過“Microsoft.AspNetCore.Authentication.JwtBearer”中間件,把“JwtBearer”中間件注入.Net7框架內(nèi)置容器中,
builder.Services.AddAuthentication("Bearer")
.AddJwtBearer("Bearer", options =>
{
options.Authority = "https://localhost:44360/";
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters
{
//指示是否對指定令牌(Token)的過期時間進行限定,當前設(shè)定為:true,即限定。
RequireExpirationTime = true,
//指示是否對指定令牌(Token)的生命周期進行自動管理,當前設(shè)定為:true,即管理,
//當前指定令牌(Token)的生命周期結(jié)束時,程序必須重新生成1個新的指定令牌(Token)才能方法授權(quán)頁面。
//使用當前時間與Token的Claims中的NotBefore和Expires對比后,進行管理。
ValidateLifetime = true,
//緩沖過期時間,“JwtBearer”令牌(Token)的總有效時間等于該時間加上jwt的過期時間,緩沖過期時間的默認值為“5分鐘”,
//當前把緩沖過期時間設(shè)定為:0,指定令牌(Token)的總有效時間即為jwt的過期時間。
//注意:
//如果不設(shè)定“JwtBearer”緩沖過期時間設(shè)定為:0,即在IdentityServer4服務(wù)中的時間(120秒之后)過期后,經(jīng)過認證特性標記的Api控制器方法依然可以獲取其值,因為還“5分鐘”的緩沖過期。
ClockSkew = TimeSpan.FromSeconds(0),
};
});
4.3 內(nèi)置授權(quán)管道中間件必須集成在“IdentityServer4”服務(wù)程序中
內(nèi)置授權(quán)管道中間件必須集成在“IdentityServer4”服務(wù)項目中,否則在使用Postman調(diào)試經(jīng)過認證特性標記的Api控制器方法時會出現(xiàn):“401Unauthorized”錯誤,如下圖所示。
對以上功能更為具體實現(xiàn)和注釋見:221204_10IdentityServer4(初識IdentityServer4)。
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
本文題目:第11章初識IdentityServer4-創(chuàng)新互聯(lián)
瀏覽地址:http://www.rwnh.cn/article46/pcshg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站、Google、網(wǎng)站策劃、搜索引擎優(yōu)化、電子商務(wù)、網(wǎng)站改版
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)