progressive-web-apps - PWA : force window. open 打开浏览器而不是PWA

标签 progressive-web-apps window.open

我已经构建了一个带有角度前端的 ASP.NET Core 应用程序。 Angular 应用程序具有 @angular/pwa 节点包设置,因此它是一个渐进式 Web 应用程序,可以安装在 Android/Windows 上,表现得像 native 应用程序。

我已使用 Microsoft.AspNetCore.Identity 设置外部登录(Microsoft、Google、Facebook、Twitter)。从我的角度应用程序中,我打开一个外部登录页面的弹出窗口:

  this.authWindow = window.open(`${this.baseUrl}/web/v2/Account/${this.action}/${medium}/${this.platform}`, null, 'width=600,height=400');

弹出窗口的 URL 路由到 ASP.NET Core 端点,我在其中进行了 return Challenge() 调用,该调用返回特定外部提供商(Microsoft、Google、Facebook、推特)。

在 Windows 上的 Chrome 中,单击触发 window.open() 的按钮以打开具有外部登录页面的窗口。成功登录后,您将被重定向到回调页面,这是一个 Razor 页面,它将消息发送到包含角度应用程序的主窗口。消息正在处理,弹出窗口正在关闭。

问题

当我在 Android 版 Chrome 上使用该网站时,我可以将 PWA 安装为应用程序,这会在我的 Android 主页上添加一个图标。当我打开 PWA 并单击按钮打开弹出窗口时,该弹出窗口正在我的 PWA 的弹出窗口中打开,因此没有问题。

当我在 Android 上打开 Chrome 并访问该网站时,在安装了 PWA 的情况下,window.open() 调用不会为 Chrome 浏览器打开弹出窗口,而是尝试打开渐进式 Web 应用程序的弹出窗口。既然如此,PWA 内的弹出窗口无法通知 Chrome 中的网站登录成功(废话……)。

但是,当未安装 PWA 时,window.open() 可以正常工作并在 Chrome 本身中打开弹出窗口。

所以底线是,PWA 安装在 Android 上。我希望能够在 Chrome 中从我的网站调用 window.open(),并让它在 Chrome 浏览器(而不是 PWA)中打开弹出窗口。

我尝试过的事情

  1. 修改ngsw-config.json

    { ..., “导航网址”:[ “/<强>”, "!//.", “!//__”, "!//__/", "!/web/v2/Account/connect//", “!/web/v2/Account/add//**” ] }

  2. 使用 target='_system' 打开窗口

    this.authWindow = window.open(${this.baseUrl}/web/v2/Account/${this.action}/${medium}/${this.platform}, '_system', '宽度=600,高度=400');

  3. 使用 target='_blank' 打开窗口

    this.authWindow = window.open(${this.baseUrl}/web/v2/Account/${this.action}/${medium}/${this.platform}, '_blank', '宽度=600,高度=400');

  4. 使用 target='_blank' 打开窗口,不使用 baseUrl,仅使用绝对路径。

    this.authWindow = window.open(/web/v2/Account/${this.action}/${medium}/${this.platform}, '_blank', '宽度=600,高度=400');

  5. 使用 ngsw-bypass

    this.authWindow = window.open(/web/v2/Account/${this.action}/${medium}/${this.platform}?ngsw-bypass=true, '_blank', '宽度=600,高度=400');

但是所有技巧似乎都表现相同,并且仍然在 PWA 中打开窗口。

最佳答案

我最终创建了一个托管外部登录端点的子域(ExternalLoginExternalLoginCallbackAddExternalLoginAddExternalLoginCallback >):

[Controller]
[Route("web/v2/[controller]")]
public class AccountController : Controller
{
    private IAccountService accountService;
    public AccountController(IAccountService accountService)
    {
        this.accountService = accountService;
    }
    
    ...

    // GET: web/Account/providers
    [AllowAnonymous]
    [HttpGet("providers", Name = "web-v2-account-external-providers")]
    public async Task<ActionResult<IEnumerable<string>>> Providers()
    {
        var result = await accountService.GetProviders();
        return Ok(result);
    }

    // GET: web/Account/connect/{provider}
    [AllowAnonymous]
    [HttpGet("connect/{medium}/{provider}", Name = "web-v2-account-external-connect-challenge")]
#if RELEASE
    [Host("external.mintplayer.com")]
#endif
    public async Task<ActionResult> ExternalLogin([FromRoute]string medium, [FromRoute]string provider)
    {
        var redirectUrl = Url.RouteUrl("web-v2-account-external-connect-callback", new { medium, provider });
        var properties = await accountService.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
        return Challenge(properties, provider);
    }

    // GET: web/Account/connect/{provider}/callback
    [HttpGet("connect/{medium}/{provider}/callback", Name = "web-v2-account-external-connect-callback")]
#if RELEASE
    [Host("external.mintplayer.com")]
#endif
    public async Task<ActionResult> ExternalLoginCallback([FromRoute]string medium, [FromRoute]string provider)
    {
        try
        {
            var login_result = await accountService.PerfromExternalLogin();
            if (login_result.Status)
            {
                var model = new LoginResultVM
                {
                    Status = true,
                    Medium = medium,
                    Platform = login_result.Platform
                };
                return View(model);
            }
            else
            {
                var model = new LoginResultVM
                {
                    Status = false,
                    Medium = medium,
                    Platform = login_result.Platform,

                    Error = login_result.Error,
                    ErrorDescription = login_result.ErrorDescription
                };
                return View(model);
            }
        }
        catch (OtherAccountException otherAccountEx)
        {
            var model = new LoginResultVM
            {
                Status = false,
                Medium = medium,
                Platform = provider,

                Error = "Could not login",
                ErrorDescription = otherAccountEx.Message
            };
            return View(model);
        }
        catch (Exception ex)
        {
            var model = new LoginResultVM
            {
                Status = false,
                Medium = medium,
                Platform = provider,

                Error = "Could not login",
                ErrorDescription = "There was an error with your social login"
            };
            return View(model);
        }
    }

    // GET: web/Account/logins
    [Authorize]
    [HttpGet("logins", Name = "web-v2-account-external-logins")]
    public async Task<ActionResult<IEnumerable<string>>> GetExternalLogins()
    {
        var logins = await accountService.GetExternalLogins(User);
        return Ok(logins.Select(l => l.ProviderDisplayName));
    }

    // GET: web/Account/add/{provider}
    [Authorize]
    [HttpGet("add/{medium}/{provider}", Name = "web-v2-account-external-add-challenge")]
#if RELEASE
    [Host("external.mintplayer.com")]
#endif
    public async Task<ActionResult> AddExternalLogin([FromRoute]string medium, [FromRoute]string provider)
    {
        var redirectUrl = Url.RouteUrl("web-v2-account-external-add-callback", new { medium, provider });
        var properties = await accountService.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
        return Challenge(properties, provider);
    }

    // GET: web/Account/add/{provider}/callback
    [Authorize]
    [HttpGet("add/{medium}/{provider}/callback", Name = "web-v2-account-external-add-callback")]
#if RELEASE
    [Host("external.mintplayer.com")]
#endif
    public async Task<ActionResult> AddExternalLoginCallback([FromRoute]string medium, [FromRoute]string provider)
    {
        try
        {
            await accountService.AddExternalLogin(User);
            var model = new LoginResultVM
            {
                Status = true,
                Medium = medium,
                Platform = provider
            };
            return View(model);
        }
        catch (Exception)
        {
            var model = new LoginResultVM
            {
                Status = false,
                Medium = medium,
                Platform = provider,

                Error = "Could not login",
                ErrorDescription = "There was an error with your social login"
            };
            return View(model);
        }
    }
}

在 PWA 中运行时,window.open 仍将在 PWA 内的嵌入式浏览器内打开链接,而从浏览器运行时,window.open 将仍然在新的浏览器窗口(而不是在 PWA 中)打开链接。在这两种情况下,我仍然可以访问 opener 来发送消息 (window.opener.postMessage)。

关于progressive-web-apps - PWA : force window. open 打开浏览器而不是PWA,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60554479/

相关文章:

ssl-certificate - PWA 需要什么样的 SSL 证书?

progressive-web-apps - PWA 是否必须使用 Workbox 进行预缓存?

ios - PWA iOS 启动画面上的触发事件

javascript - 我的 window.open 打开一个新窗口而不是新选项卡

javascript - 如何获取所有已打开的子窗口的引用

Angular 8 PWA assetGroups 离线无法工作

internet-explorer - 对 IE11 的 PWA 支持

javascript - window.closed IE9 在窗口仍然打开时报告 true

javascript - Window.open使页面变成弹出 block

Javascript 弹出窗口在 Chrome 中打开 SHOW 工具栏并编辑 URL