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 ...
随机推荐
- Session管理之ThreadLocal
ref=toolbar" target="_blank">ref=toolbar_logo" target="_blank"> ...
- ExtJS学习--------Ext.Element中其它操作方法学习
(1)对齐操作 (2)尺寸操作 (3)定位操作 (4)滚动操作 (5)经常使用事件方法
- UVA-10163 Storage Keepers DP
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem ...
- Delphi中SendMessage使用说明(所有消息说明) good
Delphi中SendMessage使用说明 SendMessage基础知识 函数功能:该函数将指定的消息发送到一个或多个窗口.此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回.而函数Po ...
- go4--break,continue + 标签
package main /* 指针 Go虽然保留了指针,但与其它编程语言不同的是,在Go当中不 支持指针运算以及”->”运算符,而直接采用”.”选择符来操作指针 目标对象的成员 操作符”&am ...
- java8-接口变化-默认方法-静态方法
Java 8中允许接口中包含具有具体实现的方法,该方法称为 “默认方法”,默认方法使用 default 关键字修饰. default String getName(){ return "哈哈 ...
- CANopen——笔记
1. c语言的typedef高级用法 typedef void (*post_sync_t)(CO_Data*); http://zhidao.baidu.com/link?url=_lDBGq_uk ...
- [RK3288][Android6.0] 调试笔记 --- Goodix GT9和GT9F区别【转】
本文转载自:http://blog.csdn.net/kris_fei/article/details/78341425 Platform: RK3288 OS: Android 6.0 Kernel ...
- 4.4 Top-Down Parsing
4.4 Top-Down Parsing Top-down parsing can be viewed as the problem of constructing a parse tree for ...
- 第五周 Leetcode 99. Recover Binary Search Tree (HARD)
Leetcode99 给定一个 二叉搜索树,其中两个节点被交换,写一个程序恢复这颗BST. 只想到了时间复杂度O(n)空间复杂度O(h) h为树高的解法,还没想到空间O(1)的解法. 交换的情况只有两 ...