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 ...
随机推荐
- tesnorflow Conv2DTranspose
tensorflow/python/layers/convolutional.py # Infer the dynamic output shape: out_height = utils.decon ...
- go17---并发
yjf512 · 2015-02-21 11:09:07 · 1076 次点击 · 预计阅读时间 2 分钟 · 大约1分钟之前 开始浏览 这是一个创建于 2015-02-21 11:09:07 ...
- java操作linux,调用shell命令
import org.junit.jupiter.api.Test; import java.io.BufferedReader; import java.io.IOException; import ...
- missing required source folder
Eclipse 中XXX is missing required source folder 问题的解决 https://blog.csdn.net/itzhangdaopin/article/det ...
- SVN主干与分支的合并 ***
下面我将step by step地演示如何一次完整的branching和merging,包括创建分支.分支开发.分支和主线同步,分支合并到主线的全过程,甚至包括如何在本地创建一个测试用的reposit ...
- 不温不火WindowsPhone
最近在考虑是否转其他平台,如iOS或者Android或者javascript等. 已经以Windows Phone 开发作为工作就一年了(也不算是真正的Windows Phone开发吧,仅仅是开发高德 ...
- 学生表、课程表、 成绩表 、教师表sql练习
转自:http://yuncode.net/code/c_58df7a8ca687e58 1.查询“1”课程比“2”课程成绩高的所有学生的学号: SELECT t1.student_id FROM ...
- 例题 5-1 STL
Raju and Meena love to play with Marbles. They have got a lot of marbles with numbers written on the ...
- linux 定义变量 ,添加变量值
1.设置值$name=test2. 输出变量的值 echo $echo $name3. 增加变量内容PATH=$PATH:/home/bin/testPATH="$PATH":/h ...
- 最大流增广路(KM算法) HDOJ 1533 Going Home
题目传送门 /* 最小费用流:KM算法是求最大流,只要w = -w就可以了,很经典的方法 */ #include <cstdio> #include <cmath> #incl ...