c# - 目录不存在 - 参数名称 : directoryVirtualPath - IT工具网

mikel阅读(315)

来源: c# – 目录不存在 – 参数名称 : directoryVirtualPath – IT工具网

我正在使用 Visual Studio Express 2012 RC。

  • 如果创建一个空白的“hello world MVC 4.5 项目”
  • 我将它降级到 4.0,以便它与我的主机 (Arvixe) 兼容
  • 我将它发布给主机。

然后我收到此错误消息,我可以在网上找到有关它的任何信息。

Server Error in '/' Application.

Directory does not exist.
Parameter name: directoryVirtualPath

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ArgumentException: Directory does not exist.
Parameter name: directoryVirtualPath

Source Error: 

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace: 


[ArgumentException: Directory does not exist.
Parameter name: directoryVirtualPath]
   System.Web.Optimization.Bundle.IncludeDirectory(String directoryVirtualPath, String searchPattern, Boolean searchSubdirectories) +357
   System.Web.Optimization.Bundle.Include(String[] virtualPaths) +287
   IconBench.BundleConfig.RegisterBundles(BundleCollection bundles) +75
   IconBench.MvcApplication.Application_Start() +128

[HttpException (0x80004005): Directory does not exist.
Parameter name: directoryVirtualPath]
   System.Web.HttpApplicationFactory.EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app) +9160125
   System.Web.HttpApplication.RegisterEventSubscriptionsWithIIS(IntPtr appContext, HttpContext context, MethodInfo[] handlers) +131
   System.Web.HttpApplication.InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context) +194
   System.Web.HttpApplicationFactory.GetSpecialApplicationInstance(IntPtr appContext, HttpContext context) +339
   System.Web.Hosting.PipelineRuntime.InitializeApplication(IntPtr appContext) +253

[HttpException (0x80004005): Directory does not exist.
Parameter name: directoryVirtualPath]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +9079228
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +97
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +256

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.237

这是什么意思?

按要求编码^^

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return Content("Hello world");
    }
}

那是我添加的唯一代码。

application_start代码

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
    }
}

路由配置

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

过滤配置

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

捆绑配置

 public class BundleConfig
{
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                    "~/Scripts/jquery-1.*"));

        bundles.Add(new ScriptBundle("~/bundles/jqueryui").Include(
                    "~/Scripts/jquery-ui*"));

        bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
                    "~/Scripts/jquery.unobtrusive*",
                    "~/Scripts/jquery.validate*"));

        bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
                    "~/Scripts/modernizr-*"));

        bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));

        bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
                    "~/Content/themes/base/jquery.ui.core.css",
                    "~/Content/themes/base/jquery.ui.resizable.css",
                    "~/Content/themes/base/jquery.ui.selectable.css",
                    "~/Content/themes/base/jquery.ui.accordion.css",
                    "~/Content/themes/base/jquery.ui.autocomplete.css",
                    "~/Content/themes/base/jquery.ui.button.css",
                    "~/Content/themes/base/jquery.ui.dialog.css",
                    "~/Content/themes/base/jquery.ui.slider.css",
                    "~/Content/themes/base/jquery.ui.tabs.css",
                    "~/Content/themes/base/jquery.ui.datepicker.css",
                    "~/Content/themes/base/jquery.ui.progressbar.css",
                    "~/Content/themes/base/jquery.ui.theme.css"));
    }
}

 

最佳答案

 

似乎这个错误源于“不包括您应用程序目录中的所需文件”或将您的代码上传到未配置为虚拟目录的目录中, 甚至在不正确的目录中。

 

关于C# – 目录不存在 – 参数名称 : directoryVirtualPath,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11333137/

localStorage使用总结_读取localstorage时按照写入顺序全部读出-CSDN博客

mikel阅读(382)

来源: localStorage使用总结_读取localstorage时按照写入顺序全部读出-CSDN博客

localStorage使用总结

一、什么是localStorage、sessionStorage

HTML5中,新加入了一个localStorage特性,这个特性主要是用来作为本地存储来使用的,解决了cookie存储空间不足的问题(cookie中每条cookie的存储空间为4k),localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同。

 

二、localStorage的优势与局限

localStorage的优势

1、localStorage拓展了cookie的4K限制

2、localStorage会可以将第一次请求的数据直接存储到本地,这个相当于一个5M大小的针对于前端页面的数据库,相比于cookie可以节约带宽,但是这个却是只有在高版本的浏览器中才支持的

localStorage的局限

1、浏览器的大小不统一,并且在IE8以上的IE版本才支持localStorage这个属性

2、目前所有的浏览器中都会把localStorage的值类型限定为string类型,这个在对我们日常比较常见的JSON对象类型需要一些转换

3、localStorage在浏览器的隐私模式下面是不可读取的

4、localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡

5、localStorage不能被爬虫抓取到

localStorage与sessionStorage的唯一一点区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空

这里我们以localStorage来分析

 

三、localStorage的使用

localStorage的浏览器支持情况:

这里要特别声明一下,如果是使用IE浏览器的话,那么就要UserData来作为存储,这里主要讲解的是localStorage的内容,所以userData不做过多的解释,而且以博主个人的看法,也是没有必要去学习UserData的使用来的,因为目前的IE6/IE7属于淘汰的位置上,而且在如今的很多页面开发都会涉及到HTML5\CSS3等新兴的技术,所以在使用上面一般我们不会去对其进行兼容

首先在使用localStorage的时候,我们需要判断浏览器是否支持localStorage这个属性

if(!window.localStorage){
            alert("浏览器支持localstorage");
            return false;
        }else{
            //主逻辑业务
        }

 

localStorage的写入,localStorage的写入有三种方法,这里就一一介绍一下

if(!window.localStorage){
            alert("浏览器支持localstorage");
            return false;
        }else{
            var storage=window.localStorage;
            //写入a字段
            storage["a"]=1;
            //写入b字段
            storage.a=1;
            //写入c字段
            storage.setItem("c",3);
            console.log(typeof storage["a"]);
            console.log(typeof storage["b"]);
            console.log(typeof storage["c"]);
        }

 

运行后的结果如下:

这里要特别说明一下localStorage的使用也是遵循同源策略的,所以不同的网站直接是不能共用相同的localStorage

最后在控制台上面打印出来的结果是:

不知道各位读者有没有注意到,刚刚存储进去的是int类型,但是打印出来却是string类型,这个与localStorage本身的特点有关,localStorage只支持string类型的存储。

localStorage的读取

if(!window.localStorage){
            alert("浏览器支持localstorage");
        }else{
            var storage=window.localStorage;
            //写入a字段
            storage["a"]=1;
            //写入b字段
            storage.a=1;
            //写入c字段
            storage.setItem("c",3);
            console.log(typeof storage["a"]);
            console.log(typeof storage["b"]);
            console.log(typeof storage["c"]);
            //第一种方法读取
            var a=storage.a;
            console.log(a);
            //第二种方法读取
            var b=storage["b"];
            console.log(b);
            //第三种方法读取
            var c=storage.getItem("c");
            console.log(c);
        }

 

这里面是三种对localStorage的读取,其中官方推荐的是getItem\setItem这两种方法对其进行存取,不要问我这个为什么,因为这个我也不知道

我之前说过localStorage就是相当于一个前端的数据库的东西,数据库主要是增删查改这四个步骤,这里的读取和写入就相当于增、查的这两个步骤

下面我们就来说一说localStorage的删、改这两个步骤

改这个步骤比较好理解,思路跟重新更改全局变量的值一样,这里我们就以一个为例来简单的说明一下

 

if(!window.localStorage){
            alert("浏览器支持localstorage");
        }else{
            var storage=window.localStorage;
            //写入a字段
            storage["a"]=1;
            //写入b字段
            storage.b=1;
            //写入c字段
            storage.setItem("c",3);
            console.log(storage.a);
            // console.log(typeof storage["a"]);
            // console.log(typeof storage["b"]);
            // console.log(typeof storage["c"]);
            /*分割线*/
            storage.a=4;
            console.log(storage.a);
        }

这个在控制台上面我们就可以看到已经a键已经被更改为4了

localStorage的删除

1、将localStorage的所有内容清除

var storage=window.localStorage;
            storage.a=1;
            storage.setItem("c",3);
            console.log(storage);
            storage.clear();
            console.log(storage);

 

 

2、 将localStorage中的某个键值对删除

 

var storage=window.localStorage;
            storage.a=1;
            storage.setItem("c",3);
            console.log(storage);
            storage.removeItem("a");
            console.log(storage.a);

 

控制台查看结果

localStorage的键获取

var storage=window.localStorage;
            storage.a=1;
            storage.setItem("c",3);
            for(var i=0;i<storage.length;i++){
                var key=storage.key(i);
                console.log(key);
            }

 

使用key()方法,向其中出入索引即可获取对应的键

 

四、localStorage其他注意事项

一般我们会将JSON存入localStorage中,但是在localStorage会自动将localStorage转换成为字符串形式

这个时候我们可以使用JSON.stringify()这个方法,来将JSON转换成为JSON字符串

示例:

if(!window.localStorage){
            alert("浏览器支持localstorage");
        }else{
            var storage=window.localStorage;
            var data={
                name:'xiecanyong',
                sex:'man',
                hobby:'program'
            };
            var d=JSON.stringify(data);
            storage.setItem("data",d);
            console.log(storage.data);
        }

 

读取之后要将JSON字符串转换成为JSON对象,使用JSON.parse()方法

var storage=window.localStorage;
            var data={
                name:'xiecanyong',
                sex:'man',
                hobby:'program'
            };
            var d=JSON.stringify(data);
            storage.setItem("data",d);
            //将JSON字符串转换成为JSON对象输出
            var json=storage.getItem("data");
            var jsonObj=JSON.parse(json);
            console.log(typeof jsonObj);

打印出来是Object对象

另外还有一点要注意的是,其他类型读取出来也要进行转换

解决"此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站"的问题 - 五粮液和 - 博客园

mikel阅读(405)

来源: 解决”此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站”的问题 – 五粮液和 – 博客园

ASP.NET MVC项目中,使用AJAX向控制器发送GET请求获取JSON数据时,出现这个错误:”此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet”。

错误截图:此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站

其实从返回的这个错误信息我们已经可以知道解决方法了,看这个信息:”因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站“,说明我们只要使用POST请求就可以了。后面的 “若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet”,这是提示第二种解决方法,就是设置JSON结果对象使其允许来自客户端的 HTTP GET 请求。以下为具体解决方法:

方法一 使用POST请求来调用控制器,从而获取JSON数据

原来发送ajax请求的前台JS代码如下:

    /*可以看到type 设置的是GET请求*/
    $.ajax({
        type:'GET',
        url: '/Home/AjaxGetJsonData',            
        success: function (data) {
            alert(data);
        },
        error: function (error) {                
            alert(error.responseText);
        }
    });

或者

    $.get('/Home/AjaxGetJsonData', null, function (data) {
        alert(data);
    });

那么我们只要将代码更改为下面两种任意一种就可以了:

    /*这里更改了ajax的参数 type 为POST ,发送POST请求就不会报错了*/
    $.ajax({
        type: 'POST',
        url: '/Home/AjaxGetJsonData',
        success: function (data) {
            alert(data);
        },
        error: function (error) {
            alert(error.responseText);
        }
    });

或者

    /*也可以直接使用$.post方法进行ajax调用*/
    $.post('/Home/AjaxGetJsonData', null, function (data) {
        alert(data);
    });

方法二 在控制器返回的JSON结果对象里,设置JsonRequestBehavior.AllowGet(允许来自客户端的 HTTP GET 请求)

原来控制器中的代码如下:

    public ActionResult AjaxGetJsonData()
    {
        string strData = "测试数据";
        return Json(strData);   
    }

更改后的代码如下 :

    public ActionResult AjaxGetJsonData()
    {
        string strData = "测试数据";
        //这里我们设置了第二个参数JsonRequestBehavior为AllowGet
        return Json(strData,JsonRequestBehavior.AllowGet);   
    }

我们可以看到在最后return Json(list, JsonRequestBehavior.AllowGet)中增加了第二个参数JsonRequestBehavior.AllowGet,默认是JsonRequestBehavior.DenyGet。之所以我们要在这里设置允许HTTP GET请求,是因为ASP.NET MVC为了预防一个网站信息泄漏的漏洞,所以默认是禁止客户端的HTTP GET 请求的。这是一个很出名的漏洞,名字是:JSON 劫持漏洞,所以我建议AJAX还是使用POST请求来获取数据,防止重要的信息被恶意攻击者窃取。

这里是MSDN文档的具体说明:允许 GET 请求可能会导致用户在某一网站中仍处于已登录状态时访问另一个网站。 这可能会生成导致信息泄漏的安全漏洞。有关此漏洞的信息,请参见 Phil Haack 的博客上的文章 JSON Hijacking,文章是英文的,我已经翻译,点击此链接:JSON劫持漏洞(详细讲解利用JSON从而进行数据劫持的漏洞攻防策略),另外还可以查看这篇文章:JSON劫持漏洞分析和攻防演练

php Illegal string offset 'name'-CSDN博客

mikel阅读(382)

来源: php Illegal string offset ‘name’-CSDN博客

上面代码可以输出值,但是报错Warning: Illegal string offset ‘name’ in ,原因是$person数组里面有空数组,空数组里没有name这个字段。最终解决办法是在 foreach 下面加个判断 if(is_array($value)),这样就搞定了。

$name = array();
foreach ($person as $value) {
if(is_array($value))
{
$name[] = $value[‘name’];
}

}

————————————————
版权声明:本文为CSDN博主「醉雨轩^_^」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/miao0967020148/article/details/83215275

将WebAPI部署在IIS上_webapi发布到iis-CSDN博客

mikel阅读(463)

来源: 将WebAPI部署在IIS上_webapi发布到iis-CSDN博客

这篇文章用的是VS2019中的ASP.NET Core Web应用程序中默认的.netcore3.1 WebAPI demo。用这个默认demo的原因就是,大家情况错综复杂,很难找到一篇适合自己的文章,也不知道自己究竟错在哪里,不好排除。用默认的demo来做展示,如果你可以做出来,可以保证你的错误不是由于你代码造成,可以帮助大家排除一部分问题,废话不多说,下面开始。

我使用的是VS2019社区版,WebAPI的版本是.netcore3.1,其他版本可能略有不同,请根据情况适当更改。

1.打开https://dotnet.microsoft.com/download/dotnet-core/3.1,点击Hosting Bundle下载安装,安装好后重启电脑。

2.打开IIS,双击模块。

3.查看是否存在ASP.NET Core Module v2,若不存在请重新安装。

4.打开VS2019,新建项目,选择ASP.NET Core Web应用程序,点击下一步。

5.随便起个名字,点击创建。

6.选择API,点击创建。
7.下拉,选择你项目的名字,然后运行。

8.运行成功后,会出现如下图所示:

9.在项目上右键,点击发布,选择文件夹,点击下一步。

10.点击完成。

11.点击发布,输出栏会显示发布成功。

12.打开IIS,右键网站,添加网站

13.网站名称随便写;应用程序池选择DefaultAppPool;物理路径就是第11步中,下方输出栏里显示的蓝色字体的发布路径(自己去选择路径,不要直接粘贴);类型选择https;端口号随便设置(不要设置成正在使用的端口);IIS证书选择IIS Express Development Certificate;设置好后,点击确定。

14.点击浏览。

15.出现如下图的错误:

16.找到发布的文件夹:

17.右键publish文件夹,选择属性,选择安全,点击编辑。

18.点击添加。

19.输入:计算机名\IIS_IUSRS(计算机名不知道的,右键桌面上“此电脑”快捷方式,选择属性,查看计算机名),点击检查名称,然后点击确定。

20.勾选读取权限,已勾选则不做改变,然后点击确定。

21.切换到常规栏,取消勾选“只读”复选框,点击确定。

22.点击确定。

23.再次浏览网站(第14步)。

24.在网站后添加 /weatherforecast ,刷新,成功!

————————————————
版权声明:本文为CSDN博主「斯 钦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44884379/article/details/112466063

.net core 的跨域报错“has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.”

mikel阅读(300)

webapi单独项目,vue的项目需要调用webapi的接口,出现:

“has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.”

需要修改.net core webapi的Program.cs的跨域策略:

region 跨域

builder.Services.AddCors(cor =>
{
cor.AddPolicy(“Cors”, policy =>
{
policy
//.WithOrigins(“https://localhost:15911”, “http://0.0.0.0:3201”)// 允许部分站点跨域请求
.AllowAnyOrigin()// 允许所有站点跨域请求
.AllowAnyHeader()// 允许所有请求头
//.AllowCredentials() // 允许Cookie信息,这句中途出过问题删了就好了,没查出原因
.AllowAnyMethod();// 允许所有请求方法
});
});

endregion

app.UseHttpsRedirection();
// 设置跨域
app.UseCors(“Cors”);

app.UseAuthorization();

app.MapControllers();

app.Run();

不是所有的 No 'Access-Control-Allow-Origin' header... 都是跨域问题 - 记一次图片上传踩坑 - 知乎

mikel阅读(267)

来源: 不是所有的 No ‘Access-Control-Allow-Origin’ header… 都是跨域问题 – 记一次图片上传踩坑 – 知乎

什么是跨域 ?

跨域这个问题大家并不陌生,这也是面试的高频问题,很多人都背过,什么因为同源策略啊,CORS 啊等等,跨域的标致就是浏览器控制台出现 Access to XMLHttpRequest at 'https://xxx.xxx.com' from origin 'https://xxx.xxx.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
首先,只有 Web 浏览器才会产生跨域,这是因为浏览器的同源策略在限制。同源策略就是 [域名(又称为主机 host),端口(port),协议(protocol)] 要统一,否则就会被浏览器判定为跨域,然后拒绝请求。但是严格的说,浏览器并不是拒绝所有的跨域请求,实际上拒绝的是跨域的读操
同源策略并不是不好,它在一定程度上保证了浏览器的安全,只是无法适应现代的潮流,在工程服务化后,不同职责的服务分散在不同的工程中,往往这些工程的域名是不同的,但一个需求可能需要对应到多个服务,这时便需要调用不同服务的接口。

哪些情况下会产生跨域 ?

URL                             说明                是否允许通信
http://www.a.com/a.js
http://www.a.com/b.js           同一域名下            允许

http://www.a.com/lab/a.js
http://www.a.com/script/b.js    同一域名下不同文件夹    允许

http://www.a.com:8000/a.js
http://www.a.com/b.js           同一域名,不同端口      不允许

http://www.a.com/a.js
https://www.a.com/b.js          同一域名,不同协议      不允许

http://www.a.com/a.js
http://70.32.92.74/b.js         域名和域名对应ip        不允许

http://www.a.com/a.js
http://script.a.com/b.js        主域相同,子域不同      不允许(cookie这种情况下也不允许访问)

http://www.a.com/a.js
http://a.com/b.js               同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)

http://www.cnblogs.com/a.js
http://www.a.com/b.js           不同域名            不允许

什么是 CORS ?

跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的 Web 应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。 比如,站点 http://domain-a.com 的某 HTML 页面通过 <img> 的 src 请求 http://domain-b.com/image.jpg。网络上的许多页面都会加载来自不同域的 CSS 样式表,图像和脚本等资源。
出于安全原因,浏览器限制从脚本内发起的跨源 HTTP 请求。 例如,XMLHttpRequest 和 Fetch API 遵循同源策略。 这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。

跨域资源共享( CORS )机制允许 Web 应用服务器进行跨域访问控制,从而使跨域数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch )使用 CORS,以降低跨域 HTTP 请求所带来的风险。

不过呢,并不一定是浏览器限制了发起跨站请求,也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。
在“上古时代”,解决跨域有很多黑科技,什么 JSONP 啊,window.name 啊,document.domain 啊等等都用上了,但现代用的基本都是CORS跨域,所以上述方法在这里就不讨论了。
由上述可知,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
虽然工作重心在后端,但是作为前端,也要了解这方面的知识,否则就会出现204预请求,然后后端没处理,就甩锅给前端的情况。
下面介绍一些 CORS 过程中常见的 HTTP 响应头(Response Headers)。

什么是 Access-Control-Allow-Origin ?
这是 HTTP 响应首部中的一个字段,
具体格式是: Access-Control-Allow-Origin: <origin> | *
其中,origin 参数的值指定了允许访问该资源的外域 URI。对于不需要携带身份凭证的请求,服务器可以指定该字段的值为通配符,表示允许来自所有域的请求。
如果服务端指定了具体的域名而非*,那么响应首部中的 Vary 字段的值必须包含 Origin。这将告诉客户端:服务器对不同的源站返回不同的内容。例如:


// 只响应来自 http://mozilla.com 的请求
Access-Control-Allow-Origin: http://mozilla.com

什么是 Access-Control-Allow-Methods ?
该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。
具体格式是:Access-Control-Allow-Methods: <method>[, <method>]*
什么是 Access-Control-Allow-Headers ?
可支持的请求首部名字。请求头会列出所有支持的首部列表,用逗号隔开。
如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。
具体格式是:Access-Control-Allow-Headers: <header-name>[, <header-name>]*
什么是 Access-Control-Allow-Credentials ?
该字段可选。它的值是一个布尔值,表示是否允许发送 Cookie。默认情况下,Cookie 不包括在 CORS 请求之中。设为 true,即表示服务器明确许可,Cookie 可以包含在请求中,一起发给服务器。
浏览器的正常请求和回应
一旦服务器通过了”预检”请求,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样,会有一个 Origin 头信息字段。服务器的回应,也都会有一个 Access-Control-Allow-Origin 头信息字段。
好了,铺垫完成,接下来要说说我踩的坑了。

问题实记
项目背景
公司因历史遗留,同时存在3种后端语言:Java,PHP,Node.js,因为后端同事都不懂 Node.js,所以 Node 项目一直是前端维护。老项目用的是 Koa 框架,之前我在上面写逻辑,上传图片是没有问题的,直到我用了 Nest 框架重构,将后台管理系统的逻辑拆分解耦出来。
踩坑过程
新项目一切请求都正常,本地跑的时候也正常,但是到了线上,只有上传图片不正常。每次上传都会预请求一次 204 OPTIONS,这一步没问题,但接下来的 POST 请求就有问题了:

我一看控制台的信息,结合多年的开发经验(其实并没有),这不就是跨域嘛,于是看代码,main.ts 中已经有了 app.enableCors(),百思不得其解,于是 Google,发现也有人遇到过类似的问题,说是 Nest 某些版本在线上环境无法正确使用 CORS,然后就形成了下列代码:

但是,并没有什么卵用,调试了好一会儿才注意到响应头是 nginx 返回的,然后就像发现新大陆一样屁颠屁颠的找运维老大:代码里面已经设置了 CORS 跨域了,是不是被 nginx 拦截了?(公司的服务器通过 nginx 做负载均衡,然后才到 node)
然后运维老大很配合的帮我配置了 nginx 的跨域,然后就悲剧了,连 OPTIONS 都过不去 :

控制台的大致意思是 CORS 规则冲突了,只能使用一种。

所以这个问题其实和 nginx 没有什么关系,运维大佬看了访问日志,说是 OPTIONS 请求是响应了的,但是到 POST 请求的时候就断开连接了,然后让我试试直接访问端口,于是控制台又出现了如下信息:

唔,大致意思是,源头是 https 协议的话,就不能请求 http 协议的资源。
于是我把网站上的 https 换成 http,就出现了如下信息:

我就觉得很奇怪,因为本地开发的时候,是能正常上传图片的。唯一不同的地方就在于,线上使用的是 pm2 进程管理工具,而我本地用的是自带的 nodemon。为了验证我的猜测,于是自己的电脑上也装了 pm2,然后跑起来,然后就。。。Bug 果然复现了。
于是让运维大佬不用 pm2 直接用 nodemon 启动试试,然后折腾我很久的跨域问题就“解决了”。为什么打引号呢,因为运维大佬并不是很想用 nodemon 来管理进程,主要是如果服务器宕机,不能自动拉起,战役还远没有结束。
然后我就围绕着 pm2 继续探索,把官方文档看了个遍,也没找到关键点,郁闷之下,只好检查的 pm2 启动配置,然后注意到这个:

这是当初我为了输出日志的时候,更新了文件,防止被 pm2 监听到,导致服务一直重启所做的措施。然后就想到了,我上传图片的时候,是先在硬盘保存,然后读取 Buffer 流,然后再上传到 oss,最后删掉硬盘的图片,核心代码如下:

 

所以我就在想,是不是因为上传的时候,存本地的图片触发了 pm2 的监听,导致服务重启,所以就会报 net::ERR_CONNECTION_RESET,于是我改成了临时目录 const uploadCachePath = '/tmp/assets/uploads'; (Mac OS、Linux 都有这个目录),然后 pm2 启动,上传,成功。

至此,折磨了我近一周的 Bug 终于修复,结果和跨域没有半毛钱关系。

插曲
有读者可能注意到 /tmp/assets/uploads 路径,要是同事用的是 Windows 系统开发咋办?这个我自然也想到了,于是改了 pm2 的启动项:

可是无论怎样改,依然会触发上述 Bug,因为服务器同时跑着 2 个 Node 项目,另一个项目也有自己的 pm2 启动项,所以感觉这个配置被另一个覆盖了,pm2 似乎是全局的。如果有其他大神深入了解过 pm2 的可以指点一下。
所以和运维大佬讨论了一下,给我开了权限,就暂时用这个临时目录,待以后找到更好的解决方案再优化,反正目前这个项目也只有我一人在维护。
遇到的其他场景
1. 服务器宕机
就在我刚找到解决方案的时候,我带的小弟跑过来问我是不是动了配置文件,老项目怎么都跨域了。我去看他的控制台,确实有 Access to ... has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. 的信息,由于刚踩的坑,何况我也没动过配置文件,所以觉得这肯定不是跨域问题。然后我看了服务器的日志,发现一直在重启,因为有个模块他没同步上去,只同步了路由文件,导致路由找不到对应的函数,服务就一直在报错重启,根本就没处理请求。于是让他把代码重新上传,问题解决。
所以个人猜测(因为没有权限看服务器的配置),这次跨域是 nginx 代理的时候,因为访问不到 Node 服务,所以自然而然地就读不到 CORS 配置,然后报跨域错误。
2. Axios 的自行检查
Axios 创建实例时,有个字段需要注意:

如果不设为 false,则会得到下面报错:

原因就是前面提到的 Access-Control-Allow-Credentials 字段,CORS 请求默认不发送 Cookie 和 HTTP 认证信息。如果要把 Cookie 发到服务器,一方面要服务器同意:
Access-Control-Allow-Credentials: true

另一方面,开发者必须在 AJAX 请求中打开 withCredentials 属性,也就是 Axios 默认打开的 withCredentials: true
否则,即使服务器同意发送 Cookie,浏览器也不会发送。或者,服务器要求设置 Cookie,浏览器也不会处理。
但是,如果省略withCredentials设置,有的浏览器还是会一起发送 Cookie。这时,需要显示关闭 withCredentials: false
需要注意的是,如果要发送 Cookie,Access-Control-Allow-Origin 就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie 依然遵循同源政策,只有用服务器域名设置的 Cookie 才会上传,其他域名的 Cookie 并不会上传,且(跨源)原网页代码中的 document.cookie 也无法读取服务器域名下的 Cookie。
总结
由上述可以总结,在后端配置了 CORS 的情况下,还会造成 Access to ... has been blocked by CORS policy ... 的情况大致有:

  1. 服务器突然重启,导致代理服务器转发中断;
  2. 服务器宕机,导致代理服务器读不到 CORS 配置;
  3. Axios 等请求插件设置了withCredentials: true,导致先行验证并拦截了请求;

有些时候,浏览器控制台给出的错误信息,不一定能真正地指出问题的所在,做为前端,还需要多去了解一些更本质的东西。

分享一些PDF文档书籍教程电子书,面试题,开发工具,视频等免费下载,想要学习java或者想要转行的小伙伴可以去看看,对于新人比较友好

十一、Net Core Api解决跨域问题(vs2022)_withorigins-CSDN博客

mikel阅读(297)

来源: 十一、Net Core Api解决跨域问题(vs2022)_withorigins-CSDN博客

修改Program.cs,注意自己调整位置

#region 跨域
builder.Services.AddCors(cor =>
{
cor.AddPolicy(“Cors”, policy =>
{
policy
//.WithOrigins(“https://localhost:15911”, “http://0.0.0.0:3201”)// 允许部分站点跨域请求
.AllowAnyOrigin()// 允许所有站点跨域请求
.AllowAnyHeader()// 允许所有请求头
//.AllowCredentials() // 允许Cookie信息,这句中途出过问题删了就好了,没查出原因
.AllowAnyMethod();// 允许所有请求方法
});
});
#endregion

app.UseCors(“Cors”);
SingalR跨域时Origin不能默认*,正好吃那个跨域也可以用下面这个

builder.Services.AddCors(options =>
{
options.AddDefaultPolicy(
builder =>
{
builder.WithOrigins(“http://192.168.5.73:8848”)
.AllowAnyHeader()
.WithMethods(“GET”, “POST”)
.AllowCredentials();
});
});

app.UseCors();

————————————————
版权声明:本文为CSDN博主「Eterno·Y」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37894611/article/details/124167762

webapi 跨域 (MVC-Web API: 405 method not allowed问题 ) - 月下之神 - 博客园

mikel阅读(312)

来源: webapi 跨域 (MVC-Web API: 405 method not allowed问题 ) – 月下之神 – 博客园

使用webapi cors

1.安装包:Install-Package Microsoft.AspNet.WebApi.Cors –IncludePrerelease

2.在webapiconfig.cs中增加如下代码。

1
2
var cors = new EnableCorsAttribute("*""*""*");
            config.EnableCors(cors);

3.ajax请求示例代码

复制代码
        $.ajax({
            url: 'http://127.0.0.1:8080/Api/Areas/XfFeedBack/PostFeedBack',
            //url: '/Api/Areas/XfFeedBack/PostFeedBack',
            type: "POST",
            data: JSON.stringify(obj),
            datatype:"json",
            contentType: "application/json; charset=utf-8",
            headers: {
                "signature": "xunfast@123!"
            },
            success: function (data) {
                console.log(data);
            }
        });
复制代码
复制代码
  $.ajax({
            //url: "http://127.0.0.1:8080/Api/Areas/SysNewsInfo/GetNewsInfoPage?pageIndex=1&pageSize=10&title=''&type=0",
            url: "/Api/Areas/SysNewsInfo/GetNewsInfoPage?pageIndex=1&pageSize=10&title=" + $("#title").val() + "&type=0",
            type: "GET",
            datatype: "json",
            headers: {
                "signature": "xunfast@123!"
            },
            success: function (data) {
                console.log(data);
            }
        });
复制代码
//单个传参,引号不用给具体名称,给名称反而值传不过去(不清楚原因)
        $.post('http://127.0.0.1:8080/Api/Areas/SysNewsInfo/NewsInfoById', { "": 1 }, function (data) {
            console.info(data);
        });

 

良田高拍仪无法拍照常见的几个问题 – 前端知识点

mikel阅读(854)

来源: 良田高拍仪无法拍照常见的几个问题 – 前端知识点

一、确定问题(必看)

首先我们要先确定是什么问题。(谷歌浏览器示例)
1. 第一步:当前页面鼠标右键,选择检查

2. 第二步:选中弹出窗口中的【console】中文名是【控制台


3. 第三步:刷新页面,点击拍照上传,然后查看console有无输出错误信息

二、 问题分析

1、错误1如下图(console中有红色错误输出)

解决方法:

每试一个方法时,如果不行的话都要重复确定问题这个操作再继续下一个解决方法。比如1不行后,再重新确定问题后再进行步骤2

  1. 如果console下面输出类似上图的错误,首先我们需要先确定高拍仪是否连接上电脑(可打开良田软件,查看是否能拍照,如果能拍照则正常连接,如果不能则是高拍仪未能连接)
  2. 如果高拍仪正常连接,则谷歌浏览器按照解决方案1试试是否可以正常拍照
  3. 如果步骤2也无法拍照,则使用360浏览器试试
  4. 如果步骤3后还是无法使用而且还是上述图中的错误,请联系)

2、错误2如下图(console中无红色错误输出)

解决方法:

每试一个方法时,如果不行的话都要重复确定问题这个操作再继续下一个解决方法。比如1不行后,再重新确定问题后再进行步骤2

  1. 如果console下面输出类似上图的错误,首先我们需要先确定高拍仪是否连接上电脑(可打开良田软件,查看是否能拍照,如果能拍照则正常连接,如果不能则是高拍仪未能连接)
  2. 1步骤也不行的话,卸载当前良田服务WebCamera,下载新的服务良田服务,提取码:9ksq,启动新的服务,点击拍照上传,查看能否拍照
  3. 2步骤还是不行的话,下载该文件video文件,提取码:uran,打开良田服务的安装目录,替换video.flt文件。最后重新启动良田服务,打开网页查看是否能拍照
  4. 上述步骤还无法解决,请联系相关人员(加qq:1430843286)

三、最后

一定要先确定高拍仪是否正确连接上电脑,良田软件能正常拍照。如果出现的问题不是上面几个也联系相关人员