?
一、簡(jiǎn)介?
?
?
?
?描述:微服務(wù)網(wǎng)關(guān)中,需要對(duì)訪問(wèn)的接口進(jìn)行身份校驗(yàn)后再轉(zhuǎn)發(fā)請(qǐng)求,網(wǎng)關(guān)中鑒權(quán)的方式有很多種,這里介紹的是常用的IdentityServer4鑒權(quán)添加到Ocelot網(wǎng)關(guān)中,同時(shí)下游的服務(wù)也要做身份校驗(yàn),
? ? 防止請(qǐng)求繞過(guò)網(wǎng)關(guān)直接請(qǐng)求下游服務(wù)。
二、創(chuàng)建IdentityServer4項(xiàng)目這里重點(diǎn)不是說(shuō)IdentityServer4,所以這里建一個(gè)簡(jiǎn)單的示例項(xiàng)目。
1.創(chuàng)建一個(gè)Identity4.Api項(xiàng)目
引入NugGet包
IdentityServer4
IdentityServer4.Storage
這里用的都是4.1.2版本
2.在項(xiàng)目中創(chuàng)建一個(gè)config靜態(tài)類
/// <summary>
/// 配置
/// </summary>
public class Config
{
/// <summary>
/// 定義作用域
/// </summary>
public static IEnumerable<ApiScope> ApiScopes =>
new ApiScope[]
{
new ApiScope("gatewayScope"),
new ApiScope("scope2")
};
public static IEnumerable<ApiResource> ApiResources =>
new ApiResource[]
{
new ApiResource("server1","服務(wù)1")
{
//4.x必須寫(xiě)
Scopes = { "gatewayScope" }
},
};
public static IEnumerable<Client> Clients =>
new Client[]
{
new Client
{
ClientId = "client_test",
ClientName = "測(cè)試客戶端",
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
ClientSecrets = { new Secret("secret_test".Sha256()) },
AllowedScopes = { "gatewayScope" }
},
};
/// <summary>
/// 測(cè)試的賬號(hào)和密碼
/// </summary>
/// <returns></returns>
public static List<TestUser> GetTestUsers()
{
return new List<TestUser>
{
new TestUser()
{
SubjectId = "1",
Username = "test",
Password = "123456"
}
};
}
}
?3.在Startup.cs的ConfigureServices()方法中加入
public void ConfigureServices(IServiceCollection services)
{
#region 內(nèi)存方式
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryApiResources(Config.ApiResources)
.AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes) //4.x新加
.AddTestUsers(Config.GetTestUsers());
#endregion
services.AddControllersWithViews();
}
4.在Startup.cs的Configure()方法中加入
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseIdentityServer();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
到這里一個(gè)IdentitySever4的鑒權(quán)中心就建好了,運(yùn)行起來(lái),用Postman測(cè)試獲取token。
?
?token獲取成功,說(shuō)明IdentityServer4的鑒權(quán)中心沒(méi)問(wèn)題了。
三、Ocelot中加入IdentityServer4認(rèn)證Ocelot網(wǎng)關(guān)默認(rèn)已經(jīng)集成了Id4的,我們需要做的事情有:
1.在配置中加入IdentityServer4的信息,ocelog.json中加入
{
"Routes": [
{
//轉(zhuǎn)發(fā)到下游服務(wù)地址--url變量
"DownstreamPathTemplate": "/api/{url}",
//下游http協(xié)議
"DownstreamScheme": "http",
//負(fù)載方式,
"LoadBalancerOptions": {
"Type": "RoundRobin" // 輪詢
},
//上游地址
"UpstreamPathTemplate": "/T1/{url}", //網(wǎng)關(guān)地址--url變量 //沖突的還可以加權(quán)重Priority
"UpstreamHttpMethod": [ "GET", "POST", "DELETE", "PUT" ],
"UseServiceDisConvery": true, //使用服務(wù)發(fā)現(xiàn)
"ServiceName": "api", //Consul服務(wù)名稱
//熔斷設(shè)置,熔斷器使用Polly
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 3, //允許多少個(gè)異常請(qǐng)求
"DurationOfBreak": 10000, // 熔斷的時(shí)間10s,單位為ms
"TimeoutValue": 5000 //單位ms,如果下游請(qǐng)求的處理時(shí)間超過(guò)多少則自動(dòng)將請(qǐng)求設(shè)置為超時(shí) 默認(rèn)90秒
},
//鑒權(quán)
"AuthenticationOptions": {
"AuthenticationProviderKey": "Bearer", //指定一個(gè)key
"AllowedScopes": [ "gatewayScope" ] //id4的作用域名稱
}
}
],
"GlobalConfiguration": {
//Ocelot應(yīng)用對(duì)外地址
"BaseUrl": "http://172.16.2.9:5200",
"ServiceDiscoveryProvider": {
//Consul地址
"Host": "172.16.2.84",
//Consul端口
"Port": 8500,
"Type": "Consul" //由Consul提供服務(wù)發(fā)現(xiàn),每次請(qǐng)求Consul
}
}
}
2.把Id4加入到IOC中
添加NuGet包
IdentityServer4.AccessTokenValidation
Ocelot項(xiàng)目Startup.cs中的ConfigureServices()方法加上
public void ConfigureServices(IServiceCollection services)
{
var authenticationProviderKey = "Bearer"; //這個(gè)為上面配置里的key
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(authenticationProviderKey, options =>
{
options.Authority = "http://localhost:5000";//id4服務(wù)地址
options.ApiName = "server1";//id4 api資源里的apiname
options.RequireHttpsMetadata = false; //不使用https
options.SupportedTokens = SupportedTokens.Both;
});
services.AddOcelot()
.AddConsul()
.AddPolly();
}
到這里,Ocelot網(wǎng)關(guān)配置Id4就配好了。
3.測(cè)試驗(yàn)證
先測(cè)試加了Id4后,不帶token訪問(wèn)下網(wǎng)關(guān)
?
?
?可以看到,報(bào)了401,沒(méi)權(quán)限訪問(wèn),再試一下把上面id4取到的token帶上訪問(wèn)。
?
?發(fā)現(xiàn)可以訪問(wèn)成功了。這Ocelot中加入Id4校驗(yàn)就完成了。
四、下游服務(wù)加入IdentityServer4認(rèn)證為什么下游服務(wù)要加身份校驗(yàn)?zāi)?,因?yàn)檎?qǐng)求可能繞過(guò)網(wǎng)關(guān)直接訪問(wèn)下游服務(wù),沒(méi)有驗(yàn)證就會(huì)出問(wèn)題了。
1.配置
只需要在startup.cs中的ConfigureServices中加入上面的代碼,去掉AuthenticationProviderKey
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = "http://localhost:5000";//id4服務(wù)地址
options.ApiName = "server1";//id4 api資源里的apiname
options.RequireHttpsMetadata = false; //不使用https
options.SupportedTokens = SupportedTokens.Both;
});
services.AddControllers().AddJsonOptions(cfg =>
{
cfg.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
});
services.AddSingleton<OrderService>();
}
然后在Configure()方法中,? ? app.UseRouting();后面加上? app.UseAuthentication();
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
//Consul注冊(cè)
app.UseConsul(Configuration);
}
?
然后在要校驗(yàn)的地方加上[Authorize]
?
?
2.校驗(yàn)不帶token直接訪問(wèn)下游服務(wù)
?
?顯示沒(méi)權(quán)限,再試帶上token直接訪問(wèn)下游服務(wù)。
?
?
?
?很好,成功訪問(wèn),然后再試下通過(guò)網(wǎng)關(guān)訪問(wèn)是否能正常訪問(wèn)。
?
也成了,全部配置完成!
?
源碼地址:??https://github.com/weixiaolong325/Ocelot-Consul-Polly-Id4.Demo??
本文摘自 :https://blog.51cto.com/u