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); } }
3. Cookie-based认证的坑(如果用了的话)
如果你的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里注册这个处理器:
对比安卓Unity和正常请求的日志,肯定能找到差异点——比如安卓请求是不是少了某个头,或者凭据格式不对。config.MessageHandlers.Add(new RequestLoggingHandler());
内容的提问来源于stack exchange,提问作者Salbrox




