BT

如何利用碎片时间提升技术认知与能力? 点击获取答案

ASP.NET Core:简洁的力量

| 作者 Chris Klug 关注 1 他的粉丝 ,译者 无明 关注 0 他的粉丝 发布于 2018年5月30日. 估计阅读时间: 15 分钟 | 如何结合区块链技术,帮助企业降本增效?让我们深度了解几个成功的案例。

关键要点

  • 在构建Web应用程序时,OWIN为开发人员提供了一个很好的Web服务器抽象。
  • ASP.NET Core脱离了标准OWIN实现,这是为开发人员而做出的简化。
  • 通过抽象来简化复杂的事物并不会削弱它,只是让它变得更简单易用。
  • 通过使用中间件而不是高级框架,开发人员可以构建出既简洁又强大的应用程序。
  • 即使没有在使用ASP.NET Core,也可以通过在旧的解决方案中使用Katana来获得相关功能。

随着.NET Core 2.0的发布,这个最初于2016年发布的具有通用性、模块化、跨平台和开放源代码的平台终于有了最新的主要版本。.Net Core包含了很多在当前版本的.NET Framework中可用的API。它的初衷是为下一代ASP.NET解决方案提供支持,但现在却成为了其他场景的基础,包括物联网、云计算和下一代移动解决方案。在本系列文章中,我们将探讨.NET Core的一些优势,以及它如何给传统.NET开发者以及所有需要为市场提供强大、高性能和经济解决方案的技术人员带来好处。

这篇是“.NET Core”系列文章的一部分。读者可以通过订阅RSS接收更新通知。

在微软决定重新构想他们的Web开发平台ASP.NET时,他们认为将其与IIS绑定可能不是一个好主意。原来的ASP.NET构建于IIS的特定技术之上,这样不仅导致ASP.NET与Windows绑定在一起,而且无法进行自行托管。这些限制导致它很难切入到以云为中心的世界。微软决定全面开放Open Web Interface for .NET(或者叫作OWIN),并且将Web服务器全面抽象出来。框架以及框架的用户因此可以完全忽略哪个服务器负责处理哪个HTTP请求,他们可以专注于构建所需的功能。

不过,OWIN并不是一个新概念。OWIN规范已经存在好几年了,微软早就允许开发人员通过一个名为Katana的开源项目在IIS中使用OWIN。事实上,微软不仅允许开发人员通过Katana使用OWIN,几年来,OWIN已经成为所有ASP.NET身份验证功能的基础。

那么,OWIN究竟是什么?说实话,它是个很简单的东西!而正是这种简单性让它变得如此伟大。它是一个接口,只使用预定义的代理和一个由字符串和对象组成的通用字典来抽象Web服务器。因此,它没有使用基于事件驱动的架构,而是定义了一个管道,叫作中间件(middleware)。

中间件其实是一段代码,负责与来自客户端的请求发生交互。(是的,我故意用“一段代码”这个词来说明它的通用性)。它可以通过几种不同的方式来实现。虽然基于类的方式在大多数情况下是首选,但其实一个具有正确签名的代理就足够了。中间件代码可以检查或者修改从客户端到达的请求和返回给客户端的响应。如果有必要,它甚至可以生成发送给客户端的响应。

然后中间件组成了一个管道,传入的消息按照中间件加入管道的顺序从一个中间件传到另一个中间件,直到其中一个中间件知道如何生成响应消息为止。然后响应消息被传回管道进行检查,在发送给客户端之前,中间件有可能会修改它。原理非常简单,但仍然非常灵活和强大。

这个过程被称为请求管道,消息流经管道,中间件在它流过时与它发生交互。但是,管道需要某种形式的管道对象来负责将消息在中间件之间传递。在OWIN中,中间件实际上更像是一个链表。传入的请求被传递给列表中的第一个中间件,在完成处理后再传递给下一个中间件。该请求从一个中间件传递到另一个中间件,直到其中的一个产生响应消息并将响应消息发回到该列表,让之前的中间件检查响应消息。事实上,这个过程有点复杂,因为响应消息实际上应该在生成后立即发送给客户端,甚至是在将它回传给管道之前。这使得修改响应消息变得稍微复杂一点,但为了简单起见,我们就忽略这一部分。

OWIN规范将传入的请求定义为由字符串和对象组成的字典。服务器接收传入的HTTP请求,将请求信息拆分为可用的块,并将其放入字典中,然后将其传递给第一个中间件进行处理。它使用预定义的关键字将请求路径、头部信息集合、包含消息体的流等内容添加到字典中。中间件使用这些关键字从字典中读取所需的信息,并完成相应的处理。除此之外,服务器还会添加用于生成响应消息的对象到字典中,如响应流和响应头部信息集合,中间件就可以通过使用字典中的对象来生成响应并发送给客户端。最重要的是,服务器实际上可以在字典中加入代理,以便向中间件提供额外的功能。例如,有一个OWIN规范扩展允许服务器提供一种专门的方式将文件发送给客户端。服务器通过提供一个预定义的代理放到字典中,并暴露给中间件。然后,中间件可以查询字典以查看当前服务器是否支持该功能,如果是,就调用代理将将文件发给客户端。

OWIN接口非常简单,但也很强大。它为我们提供对HTTP请求和响应的底层访问,同时又抽象出处理实际请求的繁琐细节。不过,它并不会限制我们通过代理来提供更高级别抽象的能力。另一方面,因为太过底层,有时候使用起来确实有点麻烦,我想这就是为什么微软决定以自己的方式拥抱OWIN。

微软在将OWIN管道添加到ASP.NET Core时,对其进行了一些更改。或者说,他们在上面添加了一个层,使其更容易操作(至少我看到的就是这样)。他们不是仅仅为中间件提供了一个通用字典,而是在其上添加了一个类型层,使其更易于使用。因此,我们不是要去获取字典,而是获取一个HttpContext对象,这样我们就能够以更简单的方式与请求和响应发生交互。例如,我们可以使用httpContext.Response.Body.Write(...)向客户端返回消息,而不是使用((Stream)dictionary[“owin.RequestBody”]).Write(...)。虽然差别不是很大,但起码不需要去记住关键字是什么,也不需要做类型转换,这样就不容易出错。

在Katana项目中,HttpContext对字典进行了包装,这样我们就可以以类型的方式来访问其中的数据项。另一方面,在ASP.NET Core中,它是一个完全自定义的对象。不过,如果我们想要使用基于OWIN的中间件,可以使用一些可用的扩展来提供“适当的”OWIN API。

那么,我们是否真的要使用这样的低级API来构建应用程序?当然不是!在这个低级API之上构建更高级的抽象是相当容易的,这些恰恰是微软已经完成的事情。在ASP.NET Core中,ASP.NET MVC就是一个中间件实现。它包含了几个使用.NET Core依赖注入功能注入到中间件的服务,但它本身是一个中间件,负责与客户端的请求发生交互。这就是这个底层API发挥其威力的地方。

因为我们可以在请求管道中注册任意多的中间件,所以可以加入我们想要使用的框架和功能。想要使用ASP.NET MVC来生成UI?不用担心,只需添加MVC中间件和支持服务即可。想要在API中使用NancyFx?没问题,只需将它添加到请求管道中。想使用Facebook身份验证?没问题!只需添加所需的中间件和服务即可。想要将Twitter身份验证与JWT令牌结合起来用在你的API中?添加中间件即可。我确定你已经明白了……这个简单的接口让我们能够加入我们需要的东西,将第三方中间件与我们自己定制的中间件相结合,创建一个完全自定义的请求管道,以满足我们的需求。最重要的是,如果没有处理请求的中间件,就什么都不会发生。这与在IIS中托管ASP.NET非常不同,其中一些功能来自ASP.NET,有些来自IIS。

我没有为ASP.NET Core请求管道写过一篇完整的文章,也没有代码来展示它的工作原理。所以,我们就以身份验证为例。这是了解OWIN最常见的方式之一,同时也是展示这个接口强大功能的一个很好的例子,所以在这里使用它似乎很合适。

将身份验证添加到ASP.NET Core Web应用程序意味着需要将一些东西添加到应用程序中。首先,我们需要将认证服务添加到服务集合中,然后告诉它我们想要支持的不同类型的认证。

假设我们想要使用Facebook身份认证,并且在用户通过身份验证后,我们希望使用Cookie认证为他们授权。配置看起来像这样:

public void ConfigureServices(IServiceCollection services) { 
  services.AddAuthentication(CookieAuthenticationDefautls.ApplicationScheme) .AddFacebook(“### CLIENT ID ###”, “### CLIENT SECRET ###”)
  .AddCookie();
 }

一旦有了这些服务,就可以像这样将认证中间件添加到请求管道中:

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
        // Middlewares that don’t require authenticated users
        app.UseAuthentication();
        // Middlewares that might require authenticated users
}

最后,当我们想要将用户重定向到Facebook进行身份验证时,只需要调用:

await HttpContext.ChallengeAsync( 
  new AuthenticationProperties { RedirectUri = "/userinfo" },
    FacebookDefaults.AuthenticationScheme);
}

此调用将使用已定义的身份验证方案来设置HttpContext,将用户重定向到正确的登录页面。在这种情况下,Facebook身份验证处理程序会将返回的状态代码设置为HTTP 302,并且将location头部字段设置为Facebook的认证地址,以便将客户端重定向到该地址。一旦用户通过Facebook的身份验证,并被重定向回带有身份令牌的应用程序,身份验证中间件就会捕获该回调并使用Facebook服务验证令牌。如果一切正常,它会要求Cookie身份验证服务发出一个用于保持客户端登录的Cookie。实际上,这意味着Cookie身份验证服务会将一个头部信息添加到HttpContext的响应头部字典中,然后再添加到响应消息中。

我们通过使用几个扩展方法来注册一些服务和一个中间件,建立了一个相当复杂的认证流程,在请求认证时重定向用户,并在认证发生时处理来自身份提供者的回调。

注意:在以前的配置中,它实际上会尝试使用Cookie身份验证来验证用户身份,而不是默认使用Facebook身份认证。但只需要作出一个很小的配置更改,就可以将Facebook作为默认的认证机制,但这已经超出了本文讨论的范围。

我希望你也赞同我所说的,迁移到基于OWIN的管道是一件好事。它可能是一个非常简单的底层接口,但如果使用得当,它会发挥巨大的威力。创建一个简单易用的接口,可以兼顾底层和高级的用法,并且不会对未来造成限制,这不是一件容易的事。但我确信这个接口能做到。现在,我们需要充分利用它!只要你稍微有点创意,就没有什么可以限制你——你只需要搞清楚需要解决什么问题。

关于作者

Chris Klug 是瑞典斯德哥尔摩tretton37的一名软件开发人员和架构师。他一生中花费了很多时间通过编写软件来解决问题,他喜欢编码时的创造性以及在编码过程中不断遇到的挑战。他还花费大量时间在世界各地的开发者会议上发表演讲,这显然引起了微软的关注,并授予他MVP嘉奖。但是当被问及兴趣爱好时,他承认,相比玩电脑,他更喜欢在一个漂亮的海滩上放风筝,或者继续扩大他身上的纹身。

随着.NET Core 2.0的发布,这个最初于2016年发布的具有通用性、模块化、跨平台和开放源代码的平台终于有了最新的主要版本。.Net Core包含了很多在当前版本的.NET Framework中可用的API。它的初衷是为下一代ASP.NET解决方案提供支持,但现在却成为了其他场景的基础,包括物联网、云计算和下一代移动解决方案。在本系列文章中,我们将探讨.NET Core的一些优势,以及它如何给传统.NET开发者以及所有需要为市场提供强大、高性能和经济解决方案的技术人员带来好处。

这篇是“.NET Core”系列文章的一部分。读者可以通过订阅RSS接收更新通知。

查看英文原文ASP.NET Core - The Power of Simplicity

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我
社区评论

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT