asp.net - ASP.NET 4.5 Rest API 在 Unity Android/iOS 构建中的工作,但在 Unity WebGL 构建中因“未知错误”而失败
问题描述
我已经为此搜索了所有可能的论坛,但不知何故没有让我WebGL
消费我的ASP.NET 4.5 REST API's
.
据我所知,这可能与WebGL
要求有关CORS
,但即使启用此功能,我也无法让游戏与我的API's
因此,要么是我在其中实现全局CORS
设置的方式有问题,ASP.NET
要么是其他一些问题正在破坏。需要明确的是,这些 APIAndroid/iOS/Windows builds
在编辑器中甚至在编辑器中运行得非常好。
到目前为止我所做的:
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 项目中获取令牌的代码片段(为了清楚起见,这适用于其他平台,只会在 a 中引发错误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。您的游戏在您自己的域上测试时运行良好,但是一旦您将文件托管在 Kongregate 上,由于您的 API 请求现在是跨域和遵守严格的 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
指示客户端在发出跨域请求时包含 cookie,如果预检响应不包含 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 的选项,我们必须在初始化我们的应用程序时执行一个非常肮脏的 hack,以便为适当的请求打开它。在您的 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 域和游戏的后端服务器之间工作!
推荐阅读
- android - 尝试进行接口类型的成员注入时 Dagger 2 NPE
- laravel - 非 www url 正在重定向到主页
- spring - 如何获取本地到 Spring Boot 以本地化消息?
- c# - 使用 Prism 在 WPF 应用程序中使用 RESX 文件
- java - Amazon Coretto 11、Spring Boot 和 PowerMock - 测试失败
- node.js - 在节点中生成后在子进程中提供输入
- node.js - 异步 / 等待 Node.js https.get
- javascript - 如何将永久数据添加到变量中
- python - 如何计算 poly 中的多个变量?
- excel - 我可以循环这个宏 X 次但仍将一些单元格引用增加 +1 吗?