作者:JanithKasunCORS和自定义CORS中间件(如果需要)。什么是CORSCORS是“Cross-OriginResourceSharing”的简称。它是一种允许或限制对Web服务器上资源的请求的机制,具体取决于发出HTTP请求的位置。此策略用于保护特定Web服务器免受其他网站或域的影响。只有允许的域才能访问服务器上的文件,例如样式表、图像或脚本等。假设您当前正在使用http://example.com/page1,并且您正在引用来自http://image.com/myimage的图像.jpg,那么除非http://image.com允许和http://example.com一样进行跨域分享,否则图片不会被抓取。在每个HTTP请求标头中都有一个名为origin的标头。它定义域请求的来源。您可以使用此标头中的信息来限制对您服务器上资源的引用。默认情况下,来自任何其他来源的请求都会受到浏览器的限制。比如你在开发的时候使用了React或者Vue这样的前端库,那么前端应用就会运行在http://localhost:3000上。同时,您的Express服务器可能正在其他端口上运行,例如http://localhost:2020。这是这些服务器之间需要允许CORS的地方。如果您在浏览器控制台中看到如下所示的错误。问题可能是CORS限制:当我们需要提供公共API并希望控制某些资源的访问和使用方式时,CORS会非常有用。或者,如果您想在其他网页上使用您自己的API或文件,您可以简单地配置CORS以允许您自己的引用,同时将其他人拒之门外。要使用Express配置CORS,首先创建一个新项目并创建目录结构,然后使用默认设置运行npminit:$mkdirmyapp$cdmyapp$npminit-y接下来安装所需的模块。我们将使用express和cors中间件:$npmi--saveexpress$npmi--savecors然后,开始创建一个简单的Web应用程序,其中包含两个路由来演示CORS的工作原理。首先创建一个名为index.js的文件作为web服务器,实现几个请求处理函数:constexpress=require('express');constcors=require('cors');constapp=express();app.get('/',(req,res)=>{res.json({message:'HelloWorld'});});app.get('/:name',(req,res)=>{letname=req.params.name;res.json({message:`Hello${name}`});});app.listen(2020,()=>{console.log('服务器正在监听2020端口');});runserver:$nodeindex.js访问http://localhost:2020/server应该返回JSONmessage:{"message":"HelloWorld"}访问http://localhost:2020/something应该可以看到:{"message":"Hellosomething"}启用所有CORS请求如果你想为所有请求启用CORS,你可以在配置路由之前简单地使用cors中间件:constexpress=require('express');constcors=require('cors');constapp=express();app.use(cors())...如果需要,这允许访问网络上任何地方的所有路由。所以在这个例子中,每个域都可以访问两条路由。例如,如果我们的服务器在http://www.example.com上运行并提供图像等内容,我们允许其他域(如http://www.differentdomain.com)从http://www.example提供服务。com用于推荐。因此http://www.differentdomain.com上的页面可以使用我们的域作为图像源:为单个路由启用CORS如果只需要其中一条路由,可以在路由中配置cors作为中间件:app.get('/',cors(),(req,res)=>{res.json({message:'HelloWorld'});});这将允许任何域访问指定的路由。在当前情况下,其他域只能访问/路由。/:name路由只能由在与API相同的域上发出的请求访问(在本例中为http://localhost:2020)。如果尝试另一个来源向/路径发送请求将成功,并将收到HelloWorld作为响应:fetch('http://localhost:2020/').then(response=>response.json()).then(data=>console.log(data)).catch(err=>console.error(err));运行上面的代码,你会看到服务器端的响应已经成功输出到控制台:{message:'HelloWorld'}如果你访问的不是根路径,比如http://localhost:2020/name或者http://localhost:2020/img/cat.png,这个请求会被浏览器拦截:fetch('http://localhost:2020/name/janith').then(response=>response.json()).then(data=>console.log(data)).catch(err=>console.error(err));如果您在另一个Web应用程序中运行代码,您应该会看到以下错误:使用选项配置CORS也可以使用自定义选项配置CORS。可以根据需要配置允许的HTTP方法,例如GET和POST。以下是允许通过CORS选项进行单域访问的方法:如果您在原始服务器中配置域名将允许来自配置域的CORS。因此,在我们的例子中,API可以从http://localhost:8080访问,其他域是不允许的。如果发送GET请求,任何路径都应该是可访问的,因为这些选项是在程序级别应用的。运行下面的代码将请求从http://localhost:8080发送到http://localhost:2020://fetch('http://localhost:2020/').then(response=>response.json()).then(data=>console.log(data)).catch(err=>console.error(err));//fetch('http://localhost:2020/name/janith').then(response=>response.json()).then(data=>console.log(data)).catch(err=>console.error(err));你可以看到你被允许从这个程序和域中获取信息。您还可以根据需要配置允许的HTTP方法:varcorsOptions={origin:'http://localhost:8080',optionsSuccessStatus:200//Supportforolderbrowsersmethods:"GET,PUT"}app.use(cors(corsOptions));如果从http://localhost:8080发送POST请求,浏览器将阻止它,因为只支持GET和PUT:fetch('http://localhost:2020',{method:'POST',body:JSON.stringify({name:"janith"}),}).then(response=>response.json()).then(data=>console.log(data)).catch(err=>console.error(err));使用函数配置动态CORS源如果配置不符合您的要求,您还可以创建函数来自定义CORS。例如,假设您想允许http://something.com和http://example.comCORS共享.jpg文件:constallowlist=['http://something.com','http://example.com'];constcorsOptionsDelegate=(req,callback)=>{让corsOptions;让isDomainAllowed=whitelist.indexOf(req.header('Origin'))!==-1;让isExtensionAllowed=req.path.endsWith('.jpg');if(isDomainAllowed&&isExtensionAllowed){//为此请求启用CORScorsOptions={origin:true}else{//为此请求禁用CORScorsOptions={origin:false}}callback(null,corsOptions)}app.use(cors(corsOptionsDelegate));回调函数接受两个参数,第一个是错误传null,第二个是选项传{origin:false}。第二个参数可以是用Express的请求对象构造的更多选项。因此,http://something.com或http://example.com上的Web应用程序将能够根据自定义配置从服务器引用具有.jpg扩展名的图像。这将成功引用资源文件:但以下文件将被阻止:Loadallowedoriginlistfromdatasource您也可以使用保存在数据库或任何类型的数据源中的白名单来允许CORS:varcorsOptions={origin:function(origin,callback){//加载数据库中允许的来源列表//示例:origins=['http://example.com','http//something.com']database.loadOrigins((error,origins)=>{callback(error,origins);});}}app.use(cors(corsOptions));