首页 文章 精选 留言 我的

精选列表

搜索[Service Mesh],共10000篇文章
优秀的个人博客,低调大师

【阿里云网站日志分析实践】通过Log Service日志服务导入MaxCompute分析

免费开通大数据服务:https://www.aliyun.com/product/odps 日志服务收集的日志除了可以被实时查询外,还可以把日志数据投递到大数据计算服务MaxCompute(原ODPS),进一步进行个性化BI分析及数据挖掘。通过日志服务投递日志数据到MaxCompute具有如下优势: 使用非常简单。用户只需要完成2步配置即可以把日志服务Logstore的日志数据迁移到MaxCompute中。 避免重复收集工作。由于日志服务的日志收集过程已经完成不同机器上的日志集中化,无需重复在不同机器上收集一遍日志数据后再导入到MaxCompute。 充分复用日志服务内的日志分类管理工作。用户可让日志服务中不同类型的日志(存在不同Logstore中)、不同Project的日志自动投递到不同的MaxCompute表格,方便管理及分析MaxC

优秀的个人博客,低调大师

使用jMeter对基于SAP ID service进行Authentication的Restful API进行并发测试

这篇文章本来Jerry只在SAP社区上写了英文版的,后来有两位做Marketing Cloud开发的德国同事,写邮件询问关于文章的更多细节,声称这种方式对他们自己的API性能测试很有用,所以我觉得还是值得用中文再写一遍。 在SAP官网api.sap.com里有大量发布的API,方便合作伙伴和客户自开发应用同SAP解决方案进行集成。 比如Jerry上个月做的一个项目,就是和国内一家专注于提供人脸识别技术解决方案的企业合作, 用户通过微信扫码从而完成人脸识别后,在用户授权的情况下,会调用SAP Marketing Cloud的contact API,生成对应的contact数据,并且将人脸识别得出的面部特征码通过Marketing Cloud扩展字段的方式一并存入contact数据中。 因为这个项目最后会在2019年6月5日于上海举行的SA

优秀的个人博客,低调大师

(5)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 熔断降级(Polly)

一、 什么是熔断降级 熔断就是“保险丝”。当出现某些状况时,切断服务,从而防止应用程序不断地尝试执行可能会失败的操作给系统造成“雪崩”,或者大量的超时等待导致系统卡死。 降级的目的是当某个服务提供者发生故障的时候,向调用方返回一个错误响应或者替代响应。举例子:调用联通接口服务器发送短信失败之后,改用移动短信服务器发送,如果移动短信服务器也失败,则改用电信短信服务器,如果还失败,则返回“失败”响应;在从推荐商品服务器加载数据的时候,如果失败,则改用从缓存中加载,如果缓存中也加载失败,则返回一些本地替代数据。 二、 Polly 简介 .Net Core 中有一个被.Net 基金会认可的库 Polly,可以用来简化熔断降级的处理。主要功能:重试(Retry);断路器(Circuit-breaker);超时检测(Timeout);缓存(Cache);降级(FallBack); 官网:https://github.com/App-vNext/Polly 介绍文章:https://www.cnblogs.com/CreateMyself/p/7589397.html Nuget安装指令:Install-Package Polly -Version 6.0.1 Polly 的策略由“故障”和“动作”两部分组成,“故障”包括异常、超时、返回值错误等情况,“动作”包括 降级(FallBack)、重试(Retry)、熔断(Circuit-breaker)等。 策略用来执行可能会有有故障的业务代码,当业务代码出现“故障”中情况的时候就执行“动作”。 由于实际业务代码中故障情况很难重现出来,所以 Polly 这一些都是用一些无意义的代码模拟出来。 Polly 也支持请求缓存“数据不变化则不重复自行代码”,但是和新版本兼容不好,而且功能局限性很大,因此这里不讲。 由于调试器存在,看不清楚 Polly 的执行过程,因此本节都用【开始执行(不调试)】 三、Polly简单使用 使用Policy的静态方法创建ISyncPolicy实现类对象,创建方法既有同步方法也有异步方法,根据自己的需要选择。下面先演示同步的,异步的用法类似。 举例:当发生ArgumentException异常的时候,执行Fallback代码。 Policy policy = Policy .Handle<ArgumentException>() //故障 .Fallback(() =>//动作 { Console.WriteLine("执行出错"); }); policy.Execute(() => {//在策略中执行业务代码 //这里是可能会产生问题的业务系统代码 Console.WriteLine("开始任务"); throw new ArgumentException("Hello world!"); Console.WriteLine("完成任务"); }); Console.ReadKey(); 如果没有被Handle处理的异常,则会导致未处理异常被抛出。 还可以用Fallback的其他重载获取异常信息: Policy policy = Policy .Handle<ArgumentException>() //故障 .Fallback(() =>//动作 { Console.WriteLine("执行出错"); },ex=> { Console.WriteLine(ex); }); policy.Execute(() => { //在策略中执行业务代码 //这里是可能会产生问题的业务系统代码 Console.WriteLine("开始任务1"); throw new ArgumentException("Hello1 world!"); Console.WriteLine("完成任务"); }); 如果Execute中的代码是带返回值的,那么只要使用带泛型的Policy<T>类即可: Policy<string> policy = Policy<string> .Handle<Exception>() //故障 .Fallback(() =>//动作 { Console.WriteLine("执行出错"); return "降级的值"; }); string value = policy.Execute(() => { Console.WriteLine("开始任务"); throw new Exception("Hello world!"); Console.WriteLine("完成任务"); return "正常的值"; }); Console.WriteLine("返回值:"+value); FallBack的重载方法也非常多,有的异常可以直接提供降级后的值。 (*)异常中还可以通过lambda表达式对异常判断“满足***条件的异常我才处理”,简单看看试试重载即可。还可以多个Or处理各种不同的异常。 (*)还可以用HandleResult等判断返回值进行故障判断等,我感觉没太大必要。 四、重试处理 Policy policy = Policy .Handle<Exception>() .RetryForever(); policy.Execute(() => { Console.WriteLine("开始任务"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("出错"); } Console.WriteLine("完成任务"); }); RetryForever()是一直重试直到成功 Retry()是重试最多一次; Retry(n) 是重试最多n次; WaitAndRetry()可以实现“如果出错等待100ms再试还不行再等150ms秒。。。。”,重载方法很多,不再一一介绍。还有WaitAndRetryForever。 五、 短路保护 Circuit Breaker 出现N次连续错误,则把“熔断器”(保险丝)熔断,等待一段时间,等待这段时间内如果再Execute 则直接抛出BrokenCircuitException异常,根本不会再去尝试调用业务代码。等待时间过去之后,再执行Execute的时候如果又错了(一次就够了),那么继续熔断一段时间,否则就恢复正常。 这样就避免一个服务已经不可用了,还是使劲的请求给系统造成更大压力。 Policy policy = Policy .Handle<Exception>() .CircuitBreaker(6,TimeSpan.FromSeconds(5));//连续出错6次之后熔断5秒(不会再去尝试执行业务代码)。 while(true) { Console.WriteLine("开始Execute"); try { policy.Execute(() => { Console.WriteLine("开始任务"); throw new Exception("出错"); Console.WriteLine("完成任务"); }); } catch(Exception ex) { Console.WriteLine("execute出错"+ex); } Thread.Sleep(500); } 其计数的范围是policy对象,所以如果想整个服务器全局对于一段代码做短路保护,则需要共用一个policy对象。 六、策略封装,包裹Warp 可以把多个ISyncPolicy合并到一起执行: policy3= policy1.Wrap(policy2); 执行policy3就会把policy1、policy2封装到一起执行。 Policy的静态方法Wrap可以把更多的policy一起封装: policy9=Policy.Wrap(policy1, policy2, policy3, policy4, policy5); 七、超时处理 这些处理不能简单的链式调用,要用到Wrap。例如下面实现“出现异常则重试三次,如果还出错就FallBack”这样是不行的 Policy policy = Policy.Handle<Exception>().Retry(3).Fallback(()=> { Console.WriteLine("执行出错"); });//这样不行,系统会直接报错 注意Wrap是有包裹顺序的,内层的故障如果没有被处理则会抛出到外层。 下面代码实现了“出现异常则重试三次,如果还出错就FallBack” Policy policyRetry = Policy.Handle<Exception>().Retry(3); //出现异常重试三次 Policy policyFallback = Policy .Handle<Exception>() .Fallback(()=> { Console.WriteLine("降级"); }); //Wrap:包裹。policyRetry在里面,policyFallback裹在外面。 //如果里面出现了故障,则把故障抛出来给外面 Policy policy = policyFallback.Wrap(policyRetry); policy.Execute(()=> { Console.WriteLine("开始任务"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("出错"); } Console.WriteLine("完成任务"); }); 运行结果: Timeout是定义超时故障,如果超时会抛出TimeoutRejectedException异常。 Policy policy = Policy.Timeout(3, TimeoutStrategy.Pessimistic);// 创建一个3秒钟(注意单位)的超时策略。 Timeout生成的Policy要和其他Policy一起Wrap使用。 超时策略一般不能直接用,而是和其他封装到一起用: Policy policy = Policy .Handle<TimeoutRejectedException>() //定义所处理的故障 .Fallback(() => { Console.WriteLine("降级"); }); policy = policy.Wrap(Policy.Timeout(2,TimeoutStrategy.Pessimistic)); policy.Execute(()=> { Console.WriteLine("开始任务"); Thread.Sleep(5000); Console.WriteLine("完成任务"); }); 执行结果: 上面的代码就是如果执行超过2秒钟,则直接Fallback。 这个的用途:请求网络接口,避免接口长期没有响应造成系统卡死。 八、Polly 的异步用法 所有方法都用Async方法即可,Handle由于只是定义异常,所以不需要异常方法: 带返回值的例子: Policy<byte[]> policy = Policy<byte[]> .Handle<Exception>() .FallbackAsync(async c => { Console.WriteLine("降级"); return new byte[0]; },async r=> { Console.WriteLine(r.Exception); }); policy = policy.WrapAsync( Policy.TimeoutAsync(2, TimeoutStrategy.Pessimistic, async(context, timespan, task) => { Console.WriteLine("timeout"); })); var bytes = await policy.ExecuteAsync(async () => { Console.WriteLine("开始任务"); HttpClient httpClient = new HttpClient(); var result = await httpClient.GetByteArrayAsync("http://static.rupeng.com/upload/chatimage/20183/07EB793A4C247A654B31B4D14EC64BCA.png"); Console.WriteLine("完成任务"); return result; }); Console.WriteLine("bytes长度"+bytes.Length); 执行结果: 没返回值的例子: Policy policy = Policy .Handle<Exception>() .FallbackAsync(async c => { Console.WriteLine("降级"); },async ex=> {//对于没有返回值的,这个参数直接是异常 Console.WriteLine(ex); }); policy = policy.WrapAsync(Policy.TimeoutAsync(3, TimeoutStrategy.Pessimistic, async(context, timespan, task) => { Console.WriteLine("timeout"); })); await policy.ExecuteAsync(async () => { Console.WriteLine("开始任务"); await Task.Delay(5000);//注意不能用Thread.Sleep(5000); Console.WriteLine("完成任务"); }); 执行结果: 注:此文章是我看杨中科老师的.Net Core微服务第二版和.Net Core微服务第二版课件整理出来的 现在的努力只是为了更好的将来,将来你一定不会后悔你现在的努力。一起加油吧!!! C#/.NetCore技术交流群:608188505欢迎加群交流 如果您认为这篇文章还不错或者有所收获,您可以点击右下角的【推荐】按钮精神支持,因为这种支持是我继续写作,分享的最大动力!

优秀的个人博客,低调大师

(3)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- Consul服务治理

Consul是注册中心,服务提供者、服务提供者、服务消费者等都要注册到Consul中,这样就可以实现服务提供者、服务消费者的隔离。 除了Consul之外,还有Eureka、Zookeeper等类似软件。 Consul就是来存储服务器名称与IP和端口对应关系的服务器 一、 consul 服务器安装 consul 下载地址 https://www.consul.io/ 墙外的网站 需要科学上网 cmd运行 consul.exe agent -dev 这是开发环境测试,生产环境要建集群,要至少一台 Server,多台 Agent (因为如果只有一台的话,如果服务死了 整个网站就出问题了) 开发环境中 consul 重启后数据就会丢失。 consul 的监控页面 http://127.0.0.1:850 consult 主要做三件事:提供服务到 ip 地址的注册;提供服务到 ip 地址列表的查询;对提供服务方的健康检查(HealthCheck); 二、 .Net Core 连接 consul 1. Nuget - > Install-Package Consul 安装Consul 2. 提供一个HealthCheck API接口 用于Consul做健康检查调用,只要返回个结果就可以 不论是什么结果。如 [Route("api/[controller]")] public class HealthController : Controller { [HttpGet] public IActionResult Get() { return Ok("ok"); } } 3.服务注册 Consul 及注销 public void Configure(IApplicationBuilder app, IHostingEnvironment env, IApplicationLifetime applicationLifetime) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(); string ip = Configuration["ip"]; int port = Convert.ToInt32(Configuration["port"]); string serviceName = "MsgService"; string serviceId = serviceName + Guid.NewGuid(); using (var client = new ConsulClient(ConsulConfig)) { //注册服务到 Consul ServiceRegister是一个异步方法 client.Agent.ServiceRegister(new AgentServiceRegistration() { ID = serviceId,//服务编号,不能重复,用 Guid 最简单 Name = serviceName,//服务的名字 Address = ip,//服务提供者的能被消费者访问的 ip 地址(可以被其他应用访问的地址,本地测试可以用 127.0.0.1,机房环境中一定要写自己的内网 ip 地址) Port = port,// 服务提供者的能被消费者访问的端口 Check = new AgentServiceCheck { DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),//服务停止多久后反注册(注销) Interval = TimeSpan.FromSeconds(10),//健康检查时间间隔,或者称为心跳间隔 HTTP = $"http://{ip}:{port}/api/health",//健康检查地址 Timeout = TimeSpan.FromSeconds(5) } }).Wait();//Consult 客户端的所有方法几乎都是异步方法,但是都没按照规范加上Async 后缀,所以容易误导。记得调用后要 Wait()或者 await } //程序正常退出的时候从 Consul 注销服务 //要通过方法参数注入 IApplicationLifetime //程序结束的时候会调用这个方法 applicationLifetime.ApplicationStopped.Register(()=> { using (var client = new ConsulClient(ConsulConfig)) { client.Agent.ServiceDeregister(serviceId).Wait(); } }); } private void ConsulConfig(ConsulClientConfiguration c) { c.Address = new Uri("http://127.0.0.1:8500"); c.Datacenter = "dc1"; } 小哥哥 小姐姐们 如果本篇文章对你们有帮助的话 就点点右下角的推荐吧 0.0 现在的努力只是为了更好的将来,将来你一定不会后悔你现在的努力。一起加油吧!!! C#/.NetCore技术交流群:608188505欢迎加群交流 如果您认为这篇文章还不错或者有所收获,您可以点击右下角的【推荐】按钮精神支持,因为这种支持是我继续写作,分享的最大动力!

优秀的个人博客,低调大师

(10)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- Ocelot+Identity Server

用 JWT 机制实现验证的原理如下图: 认证服务器负责颁发 Token(相当于 JWT 值)和校验 Token 的合法性。 一、 相关概念 API 资源(API Resource):微博服务器接口、斗鱼弹幕服务器接口、斗鱼直播接口就是API 资源。 客户端(Client):Client 就是官方微博 android 客户端、官方微博 ios 客户端、第三方微博客户端、微博助手等。 身份资源(Identity Resource):就是用户。 一个用户可能使用多个客户端访问服务器;一个客户端也可能服务多个用户。封禁了一个客户端,所有用户都不能使用这个这个客户端访问服务器,但是可以使用其他客户端访问;封禁了一个用户,这个用户在所有设备上都不能访问,但是不影响其他用户。 二、 搭建 identity server 认证服务器 新建一个空的 web 项目 ID4.IdServer Nuget - 》 Install-Package IdentityServer4 首先编写一个提供应用列表、账号列表的 Config 类 using IdentityServer4.Models; using System.Collections.Generic; namespace ID4.IdServer { public class Config { /// <summary> /// 返回应用列表 /// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetApiResources() { List<ApiResource> resources = new List<ApiResource>(); //ApiResource第一个参数是应用的名字,第二个参数是描述 resources.Add(new ApiResource("MsgAPI", "消息服务API")); resources.Add(new ApiResource("ProductAPI", "产品API")); return resources; } /// <summary> /// 返回账号列表 /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients() { List<Client> clients = new List<Client>(); clients.Add(new Client { ClientId = "clientPC1",//API账号、客户端Id AllowedGrantTypes = GrantTypes.ClientCredentials, ClientSecrets = { new Secret("123321".Sha256())//秘钥 }, AllowedScopes = { "MsgAPI", "ProductAPI" }//这个账号支持访问哪些应用 }); return clients; } } } 如果允许在数据库中配置账号等信息,那么可以从数据库中读取然后返回这些内容。疑问待解。 修改Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { app.UseIdentityServer(); } 然后在 9500 端口启动 在 postman 里发出请求,获取 token http://localhost:9500/connect/token,发 Post 请求,表单请求内容(注意不是报文头): client_id=clientPC1 client_secret=123321 grant_type=client_credentials 把返回的 access_token 留下来后面用(注意有有效期)。 注意,其实不应该让客户端直接去申请 token,这只是咱演示,后面讲解正确做法。 三、搭建 Ocelot 服务器项目 空 Web 项目,项目名 ID4.Ocelot1 nuget 安装 IdentityServer4、Ocelot 编写配置文件 Ocelot.json(注意设置【如果较新则】) { "ReRoutes": [ { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "UpstreamPathTemplate": "/MsgService/{url}", "UpstreamHttpMethod": ["Get", "Post"], "ServiceName": "MsgService", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UseServiceDiscovery": true, "AuthenticationOptions": { "AuthenticationProviderKey": "MsgKey", "AllowedScopes": [] } }, { "DownstreamPathTemplate": "/api/{url}", "DownstreamScheme": "http", "UpstreamPathTemplate": "/ProductService/{url}", "UpstreamHttpMethod": ["Get", "Post"], "ServiceName": "ProductService", "LoadBalancerOptions": { "Type": "RoundRobin" }, "UseServiceDiscovery": true, "AuthenticationOptions": { "AuthenticationProviderKey": "ProductKey", "AllowedScopes": [] } } ], "GlobalConfiguration": { "ServiceDiscoveryProvider": { "Host": "localhost", "Port": 8500 } } } 把/MsgService 访问的都转给消息后端服务器(使用Consul进行服务发现)。也可以把Identity Server配置到Ocelot,但是我们不做,后边会讲为什么不放。 Program.cs 的 CreateWebHostBuilder 中加载 Ocelot.json .ConfigureAppConfiguration((hostingContext, builder) => { builder.AddJsonFile("Ocelot.json",false, true); }) 修改 Startup.cs 让 Ocelot 能够访问 Identity Server 进行 Token 的验证 using System; using IdentityServer4.AccessTokenValidation; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Ocelot.DependencyInjection; using Ocelot.Middleware; namespace ID4.Ocelot1 { public class Startup { public void ConfigureServices(IServiceCollection services) { //指定Identity Server的信息 Action<IdentityServerAuthenticationOptions> isaOptMsg = o => { o.Authority = "http://localhost:9500"; o.ApiName = "MsgAPI";//要连接的应用的名字 o.RequireHttpsMetadata = false; o.SupportedTokens = SupportedTokens.Both; o.ApiSecret = "123321";//秘钥 }; Action<IdentityServerAuthenticationOptions> isaOptProduct = o => { o.Authority = "http://localhost:9500"; o.ApiName = "ProductAPI";//要连接的应用的名字 o.RequireHttpsMetadata = false; o.SupportedTokens = SupportedTokens.Both; o.ApiSecret = "123321";//秘钥 }; services.AddAuthentication() //对配置文件中使用ChatKey配置了AuthenticationProviderKey=MsgKey //的路由规则使用如下的验证方式 .AddIdentityServerAuthentication("MsgKey", isaOptMsg).AddIdentityServerAuthentication("ProductKey", isaOptProduct); services.AddOcelot(); } // 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.UseOcelot().Wait(); } } } 很显然我们可以让不同的服务采用不同的Identity Server。 启动 Ocelot 服务器,然后向 ocelot 请求/MsgService/SMS/Send_MI(报文体还是要传 json 数据),在请求头(不是报文体)里加上: Authorization="Bearer "+上面 identityserver 返回的 accesstoken 如果返回 401,那就是认证错误。 Ocelot 会把 Authorization 值传递给后端服务器,这样在后端服务器可以用 IJwtDecoder 的这个不传递 key 的重载方法 IDictionary<string, object> DecodeToObject(string token),就可以在不验证的情况下获取 client_id 等信息。 也可以把 Identity Server 通过 Consul 进行服务治理。 Ocelot+Identity Server 实现了接口的权限验证,各个业务系统不需要再去做验证。 四、不能让客户端请求 token 上面是让客户端去请求 token,如果项目中这么搞的话,就把 client_id 特别是 secret 泄露给普通用户的。 正确的做法应该是,开发一个 token 服务,由这个服务来向 identity Server 请求 token,客户端向 token 服务发请求,把 client_id、secret 藏到这个 token 服务器上。当然这个服务器也要经过 Ocelot 转发。 五、用户名密码登录 如果 Api 和用户名、密码无关(比如系统内部之间 API 的调用),那么上面那样做就可以了,但是有时候需要用户身份验证的(比如 Android 客户端)。也就是在请求 token 的时候还要验证用户名密码,在服务中还可以获取登录用户信息。 修改的地方: 1、 ID4.IdServer 项目中增加类 ProfileService.cs using IdentityServer4.Models; using IdentityServer4.Services; using System.Linq; using System.Threading.Tasks; namespace ID4.IdServer { 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; } } } 增加类 ResourceOwnerPasswordValidator.cs using IdentityServer4.Models; using IdentityServer4.Validation; using System.Security.Claims; using System.Threading.Tasks; namespace ID4.IdServer { public class ResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { //根据context.UserName和context.Password与数据库的数据做校验,判断是否合法 if (context.UserName == "yzk" && context.Password == "123") { context.Result = new GrantValidationResult( subject: context.UserName, authenticationMethod: "custom", claims: new Claim[] { new Claim("Name", context.UserName), new Claim("UserId", "111"), new Claim("RealName", "名字"), new Claim("Email", "qq@qq.com") }); } else { //验证失败 context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential"); } } } } 当然这里的用户名密码是写死的,可以在项目中连接自己的用户数据库进行验证。claims 中可以放入多组用户的信息,这些信息都可以在业务系统中获取到。 Config.cs 修改一下,主要是把GetClients中的AllowedGrantTypes属性值改为GrantTypes.ResourceOwnerPassword, 并且在AllowedScopes中加入 IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报forbidden错误 IdentityServerConstants.StandardScopes.Profile 修改后的 Config.cs using System.Collections.Generic; using IdentityServer4; using IdentityServer4.Models; namespace ID4.IdServer { public class Config { /// <summary> /// 返回应用列表 /// </summary> /// <returns></returns> public static IEnumerable<ApiResource> GetApiResources() { List<ApiResource> resources = new List<ApiResource>(); //ApiResource第一个参数是应用的名字,第二个参数是描述 resources.Add(new ApiResource("MsgAPI", "消息服务API")); resources.Add(new ApiResource("ProductAPI", "产品API")); return resources; } /// <summary> /// 返回客户端账号列表 /// </summary> /// <returns></returns> public static IEnumerable<Client> GetClients() { List<Client> clients = new List<Client>(); clients.Add(new Client { ClientId = "clientPC1",//API账号、客户端Id AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, ClientSecrets = { new Secret("123321".Sha256())//秘钥 }, AllowedScopes = { "MsgAPI","ProductAPI",IdentityServerConstants.StandardScopes.OpenId, //必须要添加,否则报forbidden错误 IdentityServerConstants.StandardScopes.Profile }//这个账号支持访问哪些应用 }); return clients; } } } Startup.cs 的 ConfigureServices 修改为 public void ConfigureServices(IServiceCollection services) { var idResources = new List<IdentityResource> { new IdentityResources.OpenId(), //必须要添加,否则报无效的 scope 错误 new IdentityResources.Profile() }; services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(idResources) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients())// .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>() .AddProfileService<ProfileService>(); } 主要是增加了 AddInMemoryIdentityResources 、 AddResourceOwnerValidator 、AddProfileService 2、 修改业务系统 以 MsgService 为例 Nuget -> Install-Package IdentityServer4.AccessTokenValidation 然后 Startup.cs 的 ConfigureServices 中增加 services.AddAuthentication("Bearer") .AddIdentityServerAuthentication(options => { options.Authority = "http://localhost:9500";//identity server 地址 options.RequireHttpsMetadata = false; }); Startup.cs 的 Configure 中增加 app.UseAuthentication(); 3、 请求 token 把报文头中的 grant_type 值改为 password,报文头增加 username、password 为用户名、密码。 像之前一样用返回的 access_token传递给请求的Authorization 中,在业务系统的 User中就可以获取到 ResourceOwnerPasswordValidator 中为用户设置的 claims 等信息了。 public void Send_MI(dynamic model) { string name = this.User.Identity.Name;//读取的就是"Name"这个特殊的 Claims 的值 string userId = this.User.FindFirst("UserId").Value; string realName = this.User.FindFirst("RealName").Value; string email = this.User.FindFirst("Email").Value; Console.WriteLine($"name={name},userId={userId},realName={realName},email={email}"); Console.WriteLine($"通过小米短信接口向{model.phoneNum}发送短信{model.msg}"); } 4、 独立登录服务器解决上面提到的“不能让客户端接触到 client_id、secret 的问题” 开发一个服务应用 LoginService public class RequestTokenParam { public string username { get; set; } public string password { get; set; } } using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; namespace LoginService.Controllers { [Route("api/[controller]")] [ApiController] public class LoginController : ControllerBase { [HttpPost] public async Task<ActionResult> RequestToken(RequestTokenParam model) { Dictionary<string, string> dict = new Dictionary<string, string>(); dict["client_id"] = "clientPC1"; dict["client_secret"] = "123321"; dict["grant_type"] = "password"; dict["username"] = model.username; dict["password"] = model.password; //由登录服务器向IdentityServer发请求获取Token using (HttpClient http = new HttpClient()) using (var content = new FormUrlEncodedContent(dict)) { var msg = await http.PostAsync("http://localhost:9500/connect/token", content); string result = await msg.Content.ReadAsStringAsync(); return Content(result, "application/json"); } } } } 这样客户端只要向 LoginService 的 /api/Login/ 发请求带上 json 报文体 {username:"yzk",password:"123"}即可。客户端就不知道 client_secret 这些机密信息了。 把 LoginService 配置到 Ocelot 中。 参考文章:https://www.cnblogs.com/jaycewu/p/7791102.html 注:此文章是我看杨中科老师的.Net Core微服务第二版和.Net Core微服务第二版课件整理出来的 现在的努力只是为了更好的将来,将来你一定不会后悔你现在的努力。一起加油吧!!! C#/.NetCore技术交流群:608188505欢迎加群交流 如果您认为这篇文章还不错或者有所收获,您可以点击右下角的【推荐】按钮精神支持,因为这种支持是我继续写作,分享的最大动力!

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册