Spiga

标签为.Net Core的文章

ASP.NET Core 7 源码阅读7:CAR

2023-09-25 23:01:42

摘要:一、CAR 1. CAR本质 URL请求----调用Action----生成html响应(或其他响应) CAR就是个普通类---普通方法---最终生成HTML(也可能是其他的) 一个URL,怎么调用的Action---一定是反射----反射创建控制器实例,反射准备方法参数,反射调用Action方法(也许来点优化) 然后生成一段内容(啥都可以),写入到Response里面---然后由Kestrel回发到浏览器----浏览器解析报文做呈现 先Get这个本质,不要被各种封装各种特性看花眼了~ 2. 关键节点-上帝视角 CAR虽然是最后才生效,但是在前面也出现了---全流程debug一下,回顾一下: 启动环节services.AddControllers注册IOC时扫描dll,保存到ApplicationManager 初始化中间件MapControllerRoute()转成ControllerActionDescripter 第一次请求进入,路由初始化DFAMatcher时触发转换成Endpoint,路由匹配找到Endpoint---鉴权授权--- 执行Endpoint时实例化和缓存各种工厂、 Filter等---做好调用准备 执行Filter管道, ActionBegin状态实例化控制器, Bind参数 ActionInside状态开始执行Action,得到ActionResult ResultInside状态开始执行ExecuteResult,得到结果 Controller-Action-Result流程结束 3. CAR源码 按照主流程往后走,先关注Controller,再Action,再Result,其中会有回溯 步骤1: services.AddControllers注册时扫描dll,转成ApplciationPart,保存到ApplciationPartManager 知识点:当前项目引用的dll都算数,所以是独立类库---扩展PartDemo 收集完的内容都是保存在ApplciationPartManager—等于是个中间层,其实就可以开个后门,通过其他方式添加数据进去---所以可以热插拔 甚至可以动态编译脚本---后插拔进去 步骤2:初始化中间件MapControll…… 阅读全文

ASP.NET Core 7 源码阅读6:Filter

2023-08-20 21:32:52

摘要:一、快速认识Filter 1. 流程衔接点 MVC(Filter+Controller+Action+Result)流程和前面的各种中间件Middleware处理,是如何衔接起来的? Http请求穿过一系列中间件,最终由路由RoutingMiddleware匹配得到RouteEndpoint 在EndpointMiddleware里面会执行其RequestDelegate,委托执行时就是FilterController-Action-Result 该委托在ControllerRequestDelegateFactory里面来构建的,里面通过ControllerActionInvoker来调用 这里有个新名字叫 FilterPipeline 2. 快速认识Filter Filter是MVC里面核心组成部分,有着丰富的种类,交叉的顺序,复杂的嵌套,很有挑战! Filter分2种: 声明特性,实现Filter接口:CustomSimpleShowActionFilterAttributeCustomSimpleShowAsyncActionFilterAttributeCustomSimpleShowDoubleActionFilterAttribute:一个Filter里面既有同步,又有异步,只执行异步!能改参数,能改结果,非常强大注意异步版本的结果修改坑 控制器类实现Filter接口包括Action同步异步-Result同步异步---控制器生效,全部Action都有效 3. AOP面向切面编程 要说Filter,得理解下AOP面向切面编程Aspect Oriented Programming POP面向过程,没有封装没有边界,难以应对复杂需求OOP面向对象,有封装有边界,能应付复杂需求,但原子---类---不容破坏,否则会影响稳定性---开闭原则 AOP能在不破坏封装的前提下,去额外扩展功能比如ActionFilter,啥都没修改,就能增加执行逻辑AOP的好处: 聚焦业务逻辑,轻松扩展功能 代码复用,集中管理 4. 框架中的AOP 现代化开发框架中,要灵活应用AOP面向切面编程思想: ASP.NET Core三层AOP 中间件:离MVC比较远,面向与请求级的事儿 Filter:更贴近MVC,面向单…… 阅读全文

ASP.NET Core 7 源码阅读5:鉴权授权

2023-07-10 15:35:12

摘要:从Http无状态协议---用户持久化的需求---最初是Cookie+Session---Token但是不管是哪种方式,有一段内容是不变的: 请求服务端,获取凭证 客户端再次请求,带上凭证 服务端识别凭证,判断是否允许访问 鉴权授权的本质是做啥的? 其实就是第3步解决用户识别和判断授权的问题被拆分成了2个动作: 鉴权Authentication:凭证识别解析,有没有登陆,凭证有没有过期,是张三还是李四 授权Authorization:基于解析来权限检测,判断下张三/李四有没有权限访问这个资源 一、实操 1. 没有任何权限要求实操 添加相关控制器, Cookie式登陆方法 UseAuthentication + AddAuthentication + Cookie UseAuthorization + AddAuthorization(可不写) [Authorize] [AllowAnonymous] 校验流程: 未登陆,直接访问,跳转登录页 AllowAnonymous可直接访问 登陆后跳转,正常访问 退出后访问,跳转登陆页 2. 授权 Roles授权: [Authorize(Roles = Admin)] Policy授权: [Authorize(Policy = AdminPolicy)] 复杂Policy授权: [Authorize(Policy = MutiPolicy)] 授权的设计,也是可以满足开发者各种这样的需求—目前还没演示完 如果是没有登陆,是跳转LoginPath---401 如果是有凭证,但没有权限,是跳转AccessDeniedPath--403 3. 发送了什么? 请求到达Action之前,即使没有标记,也会自动鉴权 主动鉴权:理解鉴权信息保存 主动授权:理解授权检测过程 4. 理解总结 鉴权授权是ASP.NET Core框架封装的2个中间件,目的在于请求进入具体的Filter-M-V-C之前,通过中间件完成用户权限检测包含2个步骤: 鉴权Authentication:鉴别有没有登陆,解析是张三还是李四(且将信息传递下去)---UseAuthentication配置Http管道,保证请求来了,都要做一次凭证的解析AddAu…… 阅读全文

ASP.NET Core 7 源码阅读4:MVC核心中间件

2023-06-26 16:24:03

摘要:一、核心流程概述 执行AddMVC() 将MVC的核心服务注册到容器,且通过反射扫描把相关dll收集起来 执行app.UseRouting() 将EndpointRoutingMiddleware中间件注册到http管道 执行app. MapControllerRoute() 将本程序集定义的所有Controller-Action-ParameterConversion转换为一个个的ControllerActionDescriptor放到路由中间件的配置对象RouteOptions中,注册并传入EndpointMiddleware中间件注册到http管道中 请求来了,管道模型Build---没啥动作,倒序执行中间件的实例化 收到一条http请求,先进入EndpointRoutingMiddleware,首次请求时会完成ControllerActionDescriptor到EndPoint的转化,然后通过DFA算法匹配一个Endpoint,并放到HttpContext中去 鉴权/授权/其他中间件可以根据根据Endpoint的信息对这个请求进行鉴权授权或其他操作。 EndpointMiddleware中间件执行Endpoint中的RequestDelegate逻辑,即执行FilterController-Action-Result等系列操作(MVC) 二、AddMVC 1. 上帝视角 AddMVC(AddControllersWithViews)是最初发生的,是IOC注册环节的事儿,在管道注册之前,其职责有2个: 添加MVC各种IOC注册,超多。。 反射遍历相关程序集,封装成ApplicationPart,供后续使用 2. 源码解读 从MvcServiceCollectionExtensions开始,绕一圈,最终是AddMvcCore()方法 先实例化ApplicationPartManager-----拿着项目名字,通过反射加载Dll,将信息封装到ApplciationPartManager的ApplicationParts属性中---扩展点 ConfigureDefaultFeatureProviders(partManager);的调用,这行代码是创建了一个新的ControllerFeatureProvide…… 阅读全文

ASP.NET Core 7 源码阅读3:基础中间件

2023-06-11 23:26:04

摘要:一、ExceptionHandler ASP.NET Core管道最外面,就是app.UseExceptionHandler(/Home/Error);这个是全局异常处理,这个/Home/Error在哪里? 直接看源码 UseExceptionHandler----ExceptionHandlerExtensions,开启新的Http管道,里面就是个ExceptionHandlerMiddlewareImpl------注册中间件 异常真的发生了,中间件的Invoke方法,看catch里面,最终是到ErrorPage.design.cs文件---请求响应时 没有Add,因为太简单了---没啥东西 中间件其实有3件事儿: AddXXX----builder.Build()期间,去完成的IOC注册 UseXXXX---app.Run()期间,去完成中间件注册,组装Http管道 Middleware的InvokeAsync()—请求响应时,才执行 关于全局异常处理中间件和Filter的区别 ExceptionHandlerMiddleware是全局性质,是兜底的----而ExceptionFilter其实只管控制器-Action的异常,是管不了View-ResultFilter的异常 精细度不同,中间件只知道模糊信息,不适合做业务处理----ExceptionFilter贴近业务的,可以返回业务信息 其实完整的异常方案,就应该是二者叠加-- 二、HTTPS HstsMiddleware HSTS 是 HTTP 严格传输安全(HTTP Strict Transport Security) 的缩写效果是:优先使用https---如果有https,就使用这个 源码解读: HstsMiddleware-----就是设置个header--- Strict-Transport-Security= maxage= HttpsRedirection UseHttpsRedirection 就是优先访问https,访问http会自动跳转(后台有配置https)效果:直接VS的https启动,访问http,开关中间件尝试https://localhost:7066 http://localhost:7067 …… 阅读全文

ASP.NET Core 7 源码阅读2:Http管道和Kestrel

2023-05-29 10:48:46

摘要:一、HttpPipeline 1. 理解Http请求流程 Http请求响应流程,也就是浏览器输入个地址,发生了什么事儿: 浏览器输入地址, www.xxx.com DNS解析,找到IP+Port,然后浏览器向该地址发Http报文---纯文本 Nginx/IIS/Kestrel监听端口,收到报文解析得到HttpContext 将请求转发到业务代码处理---怎么进入到controller+action? 处理结果由服务器回发到客户端,浏览器解析报文完成渲染 所谓HttpPipeline就是程序如何处理请求的全过程--- 理解Http管道所处的位置: Web服务器解析报文之后,在Web服务器回发报文之前 Http管道和controller-action的关系:其实是包含关系,任何处理动作都是管道的一部分 2. 理解Http管道 HttpPipeline本质是个啥? 接受HttpContext,然后做一系列的处理(Cookie Session 鉴权授权 缓存 路由 MVC)---最终将结果保存在HttpContext的Response里面 然后在ASP.NET Core里面,就被抽象成为一个委托—RequestDelegate---接受一个HttpContext,然后执行一系列操作 但是开发中,管道模型是很复杂的呀?因为Http请求的处理并不简单,包含了很多环节---Cookie/Session/鉴权授权/缓存/https/静态文件-------还有就是各种不同的业务处理需求(M-V-C)-----还有开发者的扩展需求(限流—黑名单白名单)-----所以需要一套扩展性的框架 这套实现,就是ASP.NET Core的HttpPipeline 3. 管道模型上帝视角 先创建个WebApplicationBuilder()---然后各种配置IOC/Logging/Configuration---然后Build()完成了各种初始化---得到WebApplication WebApplication去Use添加添加中间件(委托)---实际上是ApplicationBuilder在Use------就是把中间件(Func委托)保存到一个集合 最后框架在Run的时候,会执行ApplicationBuilder的Build方法,将委托…… 阅读全文

ASP.NET Core 7 源码阅读1:启动过程

2023-05-08 18:38:14

摘要:一、从.NET Framework到.NET Core 1. 本质 .NET Framework:描述的是上层应用框架,底层就只支持windows平台, BCL CLR都是只有一个 .NET Core: 2016年.NETCore1.0,特点是3个CLR共存的(NET Framework、NER Core、XAMARIN) 最后个版本是.NET Core3.1 .NET5:终结3个分支,统一,一个CLR,一个BCL——2020年全球疫情,导致很多内容没完成 .NET6:口号也是统一平台,各种该实现的都实现了一下 .NET7:进一步完善统一,没有太大的变化,缝缝补补 2. 跨平台的理解 运行时CLR——CoreCLR C#程序——》编译器——》DLL/EXE(metadata、IL)——》CLR/JIT——》机器码 不能跨平台是因为只有一个CLR,不同的CLR匹配不同的平台 以前不能开发Linux的CLR,是因为NET Framework底层库依赖window,如IIS,画图库等 3. ASP.NET Core有哪些好处的功能 依赖注入 日志系统架构 引入了一个跨平台的网络服务器,kestrel 试用appsettings来配置工程 试用startup来注册服务 更好的支持异步编程 对于跨网站请求的预防和保护机制 验证令牌 @Html.AntiForgrtyToken 使用HTTPS 设置CSP(内容安全策略):定义哪些资源可以被加载和执行,减少XSS攻击风险 context.Response.Headers.Add(Content-Security-Policy, default-src 'self'; script-src 'self' https://xxx.com); 强大的验证和数据绑定功能:如[BindRequired]、[BindNever]属性 使用安全API端点设计:如JWT进行认证 4. ASP.NET Core有哪些更好的地方 跨平台 对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起 处理请求的效率更高,能够处理更多请求 更多安装配置方法 二…… 阅读全文

[推荐] EntityFrameworkCore

2019-07-24 19:56:36

摘要:基于原始SQL查询创建LINQ查询,代替旧版的FromSql、SqlQuery 基本原生 SQL 查询 在版本.net core 2.0 中,我们引入了一种在依赖关系注入中注册自定义 DbContext 类型的新方法,即以透明形式引入可重用 DbContext 实例的池。 要使用 DbContext 池,请在服务注册期间使用 `AddDbContextPool` 而不是 `AddDbContext`:services.AddDbContextPool<BloggingContext>( options => options.UseSqlServer(connectionString)); 如果使用此方法,那么在控制器请求 DbContext 实例时,我们会首先检查池中有无可用的实例。 请求处理完成后,实例的任何状态都将被重置,并且实例本身会返回池中。 从概念上讲,此方法类似于连接池在 ADO.NET 提供程序中的运行原理,并具有节约 DbContext 实例初始化成本的优势。 阅读全文

鉴权功能实现

2018-11-16 16:46:20

摘要:需求背景 假设,你正在参与开发一个微服务。微服务通过 HTTP 协议暴露接口给其他系统调用,说直白点就是,其他系统通过 URL 来调用微服务的接口。有一天,你的 leader 找到你说,“为了保证接口调用的安全性,我们希望设计实现一个接口调用鉴权功能,只有经过认证之后的系统才能调用我们的接口,没有认证过的系统调用我们的接口会被拒绝。我希望由你来负责这个任务的开发,争取尽快上线。” 需求分析 1. 第一轮基础分析 对于如何做鉴权这样一个问题,最简单的解决方案就是,通过用户名加密码来做认证。我们给每个允许访问我们服务的调用方,派发一个应用名(或者叫应用 ID、AppID)和一个对应的密码(或者叫秘钥)。调用方每次进行接口请求的时候,都携带自己的 AppID 和密码。微服务在接收到接口调用请求之后,会解析出 AppID 和密码,跟存储在微服务端的 AppID 和密码进行比对。如果一致,说明认证成功,则允许接口调用请求;否则,就拒绝接口调用请求。 2. 第二轮分析优化 不过,这样的验证方式,每次都要明文传输密码。密码很容易被截获,是不安全的。那如果我们借助加密算法(比如 SHA),对密码进行加密之后,再传递到微服务端验证,是不是就可以了呢?实际上,这样也是不安全的,因为加密之后的密码及 AppID,照样可以被未认证系统(或者说黑客)截获,未认证系统可以携带这个加密之后的密码以及对应的 AppID,伪装成已认证系统来访问我们的接口。 这就是典型的“重放攻击” 。 提出问题,然后再解决问题,是一个非常好的迭代优化方法。对于这个问题,我们可以借助 OAuth 的验证思路来解决。调用方将请求接口的 URL 跟 AppID、密码拼接在一起,然后进行加密,生成一个 token。调用方在进行接口请求的的时候,将这个 token 及 AppID,随 URL 一块传递给微服务端。微服务端接收到这些数据之后,根据 AppID 从数据库中取出对应的密码,并通过同样的 token 生成算法,生成另外一个 token。用这个新生成的 token 跟调用方传递过来的 token 对比。如果一致,则允许接口调用请求;否则,就拒绝接口调用请求。 3. 第三轮分析优化 不过,这样的设计仍然存在重放攻击的风险,还是不够安全。每个 URL 拼接上 AppID、密码生成的 token 都是固定的。未认证系统截…… 阅读全文

微服务架构(二):熔断降级

2018-03-15 20:56:36

摘要:概念------为什么-----如何使用----运行原理------熔断-----降级-----超时------重试----封装 -----consul和polly整合到项目中 首先我们来明确一下,微服务架构的基本单位是微服务,也就主体是微服务----同时每一个微服务都有自己的结构。这些结构组合成了一个微服务(这属于文件夹分层发)这个时候,那么每一个微服务都会出现相同的结构。这个时候很多同学会有疑问,为什么各个微服务之间这些相同的文件不能够进行通用呢,反而会出现这么多冗余。这样做的原因,1、保证微服务的独立性,2、保证微服务的稳定。我举个例子:微服务就好比我们每一个人,我们每一个人就组成了一个社会架构,微服务和这种场景是类似的。大家都知道,每个人的结构都是一样的。如果每个人结构都全部集中到一起。会出现什么问题,大家可以想象一下。全部乱套了。同理,微服务也是一样。所有微服务的第一要务就是保证独立性。所以我这里对微服务采用文件夹分层法。 对于什么时候用程序集分层。先明白一下,每一个微服务都有自己的领域模型(也就是我们昨天说的问题和问题边界)。如果多个微服务之间。存在不得不共享资源,共享资源是不易变化,且变化不影响每一个微服务的逻辑的时候。那么我们就把这通用的逻辑抽取出来,用dll来分层进行引用,例如:微服务之间都需要通信,需要认证,需要限流,负载均衡等等。那么咱们就把这一层称作为工具层。 什么是熔断 熔断就是在被调用端出现宕机,和超时两种情况出现的一种策略应对机制。 熔断就好比保险丝,我们先来看一看保险丝的情况 为什么要使用熔断 服务调用出现异常(包括超时和宕机两种情况) 如果服务连续几次都出现异常,那么就将服务进行熔断一段时间, 服务调用出现异常(包括超时和宕机两种情况) 如果服务连续几次都出现异常,那么就将服务进行熔断一段时间 服务调用出现异常(包括超时和宕机两种情况) 如果服务连续几次都出现异常,那么就将服务进行熔断一段时间 什么是降级 为什么要使用降级 服务主动降级(选择性放弃) 主动将服务进行进行异常返回 服务异常降级 如果服务调用出现超时或者宕机的情况,就按照自定义的策略进行返回。 服务主动降级(选择性放弃) 主动将服务进行进行异常返回 服务异常降级 如果服务调用出现超时或者宕机的情况,就按照自定义的策略进行返回。 服务主动降…… 阅读全文