You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中Microsoft登录WebGL失效但Windows端正常的问题求助

Unity WebGL下MSAL登录无响应问题解决方案

核心问题分析

Unity WebGL运行在浏览器沙盒环境中,和Windows原生环境存在本质差异,你的代码在Windows上正常但WebGL失效,核心原因集中在以下几点:

  • 线程模型限制:WebGL仅支持单主线程,ContinueWith回调可能脱离Unity主线程执行,导致状态更新失效
  • MSAL.NET兼容性:MSAL.NET主打桌面/服务器场景,WebGL中部分API(如嵌入式WebView、ROPC流)无法正常工作
  • 浏览器安全规则:非用户交互触发的弹出窗口会被拦截;AcquireTokenByUsernamePassword属于ROPC流,浏览器环境禁止直接明文处理密码
  • Redirect URI配置不匹配:WebGL的回调地址需和Azure AD配置完全一致,且要能被浏览器正确传递回Unity

具体修复步骤

1. 移除无效的嵌入式WebView配置

WebGL本身运行在浏览器中,没有独立嵌入式WebView环境,删除WithUseEmbeddedWebView(true):

publicClientApp.AcquireTokenInteractive(scopeList)
    .WithPrompt(Prompt.SelectAccount)
    .ExecuteAsync()
    // 后续逻辑

2. 修复异步线程问题

Unity WebGL不支持多线程,改用async/await并确保回调在Unity主线程执行。可以实现一个简单的主线程调度器,或直接用Unity内置方式处理:

public async void RequestLogin()
{
    Debug.LogError("TRYING TO LAUNCH LOGIN PAGE");
    List<string> scopeList = new List<string>(scopes);

    try
    {
        authenticationResult = await publicClientApp.AcquireTokenInteractive(scopeList)
            .WithPrompt(Prompt.SelectAccount)
            .ExecuteAsync();

        // 回到Unity主线程更新状态
        StartCoroutine(UpdateLoginState());
    }
    catch (Exception ex)
    {
        Debug.LogError($"MSAL Login failed: {ex.Message}");
        ex.InnerException?.Let(e => Debug.LogError($"Inner Exception: {e.Message}"));
    }

    Debug.LogError("CODE SHOULD'VE RAN");
}

private IEnumerator UpdateLoginState()
{
    yield return null; // 等待回到主线程
    UserEmail = authenticationResult.Account.Username;
    StaticValues.Email = UserEmail;
    webRequest.Set_SentBy(UserEmail);
    LoggedIn = true;
    Debug.Log($"MSAL Login successful. Access Token: {authenticationResult.AccessToken}, User Email: {UserEmail}");
}

3. 彻底放弃ROPC流(AcquireTokenByUsernamePassword)

AcquireTokenByUsernamePassword属于资源所有者密码凭据流,完全不适合WebGL环境:

  • 浏览器禁止明文处理用户密码,违反安全规范
  • 该流不支持MFA,Azure AD默认禁用此流
  • 直接删除RequestManualLogin及相关密码输入逻辑

4. 正确配置Redirect URI

  • 在Azure AD应用注册中,将Redirect URI设置为WebGL构建后的实际访问地址,本地测试可用http://localhost:3011/(确保本地服务器运行在对应端口)
  • 修改WebGL生成的index.html,添加回调处理逻辑,将Azure AD返回的token传递给Unity脚本

5. 改用MSAL.js实现(推荐方案)

WebGL本质是浏览器环境,直接使用MSAL.js比MSAL.NET更可靠:

  1. 在WebGL的index.html中引入MSAL.js:
<script src="https://alcdn.msauth.net/browser/2.38.1/js/msal-browser.min.js"></script>
  1. 编写JS登录逻辑,通过unityInstance.SendMessage传递数据给Unity:
const msalConfig = {
    auth: {
        clientId: "4c203cba-62cd-42e4-984d-d4b765c65051",
        authority: "https://login.microsoftonline.com/organizations/v2.0",
        redirectUri: "http://localhost:3011/"
    }
};

const msalInstance = new msal.PublicClientApplication(msalConfig);

async function login() {
    try {
        const loginResponse = await msalInstance.loginPopup({ scopes: ["User.Read"] });
        unityInstance.SendMessage("MSALLoginObject", "OnLoginSuccess", `${loginResponse.account.username}|${loginResponse.accessToken}`);
    } catch (error) {
        unityInstance.SendMessage("MSALLoginObject", "OnLoginFailed", error.message);
    }
}
  1. 在Unity脚本中添加接收方法:
public void OnLoginSuccess(string data)
{
    var parts = data.Split('|');
    UserEmail = parts[0];
    StaticValues.Email = UserEmail;
    webRequest.Set_SentBy(UserEmail);
    LoggedIn = true;
}

public void OnLoginFailed(string errorMsg)
{
    Debug.LogError($"Login failed: {errorMsg}");
}
  1. 在Unity中通过用户交互触发登录:
public void RequestLogin()
{
    Application.ExternalCall("login");
}

6. 确保登录触发来自用户交互

浏览器会拦截非用户主动触发的弹出窗口,必须确保RequestLogin是通过按钮点击等用户交互事件调用,禁止在Start等自动执行的方法中触发。


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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 22:09:55