ocelot+consul+identity4的使用demo
Ocelot网关搭建
- 搭建core控制台项目 本demo采用2.1版本 命名为APPIGateWay
- 在Nuget包中添加Ocelot引用 选用8.0.0版本
- 添加Ocelot.json 文件 内容为:
{
"ReRoutes": [
{
"DownstreamPathTemplate": "/api/{url}",//下游地址万能模板
"DownstreamScheme": "http",
//下游地址以及端口号
//配置多个是为了实现负载均衡功能
//注:最好使用IP 而不是localhost
"DownstreamHostAndPorts": [
{
"Host": "192.168.1.100",
"Port":
},
{
"Host": "192.168.1.100",
"Port":
}
],
"UpstreamPathTemplate": "/api/{url}",//上游地址万能模板
"UpstreamHttpMethod": [ "Get", "POST" ],//转发的请求类型
"LoadBalancer": "LeastConnection",//负载均衡模式
//服务名称 需要和consul中配置的服务名称一致
"ServiceName": "TestService",
"UseServiceDiscovery": true,//是否启用服务发现
//身份验证 所需属性 不验证可去除
"AuthenticationOptions": {
"AuthenticationProviderKey": "usergateway",//自定义key
"AllowScopes": [ "TestService" ]//服务名称
}
},
//下面为身份验证服务配置
{
"DownstreamPathTemplate": "/connect/token",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "192.168.1.100",
"Port":
}
],
"UpstreamPathTemplate": "/connect/token",
"UpstreamHttpMethod": [ "Get", "POST" ],
"LoadBalancer": "LeastConnection",
"ServiceName": "IdentityService",
"UseServiceDiscovery": true,
"AuthenticationOptions": {
}
}
],
//Ocelot全局配置
"GlobalConfiguration": {
"BaseUrl": "http://192.168.1.100:5000",//对外地址
//服务发现地址配置
"ServiceDiscoveryProvider": {
"Host": "192.168.1.100",
"Port": } }
}
- 修改Program.cs
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System; namespace APPIGateWay
{
class Program
{
static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, builder) =>
{
builder
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
.AddJsonFile("Ocelot.json");//添加配置文件
})
.UseStartup<Startup>()
.UseUrls("http://192.168.1.100:5000")//使用指定url
.Build();
}
}
- 修改Startup.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
using System;
using System.Collections.Generic;
using System.Text; namespace APPIGateWay
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
//services.AddMvc(); -- no need MVC
// Ocelot
services.AddOcelot(Configuration);
//添加验证逻辑
services.AddAuthentication()
.AddIdentityServerAuthentication("usergateway", options => {
options.Authority = "http://192.168.1.100:5100";
options.ApiName = "TestService";
options.SupportedTokens = IdentityServer4.AccessTokenValidation.SupportedTokens.Both;
options.ApiSecret = "test";
options.RequireHttpsMetadata = false;
});
//增加日志
//.AddOpenTracing(option =>
//{
// //this is the url that the butterfly collector server is running on...
// option.CollectorUrl = "http://localhost:9618";
// option.Service = "Ocelot";
//}); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} //app.UseMvc(); -- no need MVC
// Ocelot
app.UseOcelot().Wait(); }
}
}
至此 网关部分搭建完毕
添加Consul注册帮助类
- 创建core 类库项目
- 添加以下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets; namespace ConsulRegisterHelper
{
public class NetworkHelper
{
public static string LocalIPAddress
{
get
{
UnicastIPAddressInformation mostSuitableIp = null;
var networkInterfaces = NetworkInterface.GetAllNetworkInterfaces(); foreach (var network in networkInterfaces)
{
if (network.OperationalStatus != OperationalStatus.Up)
continue;
var properties = network.GetIPProperties();
if (properties.GatewayAddresses.Count == )
continue; foreach (var address in properties.UnicastAddresses)
{
if (address.Address.AddressFamily != AddressFamily.InterNetwork)
continue;
if (IPAddress.IsLoopback(address.Address))
continue;
return address.Address.ToString();
}
} return mostSuitableIp != null
? mostSuitableIp.Address.ToString()
: "";
}
} public static int GetRandomAvaliablePort(int minPort = , int maxPort = )
{
Random rand = new Random();
while (true)
{
int port = rand.Next(minPort, maxPort);
if (!IsPortInUsed(port))
{
return port;
}
}
} private static bool IsPortInUsed(int port)
{
IPGlobalProperties ipGlobalProps = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipsTCP = ipGlobalProps.GetActiveTcpListeners(); if (ipsTCP.Any(p => p.Port == port))
{
return true;
} IPEndPoint[] ipsUDP = ipGlobalProps.GetActiveUdpListeners();
if (ipsUDP.Any(p => p.Port == port))
{
return true;
} TcpConnectionInformation[] tcpConnInfos = ipGlobalProps.GetActiveTcpConnections();
if (tcpConnInfos.Any(conn => conn.LocalEndPoint.Port == port))
{
return true;
} return false;
}
}
}
NetworkHelper.cs
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using System; namespace ConsulRegisterHelper
{
public static class AppBuilderExtensions
{
public static IApplicationBuilder RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime, ServiceEntity serviceEntity)
{
var consulClient = new ConsulClient(x => x.Address = new Uri($"http://{serviceEntity.ConsulIP}:{serviceEntity.ConsulPort}"));//请求注册的 Consul 地址
var httpCheck = new AgentServiceCheck()
{
DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(),//服务启动多久后注册
Interval = TimeSpan.FromSeconds(),//健康检查时间间隔,或者称为心跳间隔
HTTP = $"http://{serviceEntity.IP}:{serviceEntity.Port}{serviceEntity.HealthUrl}",//健康检查地址
Timeout = TimeSpan.FromSeconds()
}; // Register service with consul
var registration = new AgentServiceRegistration()
{
Checks = new[] { httpCheck },
ID = Guid.NewGuid().ToString(),
Name = serviceEntity.ServiceName,
Address = serviceEntity.IP,
Port = serviceEntity.Port,
Tags = new[] { $"urlprefix-/{serviceEntity.ServiceName}" }//添加 urlprefix-/servicename 格式的 tag 标签,以便 Fabio 识别
}; consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册,内部实现其实就是使用 Consul API 进行注册(HttpClient发起)
lifetime.ApplicationStopping.Register(() =>
{
consulClient.Agent.ServiceDeregister(registration.ID).Wait();//服务停止时取消注册
}); return app;
}
}
}
Register.cs
using System;
using System.Collections.Generic;
using System.Text; namespace ConsulRegisterHelper
{
public class ServiceEntity
{
public ServiceEntity()
{
HealthUrl = "/api/health";
}
/// <summary>
/// 服务IP
/// </summary>
public string IP { get; set; }
/// <summary>
/// 服务端口号
/// </summary>
public int Port { get; set; }
/// <summary>
/// 服务名称
/// </summary>
public string ServiceName { get; set; }
/// <summary>
/// 服务发现地址
/// </summary>
public string ConsulIP { get; set; }
/// <summary>
/// 服务发现端口号
/// </summary>
public int ConsulPort { get; set; }
/// <summary>
/// 健康检查地址默认为/api/health
/// </summary>
public string HealthUrl { get; set; }
}
}
ServiceEntity.cs
至此帮助类搭建完毕 该帮助类主要是为了方便服务注册使用
身份验证服务搭建
- 新建空web core项目 命名IdentityService
- 下载Quickstart 发布版放入
- 添加配置文件 appsettings.json
{
"Service": {
"Name": "IdentityService",
"Port": ""
},
"Consul": {
"IP": "localhost",
"Port": ""
},
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Warning"
}
},
"Console": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
appsettings.json
- 添加健康检查控制器
- 添加以下文件
using IdentityServer4.Models;
using IdentityServer4.Test;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; namespace IdentityService
{
//测试使用内容
public class InMemoryConfiguration
{
public static IConfiguration Configuration { get; set; }
/// <summary>
/// Define which APIs will use this IdentityServer
/// </summary>
/// <returns></returns>
public static IEnumerable<ApiResource> GetApiResources()
{
return new[]
{
new ApiResource("TestService", "测试服务1"),
new ApiResource("TestService2", "测试服务2")
};
} /// <summary>
/// Define which Apps will use thie IdentityServer
/// </summary>
/// <returns></returns>
public static IEnumerable<Client> GetClients()
{
return new[]
{
new Client
{
ClientId = "c1",
ClientSecrets = new [] { new Secret("secret1".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = new [] { "TestService", "TestService2" }
},
new Client
{
ClientId = "c-low",
ClientSecrets = new [] { new Secret("clowsecret".Sha256()) },
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
AllowedScopes = new [] { "TestService" }
}
};
}
}
}
InMemoryConfiguration.cs
using IdentityServer4.Models;
using IdentityServer4.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks; namespace IdentityService
{
public class ProfileService : IProfileService
{
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var claims = context.Subject.Claims.ToList();
context.IssuedClaims = claims.ToList();
} public async Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = true;
}
}
}
ProfileService.cs
using IdentityServer4.Models;
using IdentityServer4.Validation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks; namespace IdentityService
{
public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
//ToDo:验证自定义用户
//LoginUser loginUser = null;
bool isAuthenticated = context.UserName=="aaa"&&context.Password==""? true :false; //loginUserService.Authenticate(context.UserName, context.Password, out loginUser);
if (!isAuthenticated)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "账户名密码错误");
}
else
{
context.Result = new GrantValidationResult(
subject: context.UserName,
authenticationMethod: "custom",
claims: new Claim[] {
new Claim("Name", context.UserName),
new Claim("Id", ""),
new Claim("RealName", ""),
new Claim("Email", "")
}
);
}
return Task.CompletedTask;
}
}
}
ResourceOwnerPasswordValidator.cs
- 修改以下文件
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging; namespace IdentityService
{
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
} public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseUrls("http://192.168.1.100:5100")
.Build();
}
}
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ConsulRegisterHelper;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.PlatformAbstractions; namespace IdentityService
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{ services.AddMvc();
InMemoryConfiguration.Configuration = this.Configuration;
services.AddIdentityServer()
.AddDeveloperSigningCredential()//开发临时证书
.AddInMemoryClients(InMemoryConfiguration.GetClients())
.AddInMemoryApiResources(InMemoryConfiguration.GetApiResources())
.AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()//添加自定义验证
.AddProfileService<ProfileService>();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
// authentication
app.UseMvc();
app.UseIdentityServer();
//启用UI
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
// register this service
app.RegisterConsul(lifetime, new ServiceEntity
{
IP = NetworkHelper.LocalIPAddress,
Port = Convert.ToInt32(Configuration["Service:Port"]),
ServiceName = Configuration["Service:Name"],
ConsulIP = Configuration["Consul:IP"],
ConsulPort = Convert.ToInt32(Configuration["Consul:Port"])
});
}
}
}
Startup.cs
身份验证服务搭建完毕
测试服务搭建
- 创建TestService1 模板为coreAPi
- 引用之前创建的ConsulRegisterHelper
- 添加HealthController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc; namespace TestService1.Controllers
{
[Route("api/[controller]")]
public class HealthController : Controller
{
// GET api/values
[HttpGet]
public string Get()
{
return "ok";
}
}
}
- 修改Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime lifetime)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseMvc();
// register this service
app.RegisterConsul(lifetime, new ServiceEntity
{
IP = NetworkHelper.LocalIPAddress,
Port = Convert.ToInt32(Configuration["Service:Port"]),
ServiceName = Configuration["Service:Name"],
ConsulIP = Configuration["Consul:IP"],
ConsulPort = Convert.ToInt32(Configuration["Consul:Port"])
});
}
搭建完毕
其他服务类似于此服务
搭建完毕后可用http://localhost:5000/connect/token 访问获取token
需要传入 这些参数。
获取到token后 可访问 http://localhost:5000/api/values 获取方法内容
需要在headers中加入 Authorization 并附上定义的前缀+空格+token 即可请求到数据
附上结果图
参考博客:
微服务系列博客
https://www.cnblogs.com/edisonchou/p/dotnetcore_microservice_foundation_blogs_index.html
token权限控制
https://www.cnblogs.com/jaycewu/p/7791102.html
Ocelot+identity
http://www.cnblogs.com/liyouming/p/9025084.html
ocelot+consul+identity4的使用demo的更多相关文章
- .net core Ocelot Consul 实现API网关 服务注册 服务发现 负载均衡
大神张善友 分享过一篇 <.NET Core 在腾讯财付通的企业级应用开发实践>里面就是用.net core 和 Ocelot搭建的可扩展的高性能Api网关. Ocelot(http:// ...
- 【微服务No.4】 API网关组件Ocelot+Consul
介绍: Ocelot是一个.NET API网关.该项目针对的是使用.NET运行微服务/面向服务架构的人员,他们需要一个统一的入口进入他们的系统.然而,它可以处理任何说HTTP并在ASP.NET Cor ...
- 负载均衡之Ocelot+Consul(配置文件注册服务)
继上篇 Ocellot 做负载均衡之后,本篇将记录 Ocelot + Consul 试验如何做服务发现和服务注册. 服务发现和服务注册的背景知识,一搜满街都是. 在此,我还是写下自己对这个术语的理解吧 ...
- 负载均衡之Ocelot+Consul(WebAPI注册服务)
上一篇 负载均衡之Ocelot+Consul(文件配置注册服务),介绍了如何通过json文件注册服务,本篇将学习如何通过web api 注册服务. 在展开学习过程之前,且先总结一下 consul服 ...
- Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网关Ocelot+Consul
相关文章 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-Consul服务注册,服务发现 Consul+Ocelot+Polly在.NetCore中使用(.NET5)-网 ...
- Ocelot + Consul的demo
参考大佬的博客写的:https://www.cnblogs.com/alan-lin/p/9126155.html:也可以参考这篇博客:https://www.cnblogs.com/axzxs200 ...
- Ocelot + Consul的demo(二)集群部署
把服务A和服务B接口分别部署在两个ip地址上 修改 services.json文件, { "encrypt": "7TnJPB4lKtjEcCWWjN6jSA==&quo ...
- Ocelot + Consul + Registrator 基于Docker 实现服务发现、服务自动注册
目录 1. Consul集群搭建 1.1 F&Q Consul官方推荐的host网络模式运行 2. Registrator服务注册工具 2.1 F&Q Registrator悬挂服务 ...
- Ocelot + Consul实践
关于Consul(https://www.consul.io)是一个分布式,高可用,支持多数据中心的服务发现和配置共享的服务软件,由 HashiCorp 公司用 Go 语言开发, 基于 Mozilla ...
随机推荐
- union关键字及大小端模式
1. union 关键字 union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在 union 中所有的数据成员共用一个空间,同一时间只能储存其中一个数据成员,所有 ...
- JavaScriptSerializer 序列号datatime时少了8小时
有人说主要的因素是在于JSON格式不直接支持日期和时间. 简单一点处理办法是ToLocalTime()一下:dt = dt.ToLocalTime(); 参考http://blog.csdn.net/ ...
- 一些Razor语法
Layout asp.net mvc中的一些子视图忽然不行了,点击主视图后发现没有弹出来. 通过浏览器调试,发现打开子视图时,加载了大量的JS,CSS等.真奇怪啊,这些都是在主视图加载的啊,怎么子视图 ...
- 如何遍历newtonsoft.json的JObject里的JSON数据
这种问题,在网上搜,居然没有答案,又是一堆垃圾,连谷歌上都搜不到.老实说,我喜欢这边的工作环境,可以上谷歌,毕竟是大公司,有自己的VPN .某组织整天禁这个禁那个,去年居然连谷歌都禁了,丧心病狂至此, ...
- ios19---xib
// // ViewController.m #import "ViewController.h" @interface ViewController () @end @imple ...
- Java的Graphics中drawImage与drawLine的坐标区别
drawImage复制的区域是 dx1 <= x < dx2,dy1 <= y < dy2 drawLine绘制区域是 dx1 <= x <= dx2,dy1 &l ...
- 美国诚实签经验——IMG全球医疗险,TODO
那么,诚实签最关键的4个要点 是什么呢? 第一,证明你有一定的经济实力. 可能需要房产.存款等证明,也需要银行信用卡或借记卡半年流水证明(让人信服的每月进帐和消费能力). 这些是为了证明,你可以支付在 ...
- 使用JS准确获取URL网址中参数的几种方法
记录下使用JS准确获取URL网址中参数的方法: 参考链接1. https://blog.csdn.net/Zhihua_W/article/details/54845945?utm_source=bl ...
- PCB 圆形板切边算法 实现
在工程CAM处理圆形拼板是个头疼的问题,需人工程师自行设计切边 满足可以拼板并且拼板后锣板板边没有内角,不然会影响装配 1.原始单 PCS圆形板 此外形如果不采用邮票孔连接的话,采V-CUT连接须采用 ...
- E2017E0605-hm
carbon copy 抄送, 抄写与送达 blind carbon copy 密送 blind adj. 失明的; 盲目的,轻率的; contact n. 接触; 触点 v 联系,接触; ...