内容安全策略指令 "script-src 'self' 'unsafe-eval'"
Content Security Policy directive "script-src 'self' 'unsafe-eval'"
我正在尝试使用 ipinfo.io 和 mesowest.utah.edu API 服务为最近的气象站 return 天气观测写一个 Chrome 扩展。扩展程序的预期输出是最近的气象站的当前气温和风速观测值,使用 IP 地址地理定位。
在检查扩展的弹出窗口后,jQuery 执行的发送请求中出现 CSP 协议错误。执行此请求的脚本是我的 JavaScript 使用 .get() 方法从 API 服务 (api.mesowest.net).
获取观察结果
原始 HTML 和 JavaScript 的工作 fiddle 可以在 [http://jsfiddle.net/zK5FN/3467/][ 1],但不会像打包和 运行 作为 Chrome 扩展时那样产生错误:
我的manifest.json是:
{
"manifest_version": 2,
"name": "Sensible Weather",
"description": "This extension will return simple weather obs for a site",
"version": "2.1",
"browser_action": {
"default_icon": "day16.png",
"default_popup": "popup.html",
"default_title": "Weather at your location"
},
"icons": { "16": "day16.png",
"48": "day48.png",
"128": "day128.png"
},
"content_scripts": [
{
"matches": ["https://*.ipinfo.io/", "https://*.api.mesowest.net/"],
"js": ["jquery-3.3.1.min.js", "./popupObs.js"]
}
],
"content_security_policy": "script-src https://ipinfo.io/json/ https://*.api.mesowest.net/ https://synopticlabs.org/api/mesonet/ https://*.github.com/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js 'unsafe-eval'; connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://*rawgit.com/ 'unsafe-inline'; object-src https://ipinfo.io/json/ https://*.api.mesowest.net/",
"permissions": [
"activeTab",
"https://*.api.mesowest.net/"
]
}
我的JavaScript:
async function getObs() {
var info = await fetch(`https://ipinfo.io/json/`)
.then(resp => resp.json());
var obs = await fetch(`https://api.mesowest.net/v2/stations/nearesttime?&radius=${info.loc},100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed/`)
.then(resp => resp.json());
console.log(obs);
var tempOut;
var windOut;
var stnName = obs.STATION[0].NAME;
var stnDist = obs.STATION[0].DISTANCE;
console.log(stnName);
console.log(stnDist);
// Populate variables with obs to display
if (obs.STATION[0].OBSERVATIONS.air_temp_value_1 !== undefined) {
tempOut = obs.STATION[0].OBSERVATIONS.air_temp_value_1.value;
} else {tempOut = 'temp undefined';}
console.log(tempOut);
if (obs.STATION[0].OBSERVATIONS.wind_speed_value_1 !== undefined) {
windOut = obs.STATION[0].OBSERVATIONS.wind_speed_value_1.value + ' MPH';
} else {windOut = 'no wind data at site';}
console.log(windOut);
var outArr = ['Air temperature is ' +tempOut+' degrees F, wind speed: ' + windOut + '. Observations from the ' + stnName + ' site located ' + stnDist + ' miles from you.'];
console.log(outArr);
document.getElementById('obs').innerHTML=outArr;
}
getObs()
还有我的HTML:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="style-src 'unsafe-inline'; script-src https://*.api.mesowest.org/ https://ipinfo.io/json/ https://*.github.com/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js 'unsafe-inline' 'unsafe-eval'; connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js https://*.github.com/ 'unsafe-inline';">
<script src="../jquery-3.3.1.min.js"></script>
<script type="text/javscript" src="https://ipinfo.io/json/"></script>
<h3>Nearest weather observations by IP geolocation using <a href="http://ipinfo.io">ipinfo.io</a></h3>
</head>
<body>
<div id="mesowest">
<p id="obs">Observations courtesy of the MesoWest API service.
</p>
</div>
<script type="text/javascript" src="https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js"> </script>
</body>
</html>
我收到的错误是:
popupObsAsync.js:4 Refused to connect to 'https://api.mesowest.net/v2/stations/nearesttime?&radius=47.9790,-122.2020,100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed' because it violates the following Content Security Policy directive: "connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://*rawgit.com/ 'unsafe-inline'".
getObs @ popupObsAsync.js:4
popupObsAsync.js:4 Refused to connect to 'https://api.mesowest.net/v2/stations/nearesttime?&radius=47.9790,-122.2020,100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed' because it violates the following Content Security Policy directive: "connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js https://*.github.com/ 'unsafe-inline'".
getObs @ popupObsAsync.js:4
popupObsAsync.js:4 Refused to connect to 'https://api.mesowest.net/v2/stations/nearesttime?&radius=47.9790,-122.2020,100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed' because it violates the document's Content Security Policy.
getObs @ popupObsAsync.js:4
popupObsAsync.js:4 Uncaught (in promise) TypeError: Failed to fetch
at getObs (popupObsAsync.js:4)
at <anonymous>
我已经解决了许多不同的错误,最终只有一个被 API 调用 returned,尽管它在其他编译器中运行良好。现在它从同一行向我抛出四个错误。
您不需要使用 JSONP。
async function getObs() {
const info = await fetch(`https://ipinfo.io/json`)
.then(resp => resp.json());
const obs = await fetch(`http://api.mesowest.net/v2/stations/nearesttime?&radius=${info.loc},100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed`)
.then(resp => resp.json());
console.log(obs);
}
但是如果您确实想保留 CSP,很可能您设置的是 allow-origin https://api.mesowest.net 但您的代码正在调用 http://api.mesowest.net,如错误所示。 (即使您尝试允许 http,Chrome 也会在扩展中禁止这样做。)
我正在尝试使用 ipinfo.io 和 mesowest.utah.edu API 服务为最近的气象站 return 天气观测写一个 Chrome 扩展。扩展程序的预期输出是最近的气象站的当前气温和风速观测值,使用 IP 地址地理定位。
在检查扩展的弹出窗口后,jQuery 执行的发送请求中出现 CSP 协议错误。执行此请求的脚本是我的 JavaScript 使用 .get() 方法从 API 服务 (api.mesowest.net).
获取观察结果原始 HTML 和 JavaScript 的工作 fiddle 可以在 [http://jsfiddle.net/zK5FN/3467/][ 1],但不会像打包和 运行 作为 Chrome 扩展时那样产生错误:
我的manifest.json是:
{
"manifest_version": 2,
"name": "Sensible Weather",
"description": "This extension will return simple weather obs for a site",
"version": "2.1",
"browser_action": {
"default_icon": "day16.png",
"default_popup": "popup.html",
"default_title": "Weather at your location"
},
"icons": { "16": "day16.png",
"48": "day48.png",
"128": "day128.png"
},
"content_scripts": [
{
"matches": ["https://*.ipinfo.io/", "https://*.api.mesowest.net/"],
"js": ["jquery-3.3.1.min.js", "./popupObs.js"]
}
],
"content_security_policy": "script-src https://ipinfo.io/json/ https://*.api.mesowest.net/ https://synopticlabs.org/api/mesonet/ https://*.github.com/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js 'unsafe-eval'; connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://*rawgit.com/ 'unsafe-inline'; object-src https://ipinfo.io/json/ https://*.api.mesowest.net/",
"permissions": [
"activeTab",
"https://*.api.mesowest.net/"
]
}
我的JavaScript:
async function getObs() {
var info = await fetch(`https://ipinfo.io/json/`)
.then(resp => resp.json());
var obs = await fetch(`https://api.mesowest.net/v2/stations/nearesttime?&radius=${info.loc},100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed/`)
.then(resp => resp.json());
console.log(obs);
var tempOut;
var windOut;
var stnName = obs.STATION[0].NAME;
var stnDist = obs.STATION[0].DISTANCE;
console.log(stnName);
console.log(stnDist);
// Populate variables with obs to display
if (obs.STATION[0].OBSERVATIONS.air_temp_value_1 !== undefined) {
tempOut = obs.STATION[0].OBSERVATIONS.air_temp_value_1.value;
} else {tempOut = 'temp undefined';}
console.log(tempOut);
if (obs.STATION[0].OBSERVATIONS.wind_speed_value_1 !== undefined) {
windOut = obs.STATION[0].OBSERVATIONS.wind_speed_value_1.value + ' MPH';
} else {windOut = 'no wind data at site';}
console.log(windOut);
var outArr = ['Air temperature is ' +tempOut+' degrees F, wind speed: ' + windOut + '. Observations from the ' + stnName + ' site located ' + stnDist + ' miles from you.'];
console.log(outArr);
document.getElementById('obs').innerHTML=outArr;
}
getObs()
还有我的HTML:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Security-Policy" content="style-src 'unsafe-inline'; script-src https://*.api.mesowest.org/ https://ipinfo.io/json/ https://*.github.com/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js 'unsafe-inline' 'unsafe-eval'; connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js https://*.github.com/ 'unsafe-inline';">
<script src="../jquery-3.3.1.min.js"></script>
<script type="text/javscript" src="https://ipinfo.io/json/"></script>
<h3>Nearest weather observations by IP geolocation using <a href="http://ipinfo.io">ipinfo.io</a></h3>
</head>
<body>
<div id="mesowest">
<p id="obs">Observations courtesy of the MesoWest API service.
</p>
</div>
<script type="text/javascript" src="https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js"> </script>
</body>
</html>
我收到的错误是:
popupObsAsync.js:4 Refused to connect to 'https://api.mesowest.net/v2/stations/nearesttime?&radius=47.9790,-122.2020,100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed' because it violates the following Content Security Policy directive: "connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://*rawgit.com/ 'unsafe-inline'".
getObs @ popupObsAsync.js:4
popupObsAsync.js:4 Refused to connect to 'https://api.mesowest.net/v2/stations/nearesttime?&radius=47.9790,-122.2020,100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed' because it violates the following Content Security Policy directive: "connect-src https://*.api.mesowest.net/ https://ipinfo.io/json/ https://rawgit.com/fairlycasual/willChromeExtension.github.io/master/popupObsAsync.js https://*.github.com/ 'unsafe-inline'".
getObs @ popupObsAsync.js:4
popupObsAsync.js:4 Refused to connect to 'https://api.mesowest.net/v2/stations/nearesttime?&radius=47.9790,-122.2020,100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed' because it violates the document's Content Security Policy.
getObs @ popupObsAsync.js:4
popupObsAsync.js:4 Uncaught (in promise) TypeError: Failed to fetch
at getObs (popupObsAsync.js:4)
at <anonymous>
我已经解决了许多不同的错误,最终只有一个被 API 调用 returned,尽管它在其他编译器中运行良好。现在它从同一行向我抛出四个错误。
您不需要使用 JSONP。
async function getObs() {
const info = await fetch(`https://ipinfo.io/json`)
.then(resp => resp.json());
const obs = await fetch(`http://api.mesowest.net/v2/stations/nearesttime?&radius=${info.loc},100&limit=1&units=ENGLISH&token=804c1eb09a394255beef8e84b68123bf&vars=air_temp,wind_speed`)
.then(resp => resp.json());
console.log(obs);
}
但是如果您确实想保留 CSP,很可能您设置的是 allow-origin https://api.mesowest.net 但您的代码正在调用 http://api.mesowest.net,如错误所示。 (即使您尝试允许 http,Chrome 也会在扩展中禁止这样做。)