我为此搜索了所有可能的论坛,并且以某种方式还没有使我的WebGL
消耗掉我的ASP.NET 4.5 REST API's
。
据我所知,这可能与WebGL
要求CORS
有关,但即使启用此功能,我也无法使游戏与我的API's
进行交流
所以我在CORS
中实现全局ASP.NET
设置的方式出了问题,或者其他问题正在中断。需要明确的是,这些API在Android/iOS/Windows builds
甚至在编辑器中都运行良好。
我到目前为止所做的:按照Microsoft相关文档的建议安装
Microsoft CORS build
,然后在WebAPIConfig
中的Visual Studio
类中添加以下代码:
public static void Register(HttpConfiguration config)
{
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
////new code
config.EnableCors(new EnableCorsAttribute("*", "*", "*"));
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
这也在我的web.config中:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
我需要全局这些设置,所以我使用了文档指示的"*"
来包括所有域,方法类型和标头,因为我的API使用了ASP.NET令牌身份验证。
这里是在Unity项目中获取令牌的代码段(请注意,这在其他平台上也有效,仅在WebGL build
中引发错误)
public IEnumerator login()
{
string url = API.ROUTEPATH + API.TOKEN;
WWWForm form = new WWWForm();
form.AddField("grant_type", "password");
form.AddField("username", API.APIUSERNAME);
form.AddField("password", API.APIPASSWORD);
UnityWebRequest uwr = UnityWebRequest.Post(url, form);
uwr.SetRequestHeader("Content-Type", "application/json");
yield return uwr.SendWebRequest();
try
{
if (uwr.isNetworkError)
{
Debug.Log(uwr.error);
}
else
{
APIAuthToken returnauth = JsonUtility.FromJson<APIAuthToken>(uwr.downloadHandler.text);
if (!string.IsNullOrEmpty(returnauth.access_token))
{
API.hasAuth = true;
API.token = returnauth.access_token;
Debug.Log(returnauth.access_token);
}
}
}
catch
{
}
}
uwr.error
会产生以下非常有用的错误:Unknown Error
所以我什至不确定它是否与CORS
相关,这只是我根据所做的研究得出的最佳猜测,但是即使有多种不同的实现我仍然坐着同样的错误。因此,如果API's
和我的Unity代码没有问题,请忽略ASP.NET
代码段。
cURL-简单的
curl -I <endpoint>
或curl -X OPTIONS -v <endpoint>
可以显示大量与CORS相关的信息。它可以让您设置不同的来源,检查飞行前的响应等等。
“假设您有一个使用cookie进行会话管理的后端API。您在自己的域上进行测试时,您的游戏效果很好,但是由于您的API请求现已交叉,因此一旦您将文件托管在Kongregate上,该游戏就会崩溃域,并遵守严格的CORS规则。“
这是您的问题吗?
[如果双方没有正确设置,可能双方都会拒绝发送cookie,但这很好,这意味着您可以控制将cookie发送到的域。
因此,您可能首先需要将服务器配置为允许多重来源但是请确保根据白名单验证该值,以便您不只是将会话cookie发送到任何来源域。带有CORS中间件(游戏ID 12345)和以下原始白名单的Node Express上的示例:
express = require('express')
var cors = require('cors')
var app = express()
var whitelist = ['https://game12345.konggames.com'];
var corsOptions = {
credentials: true,
origin: function (origin, callback) {
if (whitelist.indexOf(origin) !== -1) {
callback(null, true)
} else {
callback(new Error('Not allowed by CORS'))
}
}
};
app.use(cors(corsOptions));
app.options('*', cors(corsOptions)); // Enable options for preflight
app.get('/', (req, res) => res.send('Hello World!'))
app.listen(8080, () => console.log(`Example app listening on port 8080!`))
cURL命令从白名单数组中的来源检查OPTIONS预检请求的标头:
curl -X OPTIONS -H"Origin: https://game12345.konggames.com" -v http://localhost:8080/
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> OPTIONS / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
> Origin: https://game12345.konggames.com
>
< HTTP/1.1 204 No Content
< X-Powered-By: Express
< Access-Control-Allow-Origin: https://game12345.konggames.com
< Vary: Origin, Access-Control-Request-Headers
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET,HEAD,PUT,PATCH,POST,DELETE
< Content-Length: 0
< Date: Tue, 24 Sep 2019 22:04:08 GMT
< Connection: keep-alive
<
* Connection #0 to host localhost left intact
指示客户端发出跨域请求时,如果预检响应中不包含Access-Control-Allow-Credentials:true,或者您的Access-Control-Allow-Access设置为通配符( *),则不会发送Cookie,并且您可能会在浏览器的Javascript控制台中看到错误:
Access to XMLHttpRequest at 'https://api.mygamebackend.com' from origin 'https://game54321.konggames.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
Unity的UnityWebRequest和较旧的WWW类在幕后使用XMLHttpRequest
从远程服务器获取数据。由于没有将withCredentials
标志设置为true的选项,因此我们必须在初始化应用程序时执行非常肮脏的破解,才能针对适当的请求将其打开。在您的WebGL模板或生成的index.html中:
<script>
XMLHttpRequest.prototype.originalOpen = XMLHttpRequest.prototype.open;
var newOpen = function(_, url) {
var original = this.originalOpen.apply(this, arguments);
if (url.indexOf('https://api.mygamebackend.com') === 0) {
this.withCredentials = true;
}
return original;
}
XMLHttpRequest.prototype.open = newOpen;
</script>
此代码段覆盖了XMLHttpRequest的open方法,因此我们可以在需要时有条件地将withCredentials设置为true。一旦安装到位,跨域Cookie应开始在Kongregate托管的iframe域和游戏的后端服务器之间工作!