简体   繁体   English

ASP.Net Core Antiforgery、Angular 和 IFRAMES

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

Let's assume you have another website that wants to display your Angular application inside an IFRAME on one of their pages.假设您有另一个网站想要在其中一个页面上的 IFRAME 中显示您的 Angular 应用程序。 How do you configure ASP.Net Core Antiforgery to work properly?如何配置 ASP.Net Core Antiforgery 才能正常工作?

I spent a reasonable amount of time trying to piece this together, so this is my attempt to help others trying to figure out how to get anti-forgery tokens working with ASP.Net Core 6 and Angular application being displayed inside an IFRAME on another website.我花了相当多的时间试图把它拼凑起来,所以这是我试图帮助其他人试图弄清楚如何让防伪令牌与 ASP.Net Core 6 和 Angular 应用程序一起显示在另一个网站上的 IFRAME 中的应用程序.

This assumes you have already configured ASP.Net Core Antiforgery to work with Angular SPA .这假设您已经将ASP.Net Core Antiforgery 配置为与 Angular SPA 一起使用

ASP.Net Core Antiforgery, Angular and IFRAMES ASP.Net Core Antiforgery、Angular 和 IFRAMES

Let's assume you have another website that wants to display your Angular application inside an IFRAME on one of their pages.假设您有另一个网站想要在其中一个页面上的 IFRAME 中显示您的 Angular 应用程序。 You will encounter a couple of issues to get this working.您将遇到几个问题才能使其正常工作。 Let's tackle them one at a time.让我们一次解决一个。

Refused to display in a frame because it set 'X-Frame-Options' to 'sameorigin'.拒绝在框架中显示,因为它将“X-Frame-Options”设置为“sameorigin”。

By default, when you call service.GetAndStoreTokens(context) , the Antiforgery service sets a response header called X-Frame-Options to te value SAMEORIGIN .默认情况下,当您调用service.GetAndStoreTokens(context)时,Antiforgery 服务会将名为X-Frame-Options的响应 header 设置为值SAMEORIGIN According to MDN , "The X-Frame-Options HTTP response header can be used to indicate whether or not a browser should be allowed to render a page in a <frame> , <iframe> , <embed> or <object> . Sites can use this to avoid click-jacking attacks, by ensuring that their content is not embedded into other sites."根据MDN“X-Frame-Options HTTP 响应 header 可用于指示是否应允许浏览器在<frame><iframe><embed><object>中呈现页面。可以使用它来避免点击劫持攻击,确保他们的内容不会嵌入到其他网站中。”

In order to get past this issue, you need to turn off this behavior when setting up the Antiforgery service:为了解决此问题,您需要在设置 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;
});

Now your web page displays inside the IFRAME, but none of the POST requests work properly.现在您的 web 页面显示在 IFRAME 内,但没有一个 POST 请求正常工作。 That's because there are no cookies are being passed to it.那是因为没有 cookies 被传递给它。

Cookies not being sent into IFRAME Cookies 未发送到 IFRAME

According to this excellent article, "this is a relatively new problem, as up until recently cookies would be sent through cross-site requests. It all changed when the default value for the SameSite cookie attribute was changed by Google Chrome -- introducing new default behavior that prevents these cookies from going through cross-site requests."根据这篇优秀的文章, “这是一个相对较新的问题,直到最近 cookies 将通过跨站点请求发送。当谷歌浏览器更改SameSite cookie 属性的默认值时,这一切都改变了——引入新的默认值阻止这些 cookies 通过跨站点请求的行为。”

If you watch the network traffic, you'll notice that the cookies that come down with you application entry point are marked as SameSite:Strict .如果您观察网络流量,您会注意到应用程序入口点的 cookies 被标记为SameSite:Strict This means they will only get sent if the request comes from a client directly connected to your site.这意味着只有当请求来自直接连接到您站点的客户端时,它们才会被发送。 They don't get sent to the IFRAME, so your Angular application is unable to read them and send it back in the HEADER of your API request.它们不会被发送到 IFRAME,因此您的 Angular 应用程序无法读取它们并将其发送回 HEADER 请求的 HEADER 中。

To resolve this problem, you need to fix both of your cookies.要解决此问题,您需要修复两个cookies。 Both of them need to be updated to SameSite:None (cookie can be sent to any site) and Secure:true (can only be delivered over HTTPS), which will allow the cookie to flow into the IFRAME.两者都需要更新为SameSite:None (cookie 可以发送到任何站点)和Secure:true (只能通过 HTTPS 传递),这将允许 cookie 流入 IFRAME。

First, update the Antiforgery service to fix the properties on the default cookie:首先,更新 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;
});

Then update the cookie being sent to the Angular application:然后更新发送到 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);
});

At this point, the application should display properly in the IFRAME and be able to interact with the Web API.此时,应用程序应在 IFRAME 中正常显示,并能够与 Web API 进行交互。 I hope this helps!我希望这有帮助!

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

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