You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Unity安卓端用相同凭据调用ASP.NET Web API遭授权拒绝

解决Unity安卓端调用ASP.NET Web API授权失败的问题

这种跨平台授权不一致的问题我之前碰过好几次——核心原因其实是Unity在Windows和安卓上的网络请求实现细节差异很大,哪怕你用了一模一样的凭据,请求的"隐形细节"可能差了十万八千里。结合你说的「浏览器(包括安卓浏览器)都正常,但安卓Unity不行」,我整理了几个优先级最高的排查方向:

1. 先确认Authorization头是不是真的传对了

Unity的UnityWebRequest在安卓上偶尔会出现头信息被意外覆盖或者格式错误的情况:

  • 如果用的是Bearer Token,务必检查安卓端的头格式是Bearer {你的Token}——别漏了Bearer和Token之间的空格!我之前就因为少打了这个空格折腾了半天。
  • 不要依赖Unity的自动认证逻辑,手动硬编码头试试,代码大概是这样:
    var request = UnityWebRequest.Get("你的API地址");
    // Bearer Token示例
    request.SetRequestHeader("Authorization", $"Bearer {yourAuthToken}");
    // 如果是Basic Auth的话
    // var authStr = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));
    // request.SetRequestHeader("Authorization", $"Basic {authStr}");
    
  • 另外可以在API端加个日志,打印所有请求的Authorization头,对比安卓Unity、Windows Unity和浏览器的请求内容,一眼就能看出是不是头没传对。

2. 排查SSL证书的信任问题

如果你的API用的是HTTPS,Unity安卓默认不会信任自签名证书或者小众CA颁发的证书,但浏览器会自动处理(或者提示用户信任):

  • 先临时把API改成HTTP测试一下,如果能正常返回数据,那百分百是证书问题。
  • 解决办法是把证书导入Unity安卓项目:把你的SSL证书导出成.cer格式,放到Assets/Plugins/Android/assets目录,然后在请求时手动加载证书验证:
    var certPath = Path.Combine(Application.streamingAssetsPath, "你的证书.cer");
    var cert = new X509Certificate(File.ReadAllBytes(certPath));
    request.certificateHandler = new CustomCertHandler(cert);
    
    这里的CustomCertHandler是继承自CertificateHandler的自定义类,用来返回信任的证书:
    public class CustomCertHandler : CertificateHandler
    {
        private X509Certificate _trustedCert;
        public CustomCertHandler(X509Certificate cert) => _trustedCert = cert;
        protected override bool ValidateCertificate(byte[] certificateData)
        {
            var incomingCert = new X509Certificate(certificateData);
            return incomingCert.Equals(_trustedCert);
        }
    }
    

如果你的API用的是Cookie认证(比如Forms Auth),Unity安卓的UnityWebRequest默认不会自动保存和携带Cookie,但浏览器会:

  • 登录请求成功后,手动提取Set-Cookie头的值,后续所有请求都带上这个Cookie:
    // 登录请求完成后获取Cookie
    string authCookie = loginRequest.GetResponseHeader("Set-Cookie");
    // 后续API请求带上Cookie
    var dataRequest = UnityWebRequest.Get("需要授权的API地址");
    dataRequest.SetRequestHeader("Cookie", authCookie);
    
  • 长远来看,建议换成JWT这类Token-based认证,完全不依赖Cookie,跨平台兼容性好太多。

4. Unity安卓的网络栈设置

Unity在安卓上有不同的网络栈实现,切换一下可能解决问题:

  • 打开Edit > Project Settings > Player > Android > Other Settings,找到Configuration里的Internet Access,确保设置为Require
  • 再看看WebRequest的后端选项(不同Unity版本位置可能有差异),切换成AndroidHttpClient或者默认的UnityWebRequest试试,有时候换个栈就神奇地好了。

5. API端加日志抓差异

如果上面的方法都没用,就在ASP.NET Web API端加个请求日志,把每个请求的所有头、参数都打出来:

  • 写个自定义的消息处理器:
    public class RequestLoggingHandler : DelegatingHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            // 打印请求头和方法、路径
            Debug.WriteLine($"Request: {request.Method} {request.RequestUri}");
            foreach (var header in request.Headers)
            {
                Debug.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
            }
            return await base.SendAsync(request, cancellationToken);
        }
    }
    
  • WebApiConfig里注册这个处理器:
    config.MessageHandlers.Add(new RequestLoggingHandler());
    
    对比安卓Unity和正常请求的日志,肯定能找到差异点——比如安卓请求是不是少了某个头,或者凭据格式不对。

内容的提问来源于stack exchange,提问作者Salbrox

火山引擎 最新活动