繁体   English   中英

ASP.Net Core Antiforgery、Angular 和 IFRAMES

[英]ASP.Net Core Antiforgery, Angular and IFRAMES

假设您有另一个网站想要在其中一个页面上的 IFRAME 中显示您的 Angular 应用程序。 如何配置 ASP.Net Core Antiforgery 才能正常工作?

我花了相当多的时间试图把它拼凑起来,所以这是我试图帮助其他人试图弄清楚如何让防伪令牌与 ASP.Net Core 6 和 Angular 应用程序一起显示在另一个网站上的 IFRAME 中的应用程序.

这假设您已经将ASP.Net Core Antiforgery 配置为与 Angular SPA 一起使用

ASP.Net Core Antiforgery、Angular 和 IFRAMES

假设您有另一个网站想要在其中一个页面上的 IFRAME 中显示您的 Angular 应用程序。 您将遇到几个问题才能使其正常工作。 让我们一次解决一个。

拒绝在框架中显示,因为它将“X-Frame-Options”设置为“sameorigin”。

默认情况下,当您调用service.GetAndStoreTokens(context)时,Antiforgery 服务会将名为X-Frame-Options的响应 header 设置为值SAMEORIGIN 根据MDN“X-Frame-Options HTTP 响应 header 可用于指示是否应允许浏览器在<frame><iframe><embed><object>中呈现页面。可以使用它来避免点击劫持攻击,确保他们的内容不会嵌入到其他网站中。”

为了解决此问题,您需要在设置 Antiforgery 服务时关闭此行为:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAntiforgery(options =>
{
    options.HeaderName = "X-XSRF-TOKEN";
    // suppress setting X-Frame-Options to SAMEORIGIN
    options.SuppressXFrameOptionsHeader = true;
});

现在您的 web 页面显示在 IFRAME 内,但没有一个 POST 请求正常工作。 那是因为没有 cookies 被传递给它。

Cookies 未发送到 IFRAME

根据这篇优秀的文章, “这是一个相对较新的问题,直到最近 cookies 将通过跨站点请求发送。当谷歌浏览器更改SameSite cookie 属性的默认值时,这一切都改变了——引入新的默认值阻止这些 cookies 通过跨站点请求的行为。”

如果您观察网络流量,您会注意到应用程序入口点的 cookies 被标记为SameSite:Strict 这意味着只有当请求来自直接连接到您站点的客户端时,它们才会被发送。 它们不会被发送到 IFRAME,因此您的 Angular 应用程序无法读取它们并将其发送回 HEADER 请求的 HEADER 中。

要解决此问题,您需要修复两个cookies。 两者都需要更新为SameSite:None (cookie 可以发送到任何站点)和Secure:true (只能通过 HTTPS 传递),这将允许 cookie 流入 IFRAME。

首先,更新 Antiforgery 服务以修复默认 cookie 的属性:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAntiforgery(options =>
{
    options.HeaderName = "X-XSRF-TOKEN";
    // suppress setting X-Frame-Options to SAMEORIGIN
    options.SuppressXFrameOptionsHeader = true;
    // allow cookie to be sent to IFRAME
    options.Cookie.SameSite = SameSiteMode.None;
    options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
});

然后更新发送到 Angular 应用程序的 cookie:

var app = builder.Build();
app.MapControllers();

var service = app.Services.GetRequiredService<IAntiforgery>();

app.Use(async (context, next) =>
{
    var path = context.Request.Path;
    if (path.Equals("/default.html", StringComparison.CurrentCultureIgnoreCase))
    {
        // generate .AspNetCore.Antiforgery authentication cookie
        var tokenSet = service.GetAndStoreTokens(context);
        var token = tokenSet.RequestToken;
        // duplicate the .AspNetCore.Antiforgery authentication and create a cookie called XSRF-TOKEN
        if (token != null)
        {
            context.Response.Cookies.Append("XSRF-TOKEN", token, new CookieOptions
            {
                Path = "/",
                HttpOnly = false,
                // allow cookie to be sent to IFRAME
                SameSite = SameSiteMode.None,
                Secure = true
            });
        }
    }

    await next(context);
});

此时,应用程序应在 IFRAME 中正常显示,并能够与 Web API 进行交互。 我希望这有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM