1 说明:
Cors(跨域)限制中间件可以解决一些Cors(跨域)异常例如:“' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.”。
Cors(跨域)限制中间件更为重要的作用是:
- 通过IP域名端口来限制前端项目对后端项目的Cors(跨域)访问。
- 把物理上分离的前后端项目,在逻辑上统合到同1个域名下(例如:http://localhost:8080), 从而减少异常的产生。
- 如果前端项目是网站应用程序,且前端项目对后端项目Cors(跨域)访问不进行限制,那么程序中只要定义跨域异常处理管道中间件即可;跨域限制依赖注入和管道中间件之AddCors和UseCors可以不定义在程序中。
- 如果前端项目是App应用程序,则必须在后端项目中定义Cors(跨域)限制中间件,且IP域名端口必须是:http://127.0.0.1:8080,而不能是:http://localhost:8080;否则前端App应用项目将不能获取渲染显示数据。
- 当前所有的网站项目都可能有对应的App应用程序,所以最好把跨域限制依赖注入和管道中间件之AddCors和UseCors可以定义在程序中,为需求的扩展留有余地。
- Cors(跨域)限制管道中间件UseCors最好调用在跨域异常处理管道中间件之前,这样更符合管道中间件的调用逻辑;当然两者之间没有必然的前后调用顺序,即使用两者颠倒调用也不会出现逻辑异常,但这违背了两者的“应/答”逻辑。
2 重构appsettings.json
{
"ConnectionStrings": {
//Trusted_Connection=true或Integrated Security=true/SSPI:“Windows凭据”对SQL Server进行身份验证,表示可以在不知道数据库用户名和密码的情况下时,依然可以连接SQL Server数据库。
//"integrated":"security=true是通过“Windows身份认证”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接;表示可以在不知道数据库用户名和密码的情况下时,依然可以连接SQL Server数据库,如果integrated", "security=false","或者不写,表示一定要输入正确的数据库登录名和密码。": null。
//Persist Security Info:该配置只用于通过“SQL Server身份认证”对SQL Server数据库进行身份验证,并与SQL Server数据库进行连接;简单的理解为"ADO在数据库连接成功后是否保存密码信息",True表示保存,False表示不保存.ADO缺省为True(ADO.net缺省为False,未测试,根据参考资料上说的)。
//MultipleActiveResultSets:它允许在单个连接上执行多重的数据库查询或存储过程,目前只适用于Sql Server 2005及其以上版本;如果不用MultipleActiveResultSets ,则一般报错为sqldatareader未关闭,即需要关闭了之后才能打开另一个。
//Trust Server Certificate:是否使用SSL证书和加密方式,对SQL Server数据库的连接字符串进行加密,该操作属性安全性配置,目前只适用于Sql Server 2005及其以上版本;
//"SqlServerWindows": "Data Source=.;Initial Catalog=ShopDemo;Integrated Security=true;MultipleActiveResultSets=true;Trust Server Certificate=True"
//IIS发布部署连接字符串必须使用“SQL Server身份认证”数据库连接方式,才能实现发布部署程序与数据库的CURD的操作
//SqlServer数据库软件的连接字符串。
"ConnectionString": "Data Source=.;Initial Catalog=ShopDemo;Integrated Security=False;Persist Security Info=False;User ID=zz;Password=zz;MultipleActiveResultSets=true;Trust Server Certificate=True",
"DataProvider": "sqlserver",
//Allow User Variables=True:MySql数据库软件是否支持执行带有参数的SQL命令语句,True:支持。
//MySql数据库软件的连接字符串。
// "ConnectionString": "Server=localhost;User ID=root;Password=zhoujian;Database=ShopDemo;Allow User Variables=True",
// "DataProvider": "mysql",
"SQLCommandTimeout": "" //注意该值被设定为:空字符串,在“appsettings.json”中如果设定为:null,则会出现警告信息,即使设定为:空字符串,在反序列化操作时依然会实例化为:null。
},
"CacheConfig": {
"DefaultCacheTime": 60,
"ShortTermCacheTime": 3,
"BundledFilesCacheTime": 120
},
"DistributedCacheConfig": {
"DistributedCacheType": "redis",
"Enabled": true,
//"Name:是别名,可以任意起。
//Ip:是Redis的服务端地址,例如安装本地,就是:127.0.0.1"。
//Port:端口号默认值:6379。
//Password:可以在配置字符串字符串中设置;也可以通过Redis安装的根目录下的配置文件(redis.windows.conf)进行设置,那么该密码就是全局性的。
//connectRetry:连接的超时时后的,自动重新连接次数:3次,注意:该配置只在连接操作时有效。
//syncTimeout:超时会影响redis取值的超时,但是开多个task时,超时设置非常大也解决不了。
//DefaultDatabase:Redis软件的分布式数据库的编号值,一般Redis软件的分布式数据库的编号值默认是:0到15,当前配置为:10。注意:此处的配置使用的是数组,用于将来进行Redis分布式操作的可拓展。
"ConnectionString": "127.0.0.1:6379,ssl=False,connectRetry=3,syncTimeout=10000,DefaultDatabase=10",
//"ConnectionString": "127.0.0.1:6379,ssl=False",
"SchemaName": "dbo",
"TableName": "DistributedCache"
},
"JwtBearerConfig": {
"Issuer": "JwtBearer签发",
"Audience": "Token订阅",
"SecretKey": "8kh2luzmp0oq9wfbdeasygj647vr531n"
},
"CorsLimitConfig": {
"PolicyName": "CorsIpAccess",
"EnableAllIPs": false,
//跨域(Cors)限制的域名及其端口集,用来限定vue/uni-app前端所设定的域名及其端对当前后端程序的访问。
//注意:http://127.0.0.1:1818 和 http://localhost:1818 是不一样的
"IPs": "http://localhost:8080,http://localhost:8081,http://localhost:8082,http://127.0.0.1:8080,http://127.0.0.1:8081,http://127.0.0.1:8082,https://localhost:443"
}
}
3 Framework.Infrastructure.Extensions.ServiceCollectionExtensions. AddCorsLimit
/// <param name="services">.Net(Core)框架内置依赖注入容器实例。</param>
/// <summary>
/// 【添加跨域限制】
/// <remarks>
/// 摘要:
/// 抽离跨域限制中间件实例的依赖注入操作,限制前端“vue/uni-app”项目的域名及其端口从当前程序中获取数据,从而实现页面的渲染显示数据支持。
/// </remarks>
/// </summary>
public static void AddCorsLimit(this IServiceCollection services)
{
//从单例实例的字典成员实例中获取当前程序所有配置相关数据。
AppSettings _appSettings = Singleton<AppSettings>.Instance;
//从应用配置类实例中获取Cors(跨域)限制相关数据。
CorsLimitConfig _corsLimitConfig = _appSettings.Get<CorsLimitConfig>();
//通过AddCors依赖注入中间方法,把Cors(跨域)限制策略依赖中间件实例,注入到.Net(Core)框架默认容器中。
services.AddCors(options =>
{
//如果前端“vue/uni-app”项目的域名及其端口,与“appsettings.json”文件中所限定的域名及其端口,至少有1个相配置,则前端“vue/uni-app”项目就从当前后端项目中获取数据,从而实现页面的渲染显示;否则就不能从当前后端项目中获取数据。
if (!_corsLimitConfig.EnableAllIPs)
{
options.AddPolicy(_corsLimitConfig.PolicyName,
policy =>
{
policy
.WithOrigins(_corsLimitConfig.IPs.Split(','))
.AllowAnyHeader()
.AllowAnyMethod();
});
}
else
{
//不做限定,“appsettings.json”文件中所限定的域名及其端口,不对前端“vue/uni-app”项目的域名及其端口进行限定,即前端“vue/uni-app”项目设定任意的域名及其端口,都能从当前后端项目中获取数据,从而实现页面的渲染显示。
options.AddPolicy(_corsLimitConfig.PolicyName,
policy =>
{
policy
.SetIsOriginAllowed((host) => true)
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials();
});
}
});
}
4 Framework.Infrastructure.Extensions.ApplicationBuilderExtensions. UseCorsLimit
/// <param name="application">.NetCore框架内置管道接口实例。</param>
/// <summary>
/// 【使用跨域限制】
/// <remarks>
/// 摘要:
/// 把Cors(跨域)限制管道中间件实例集成到.NetCore框架内置管道中。
/// </remarks>
/// </summary>
public static void UseCorsLimit(this IApplicationBuilder application)
{
//从单例实例的字典成员实例中获取当前程序所有配置相关数据。
AppSettings _appSettings = Singleton<AppSettings>.Instance;
//从应用配置类实例中获取Cors(跨域)限制相关数据。
CorsLimitConfig _corsLimitConfig = _appSettings.Get<CorsLimitConfig>();
//Cors(跨域)限制中间件可以解决一些Cors(跨域)异常例如:“' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.”。
//Cors(跨域)限制中间件更为重要的作用是:
// 1、通过IP域名端口来限制前端项目对后端项目的Cors(跨域)访问。
// 2、把物理上分离的前后端项目,在逻辑上统合到同1个域名下(例如:http://localhost:8080), 从而减少异常的产生。
// 3、如果前端项目是网站应用程序,且前端项目对后端项目Cors(跨域)访问不进行限制,那么程序中只要定义跨域异常处理管道中间件即可;跨域限制依赖注入和管道中间件之AddCors和UseCors可以不定义在程序中。
// 4、如果前端项目是App应用程序,则必须在后端项目中定义Cors(跨域)限制中间件,且IP域名端口必须是:http://127.0.0.1:8080,而不能是:http://localhost:8080;否则前端App应用项目将不能获取渲染显示数据。
// 5、当前所有的网站项目都可能有对应的App应用程序,所以最好把跨域限制依赖注入和管道中间件之AddCors和UseCors可以定义在程序中,为需求的扩展留有余地。
// 6、Cors(跨域)限制管道中间件UseCors最好调用在跨域异常处理管道中间件之前,这样更符合管道中间件的调用逻辑;当然两者之间没有必然的前后调用顺序,即使用两者颠倒调用也不会出现逻辑异常,但这违背了两者的“应 / 答”逻辑。
application.UseCors(_corsLimitConfig.PolicyName);
}
5 Framework.Infrastructure.CorsLimitStartup
using Core.Infrastructure;
using Framework.Infrastructure.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace Framework.Infrastructure
{
/// <summary>
/// 【跨域限制启动--类】
/// <remarks>
/// 摘要:
/// 通过该类中的方法成员,抽离跨域限制的依赖注入和管道中间件,为限制前端“vue/uni-app”项目的域名及其端口从当前程序中获取数据,从而实现页面的渲染显示数据支持。
/// </remarks>
/// </summary>
public class CorsLimitStartup : IStartup
{
#region 属性--接口实现
/// <summary>
/// 【顺序】
/// <remarks>
/// 摘要:
/// 获取跨域限制启动类中管道中间件实例,被集成到内置管道实例中的顺序,默认值:200。
/// 注意:
/// .NetCore框架默定义了一些常用的内置管道中间件,并默认规定了这些内置管道中间件实例在内置管道实例中被调用的顺序,
/// 如果不按照该默认顺序调用这些内置管道中间件,在程序执行时就会出现逻辑异常。
/// </remarks>
/// </summary>
public int Order => 200;//注意:Cors(跨域)限制管道中间件UseCors最好调用在跨域异常处理管道中间件之前,这样更符合管道中间件的调用逻辑;当然两者之间没有必然的前后调用顺序,即使用两者颠倒调用也不会出现逻辑异常,但这违背了两者的“应/答”逻辑。
#endregion
#region 方法--接口实现
/// <param name="services">.Net(Core)框架内置依赖注入容器实例。</param>
/// <param name="configuration">.NetCore框架内置配置接口实例(存储着当前程序中所有*.json文件中的数据)。</param>
/// <summary>
/// 【配置服务】
/// <remarks>
/// 摘要:
/// 通过该方法成员,抽离跨域限制中间件实例的依赖注入操作,限制前端“vue/uni-app”项目的域名及其端口从当前程序中获取数据,从而实现页面的渲染显示数据支持。
/// </remarks>
/// </summary>
public void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddCorsLimit();
}
/// <param name="application">.NetCore框架内置管道接口实例。</param>
/// <summary>
/// 【配置】
/// <remarks>
/// 摘要:
/// 该方法把Cors(跨域)限制管道中间件实例集成到.NetCore框架内置管道中。
/// </remarks>
/// </summary>
public void Configure(IApplicationBuilder application)
{
application.UseCorsLimit();
}
#endregion
}
}
6 第1阶段总结
到本章为止对于后端项目的整合抽象已经完成,即后端项目的整个框架已经搭建完成,之后是根据前端项目的功能和业务需求向后端项目填充相应的定义实现。
对以上功能更为具体实现和注释见:230208_032shopDemo(跨域(Cors)限制配置的定义实现)。