使用Web API ASP.NET Core 2.2部署Angular 8应用程序

目录

情境化部署方案

从理论到实践

后端和CORS,单独的章节


情境化部署方案

当我开始这个部署过程时,一个带有Angular应用程序的ASP.NET核心web应用程序,我花了几天时间尝试和错误方法,发现后端和前端需要在虚拟机(Microsoft Azure虚拟机)中协同工作。部署这两种技术ASP.NET CoreAngular需要许多细节。因此,我决定创建一些主题,以便我可以记住并在下一个项目中进行复制。这些话题正在增加,而我对这些技术的成功感到沮丧。那时,我想到了写一个帖子的想法,旨在以所有人都可以访问的方式组织所有任务,并在一个地方提供尽可能多的信息。

对于此处执行的操作,有很多文档需要阅读才能获得概念上的理解,而不是本文的目的。在整个帖子中,将出现一些链接,以在出现问题时提供更大的技术支持。

引用:

这篇文章没有什么特别的和创造性的,我相信它的优点在于将有关该技术的各种信息和测试归为一组。

我是具有多年经验的开发人员,但不在基础架构领域。因此,对于某些专家来说,DevOps可以在看到已采取的措施时皱鼻子,随着问题的出现,这些措施按照时间顺序排列。尽管我已经部署了其他几个ASP.NET应用程序,但我还是低估了ASP.NET Core的部署过程,该过程比ASP.NET旧版本复杂得多。我相信,像我一样,有很多开发人员都希望并且需要了解构建应用程序时端到端的工作方式。这些专业人员面临的一个大问题是知道哪些配置职责属于后端安装,什么属于前端。有好几次不知道是通过Web服务器配置(在本例中为IIS)在后端还是在前端上解决问题。要知道问题的根源从何而来,总是很困难地处理。

从理论到实践

这是一个相对简单的应用程序,从一开始就采用的策略是使用最简单的安装进行部署。并且,当我需要一些额外的配置时,我将根据技术文档和其他专业人员的意见采取一些措施。但是,尽管这是一个简单的应用程序,但这不是“ Hello World 因此在通过UI安全地访问数据、访问数据库、用户身份验证等方面存在一些问题和疑虑,但主要是因为我们有两个相互交流的独立应用程序。因此,该过程始于Web API的发布以及已发布文件的副本到Windows 2012 R2服务器的复制,以及Angular构建和程序包的副本到同一服务器的复制。

Web API应用程序(后端)在ASP.NET Core 2.2中实现,使用EntityFramework Core 2.2.6SQL Server Express数据库中实现了数据持久性。Json Web Tokens——JWT也被实现用于通过APICORS对用户进行身份验证,CORS可以防止另一个未经授权的Web页面向我们的应用程序页面的域发出请求。

前端是采用Angular 8.2.3实现,rxjs 6.4.0实现了observates,以订阅web API的端点(GETPOSTPUTDELETEPATCH方法)。这是一个用typescript 3.5实现的简单应用程序,带有4.3.1 bootstrap 和其他接口插件(ngx-bootstrapAngular materialnpmjs等),甚至没有使用延迟加载来优化应用程序加载。要部署Angular接口,请按照文档中的建议执行ng build --prod命令及复制其文件到服务器。Angular构建以优化的格式打包文件,缩小文件大小,禁用特定的开发检查以加快应用程序运行速度。

要使用Microsoft Azure云中的VM,请在开始测试之前,打开两个端口以连接到应用程序。一个用于访问Web API的端口,另一个用于用户界面。因此,您必须创建两个端点,并且可以创建网络过滤器或子网或网络适配器。您可以将控制传入和传出流量的筛选器放在附加到接收流量的资源的网络安全组中。若要了解有关使用Azure门户打开虚拟机端口的更多信息,请执行以下操作:

或有关Azure VM端点配置的更多详细信息:

在对服务器进行这些设置之后,将后端和前端文件适当地复制到服务器中(位于服务器上任意位置的单独文件夹中),现在该为每个应用程序创建一个网站了。我们不会详细介绍IIS中的网站创建过程,只需遵循文档中的建议,此过程通常不会引起问题。但是,在IIS 8中创建两个站点之后,出现了有关前端文件的问题。因为当尝试在Google Chrome浏览器中加载前端时,该应用程序不会呈现主页,而是显示以下消息:

404 - File or directory not found. The resource you are looking for might have been removed, 
had its name changed, or is temporarily unavailable.

此错误是指缺少将Angular中实现的用户界面集成到Web服务器的web.config。实际上,web.config是执行IIS配置的文件,用于应用程序与Web服务器一起使用的参数定义。Angular的构建不指向特定的服务器(在本例中为Internet Information Server-IIS),因为相同的Angular 应用程序也可以与ApacheNginxGolangGithub Pages等一起部署。因此,在生成部署时,必须手动为前端创建一个web.config文件,并将其放置在包含前端文件的同一文件夹中。

1:不带web.config的应用程序主界面的Google Chrome视图

以下是为此目的Angular文档中提取的web.config代码。

<!--?xml version="1.0" encoding="UTF-8"?-->
<configuration>
    <system.webserver>
        <security>
            <authorization>
                <remove roles="" users="*" verbs="">
                <add accesstype="Allow" users="?">
            </add></remove></authorization>
        </security>
        <staticcontent>
            <remove fileextension=".woff">
            <mimemap fileextension=".woff2" mimetype="application/font-woff2">
            <mimemap fileextension=".woff" mimetype="application/x-font-woff">
        </mimemap></mimemap></remove></staticcontent>
        <rewrite>
            <rules>
                <rule name="Angular Routes" stopprocessing="true">
                    <match url=".*">
                    <conditions logicalgrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}"
                        matchtype="IsFile" negate="true">
                        <add input="{REQUEST_FILENAME}"
                             matchtype="IsDirectory" negate="true">
                    </add></add></conditions>
                    <action type="Rewrite" url="/index.html">
                </action></match></rule>
            </rules>
        </rewrite>
    </system.webserver>
</configuration>

*)此代码的第一行已由CodeProject编辑器本身注释。

文档中提供的原始web.config文件通过<rewrite><rules>标记建立了一些规则,以定义IIS中路由的行为。这对于应用程序正常运行至关重要,因为通过重写请求的URL地址及其HTTP响应,它也已添加到web.config标记<staticContent>中,以便IIS 通过该部分识别带有.woff.woff2扩展名的文件。还有其他方法可以使这些选项生效,但是在本示例中,我们将通过在web.config插入的代码来使用这些资源。

2IISAngular应用程序的重写URL部分

仍在谈论前端部署,一些帖子中有关于Angular构建生成的index.html文件的更改的建议。该index.html有一个标记,指定解析与应用程序和资产、静态文件、图像、脚本和其他base href='/'相关的url的基本路径。在某些情况下,如果生产环境具有要在其他应用程序和其他特性中安装的子文件夹,则可以更改此路径。有一些示例将斜杠从基本标记中删除。在尝试解决加载页面问题时,我更改了此标签以尝试其他可能性,并且应用程序完全停止。对于未链接到其他应用程序且在这些情况下不应更改的应用程序,斜杠表示应用程序的根目录。仅在特定情况下,才应更改此标签。

后端和CORS,单独的章节

了解有关Web API项目类型的一些概念,以便在部署中进行正确的设置非常重要。再次,我不会赘述太多,因为ASP.NET Core文档是非常讲究的。对于本示例的后端,它是FDD(与结构有关的部署),其中,使用Windows Server 2012 R2中提供的.NET Core版本部署应用程序。有关这方面的更多信息,请查看此链接,并且要了解有关ASP.NET Core API Web服务的部署类型的更多信息,请单击此链接

InProces是此项目中使用的Web API宿主模型,它已由Visual Studio在创建模板中配置。

<propertygroup>
    <targetframework>netcoreapp2.2</targetframework>
    <aspnetcorehostingmodel>InProcess</aspnetcorehostingmodel>
</propertygroup>

但是,重要的是要知道这种托管类型的一些特征,这样就不会因为它是Visual Studio的项目模板而采用它。该InProcess非常适合在这个项目中使用的架构,因为它使用已配置的IIS HTTP服务器(IISHttpServer),而不是Kestrel服务器。它使用CreateDefaultBuilder调用UseIIS()方法来注册IISHttpServer。这样,服务的Program启动类可以保持不变,无需任何其他配置即可在生产环境中使用。下面的代码段是位于项目根目录下的Program.cs文件的一部分。

public class Program
{
    public static void Main(string[] args)
    {
        CreateWebHostBuilder(args).Build().Run();
    }

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseStartup Startup();
}

通过浏览HTML页面开始运行该应用程序,将显示代码布局、格式和图像。这表明前端安装已正确安装。但是,当开始使用访问后端的功能时,在本示例中为登录页面。在后端插入调用身份验证控制器端点的用户和密码,将出现错误:

main-es2015.fbdfd9b26a7e658d49a6.js:1 Http failure response for 
http://server-sample.cloudapp.net:95/api/auth/login/: 0 Unknown Error.

首先,这种错误类型很难识别,因为浏览器中的消息本身是Unknown Error。在此示例中,它是由于CORS(跨原始资源共享)的配置不正确而发生的,但也可能是由于其配置不足造成的。

3:未知错误

在整个资源计时中使用Google Chrome浏览器的分析工具,可以尝试诊断问题。资源定时显示阶段允许查看客户端请求,直到接收到该请求并将服务器的响应发送到每个已发送的请求为止。也可能会收到与此数据处理相关的性能问题的不同指标。您可以看一下此链接

资源计时在每个请求中呈现几个阶段,从排队请求(如有必要)开始,经过停顿/阻止代理协商“ DNS查找连接已发送SSL请求等待和下载以毫秒为单位显示每个执行的时间。由登录请求生成的发布请求的分析在第一个停止阶段结束,没有显示任何其他阶段,从而向服务器发送了请求过程的中断信号。当请求成功时,将显示一个图表,显示上述每个阶段及其相应的持续时间。

4:使用资源定时

CORS的主要功能是验证通过应用程序向特定Internet资源(后端端点)发出的每个请求,从而验证请求是否被允许。如果没有CORS或其他类似设备,则有可能使应用程序消耗网络上部署的任何服务(如银行、商店、政府机构)的资源。只需要知道所需的URI即可访问。当然,网络上还有其他安全障碍,例如用户身份验证本身。我们可以将CORS理解为浏览器执行的第一个访问障碍,以防止访问未经授权的网络域。同样的,它是运行CORS的浏览器。由于即使没有配置CORS也是如此,因此在通过Postman或其他工具为后端端点运行连接测试时,在前端和后端之间没有分隔的应用程序中,不需要CORS。因为对资源的请求将在同一域内,并且对整个应用程序使用相同的基本URL,所以没有锁。关于此方面的文档,https://developer.mozilla.org/en-US/docs/ Web / HTTP / CORS比这个简单的解释要丰富得多,并且带来了更高层次的细节,因此建议阅读它。

ASP.NET Core中,CORS是在Web API项目的Startup类中的项目根目录下配置的。有几种方法可以配置它,只需在某些搜索引擎中进行一些查询以进行检查即可。该项目采用的形式是在ConfigureServices方法中插入以下代码以及其他代码。

services.AddCors(options =>
{
    options.AddPolicy(_AppCorsPolicy,
        builder =>
        {
            builder.WithOrigins("http://localhost:4200")
                .AllowAnyHeader()
                .AllowAnyMethod();
        });
});

这是通过声明和使用局部变量_AppCorsPolicy来完成的:

readonly string _AppCorsPolicy = "AppCorsPolicy";

_AppCorsPolicy可以分配给UseCors()扩展名,该扩展名插入到Startup类的Configure方法(IapplicationBuilder appIhostingEnvironment env)中。

app.UseCors(_AppCorsPolicy);

关于CORS WithOriginsAllowAnyOrigins扩展的使用存在问题。WithOrigins扩展通过配置的选项列表限制对后端的访问,AllowAnyOrigins允许从任何来源进行访问,这是一种不安全的做法。实际上,这种选择在某些情况下是行不通的,因为AllowAnyOriginsAllowCredentials的规范返回浏览器的无效响应。有几篇文章引发了这种类型的错误,这些帖子显然表明这两个扩展可以正确地一起工作。但AllowAnyOrigin影响预检请求和访问控制允许来源头/头,最佳情况看这里。因此,请远离懒惰,映射将访问后端并使用WithOrigins扩展名的设备的URL 

Startup类的Configure方法中,还可以添加app.UseDefaultFiles()app.UseStaticFiles()方法,以允许IIS通过后端访问用户界面资产文件。另外,请检查是否在IIS中的应用程序的网站上安装了CORS,如果未安装,请安装它。

5Web API IIS站点上的CORS(后端)

ASP.NET Core文档中,建议您为应用程序的控制器使用EnableCors装饰器,请查看此链接。当我在文档中看到此建议时,我感到很害怕,因为由于无法使应用程序在生产环境中正常工作,我认为我必须重写所有控制器,但这不是强制性的。它的使用允许使用多个CORS使用策略。在这种情况下,它在控制器的基类中实现,大大减少了工作量。只需使用Microsoft.AspNetCore.Cors包并装饰所需的类即可。

6:将Microsoft.AspNetCore.Cors添加到后端

引用:

前端没有关于CORS的配置,所有配置都是在后端进行的,它仅负责禁止未经授权的人员访问其自己的资源。

此时,在问题持续了几个小时甚至几天的测试场景中,一些建议和技巧很重要。因此,您应该抵制仅构建应用程序并将仅几个文件复制到服务器的行为,始终发布应用程序并再次复制它们。APP_NAME.deps.json文件的情况取决于launchSettings.json属性的更改或生成可以重新生成它的Startup类,如果未更新,则会影响安装。通过发布应用程序项目,它将生成一个web.config文件。我在web.config中看到了一些建议更改的更改,甚至还做了一些解决了一些问题的更改。但是在某些情况下,更改web.config只会导致问题,并使其尽可能麻烦。因此,不要在您的应用程序中创建web.config,而应由publish为您完成,然后添加应用程序所需的子句。Visual Studio Publish在执行此操作方面似乎非常胜任,至少对于我来说不是那么复杂的应用程序。

以下代码片段(从网络上的一些出版物复制)插入了我的web.config

<httpprotocol>
	<customheaders>
		<add name="Access-Control-Allow-Origin" value="http://localhost:4200">
		<add name="Access-Control-Allow-Credentials" value="true">
		<add name="Access-Control-Allow-Headers" value="*">
		<add name="Access-Control-Allow-Methods" value="*">
	</add></add></add></add></customheaders>
</httpprotocol>

在此示例的应用程序中(不一定会在具有不同IIS配置的其他应用程序中发生这种情况)返回以下错误:

Access to XMLHttpRequest at 'http://server/api;auth/login/' from origin 
'http://localhost:4200' has been blocked by CORS policy: 
Response to preflight request doesn't pass access control check: 
The 'Access-Control-Allow-Origin' header contains multiple values 
'http://localhost:4200, http://localhost:4200/', but only one is allowed.

澄清一下,CORS有两种不同的配置,一种在应用程序(Startup类)中,另一种在web.config。从web.config删除此配置时,仅将Startup类的配置留给CORS,该应用程序将运行,这表明不需要在其他任何地方配置CORS。如果决定采用与此类似的配置,请在IIS中查看HTTP响应标头,该标头必须为空,如下图所示:

7IIS中的HTTP响应标头

Google Chrome控制台上看不到任何错误,表明URL地址带有一个额外的斜杠或类似的内容。错误是很普遍的,常常导致我们做其他一千件事。因此,请用PostmanFiddler检查您的URL,尤其是在将其与环境变量连接时。我花了很多时间,因为我不小心输入了分号而不是斜线。

遵循这些建议,测试应用程序可以对其端点进行测试而没有任何问题。但是,正如我们之前所说,这是一个真正的应用程序,可以访问数据库,具有用户身份验证和授权,具有日志控制以及具有多个第三方工具的体系结构。因此,在解决了CORS设置之后,仍然存在一个错误,其中出现了术语ERR_UNSAFE_PORT的描述。此错误是由于以下事实造成的:此链接中列出了Google Chrome保留了一些特殊服务端口,而我在保留给这些服务的其中一个端口上找到了正确的端口。

这是一个有点困难的经历,但是这样做很有益。正如我从一开始就说过的那样,其目的是为感兴趣的读者提供一些问题的指南,并通过这篇文章提供尽可能多的信息。当然,在许多情况下,我们无法涵盖此文章,但可以通过更正或添加更多信息来随意提供更多信息。这只是尝试促进此类工作的开始。

发布了69 篇原创文章 · 获赞 146 · 访问量 49万+

猜你喜欢

转载自blog.csdn.net/mzl87/article/details/104805429