Ocelot 认证与授权
Ocelot 认证与授权
目前项目接口都是公开的,没有经过任何的认证,只要知道接口的调用方法,任何人都可以随意调用,因此,很容易就造成信息泄露或者服务被攻击。
需要在Ocelot中接入IdentityServer4的认证与授权。
IdentityServer4使用
NETCORE - IdentityServer4 身份认证 ,可参考:https://www.cnblogs.com/1285026182YUAN/p/15250347.html
IdentityServer4有多种认证模式,包括用户密码、客户端等等,我这里只需要实现IdentityServer4的验证过程即可,因此,我选择了使用最简单的客户端模式。
首先我们来看,当没有Ocelot网关时系统是如何使用IdentityServer4进行认证的。
客户端需要先想IdentityServer请求认证,获得一个Token,然后再带着这个Token向下游服务发出请求。
一. IdentityServer服务端
创建IdentityServer服务端
1. 创建项目 :IdentityServer
框架:netcore web api
2. 增加 nuget 包:IdentityServer4
3. 配置文件:appsettings.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" }
}, "SSOConfig": { "ApiResources": [ { "Name": "identityAPIService", "DisplayName": "identityAPIServiceName" } ], "Clients": [ { "ClientId": "mark", "ClientSecrets": [ "markjiang7m2" ], "AllowedGrantTypes": "ClientCredentials", "AllowedScopes": [ "identityAPIService" ] } ] }, "AllowedHosts": "*" }
ApiResources
为数组类型,表示IdentityServer管理的所有的下游服务列表
-
Name: 下游服务名称
-
DisplayName: 下游服务别名
Clients
为数组类型,表示IdentityServer管理的所有的上游客户端列表
-
ClientId: 客户端ID
-
ClientSecrets: 客户端对应的密钥
-
AllowedGrantTypes: 该客户端支持的认证模式,目前支持如下:
-
Implicit
-
ImplicitAndClientCredentials
-
Code
-
CodeAndClientCredentials
-
Hybrid
-
HybridAndClientCredentials
-
ClientCredentials
-
ResourceOwnerPassword
-
ResourceOwnerPasswordAndClientCredentials
-
DeviceFlow
-
AllowedScopes: 该客户端支持访问的下游服务列表,必须是在
ApiResources
列表中登记的
4. 创建配置文件类:SSOConfig,用于读取配置文件。
using IdentityServer4.Models; using Microsoft.Extensions.Configuration; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace IdentityServer { public class SSOConfig { private IConfigurationSection section; public SSOConfig(IConfiguration Configuration) { section = Configuration.GetSection("SSOConfig"); } public IEnumerable<IdentityResource> GetIdentityResources() { return new List<IdentityResource> { new IdentityResources.OpenId(), new IdentityResources.Profile() }; } public IEnumerable<ApiResource> GetApiResources() { List<ApiResource> resource = new List<ApiResource>(); if (section != null) { List<ApiConfig> configs = new List<ApiConfig>(); section.Bind("ApiResources", configs); foreach (var config in configs) { resource.Add(new ApiResource(config.Name, config.DisplayName) { Scopes = { config.Name } }); } } return resource.ToArray(); } /// <summary> /// 定义受信任的客户端 Client /// </summary> /// <returns></returns> public IEnumerable<Client> GetClients() { List<Client> clients = new List<Client>(); if (section != null) { List<ClientConfig> configs = new List<ClientConfig>(); section.Bind("Clients", configs); foreach (var config in configs) { Client client = new Client(); client.ClientId = config.ClientId; List<Secret> clientSecrets = new List<Secret>(); foreach (var secret in config.ClientSecrets) { clientSecrets.Add(new Secret(secret.Sha256())); } client.ClientSecrets = clientSecrets.ToArray(); GrantTypes grantTypes = new GrantTypes(); var allowedGrantTypes = grantTypes.GetType().GetProperty(config.AllowedGrantTypes); client.AllowedGrantTypes = allowedGrantTypes == null ? GrantTypes.ClientCredentials : (ICollection<string>)allowedGrantTypes.GetValue(grantTypes, null); client.AllowedScopes = config.AllowedScopes.ToArray(); clients.Add(client); } } return clients.ToArray(); } public IEnumerable<ApiScope> GetApiScopes() { var apiScopes = new List<ApiScope>(); List<ApiConfig> configs = new List<ApiConfig>(); section.Bind("ApiResources", configs); var scopes = configs.Select(t => { return t.Name; }).ToList(); scopes.ForEach(t => { apiScopes.Add(new ApiScope(t)); }); return apiScopes; } } public class ApiConfig { public string Name { get; set; } public string DisplayName { get; set; } } public class ClientConfig { public string ClientId { get; set; } public List<string> ClientSecrets { get; set; } public string AllowedGrantTypes { get; set; } public List<string> AllowedScopes { get; set; } } }
5. 服务注册:startup.cs
public void ConfigureServices(IServiceCollection services) { var ssoConfig = new SSOConfig(Configuration); services.AddIdentityServer()//Ids4服务 .AddDeveloperSigningCredential()//添加开发人员签名凭据 .AddInMemoryIdentityResources(ssoConfig.GetIdentityResources())//添加内存apiresource .AddInMemoryApiResources(ssoConfig.GetApiResources()) .AddInMemoryApiScopes(ssoConfig.GetApiScopes()) .AddInMemoryClients(ssoConfig.GetClients());//把配置文件的client配置资源放到内存 services.AddControllers(); services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "IdentityServer", Version = "v1" }); }); }
中间件使用
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); app.UseSwagger(); app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "IdentityServer v1")); } app.UseHttpsRedirection(); app.UseRouting(); app.UseIdentityServer(); app.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
修改端口号为:8005
配置完成,启动项目后,调用接口获取 token 。
二. 下游服务认证配置
项目:OService1
增加 nuget 包, IdentityServer4.AccessTokenValidation
在appsettings.json
中加入IdentityServer服务信息
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft": "Warning", "Microsoft.Hosting.Lifetime": "Information" } }, "IdentityServerConfig": { "ServerIP": "localhost", "ServerPort": 8005, "IdentityScheme": "Bearer", "ResourceName": "identityAPIService" }, "AllowedHosts": "*" }
这里的identityAPIService
就是在IdentityServer服务端配置ApiResources
列表中登记的其中一个下游服务。
在Startup.cs
中读取IdentityServer服务信息,加入IdentityServer验证
引用:http://letyouknow.net/ocelot/ocelot-tutorial-4.html
项目:https://gitee.com/wuxincaicai/ocelothost.git