X-Frame-옵션 여러 도메인에서 허용
X-Frame-Options 헤더를 사용하여 보호해야 하는 ASP.NET 4.0 IIS 7.5 사이트가 있습니다.
또한 페이스북 앱뿐만 아니라 동일한 도메인에서 사이트 페이지를 프레임화할 수 있어야 합니다.
현재 다음 사이트로 구성된 사이트가 있습니다.
Response.Headers.Add("X-Frame-Options", "ALLOW-FROM SAMEDOMAIN, www.facebook.com/MyFBSite")
Chrome 또는 Firefox를 사용하여 Facebook 페이지를 볼 때 사이트 페이지(Facebook 페이지로 프레임화된 경우)는 정상으로 표시되지만 IE9에서 다음 오류가 발생합니다.
할 수 이 를 표시할 수 없습니다…")
X-Frame_Options제한).
을 어떻게 합니까?X-Frame-Options: ALLOW-FROM하나 이상의 도메인을 지원합니까?
X-FRAME-OPTION새로운 기능이 되는 것은 단일 도메인만 정의될 수 있다면 근본적으로 결함이 있는 것처럼 보입니다.
X-Frame-Options사용되지 않습니다.MDN에서:
이 기능은 웹 표준에서 제거되었습니다.일부 브라우저에서는 여전히 지원할 수 있지만 삭제 중입니다.이전 프로젝트나 새 프로젝트에서는 사용하지 마십시오.이를 사용하는 페이지 또는 웹 앱은 언제든지 손상될 수 있습니다.
현대적인 대안은 헤더이며, 다른 많은 정책과 함께 지시문을 사용하여 프레임에서 페이지를 호스팅할 수 있는 URL을 화이트리스트에 추가할 수 있습니다.
frame-ancestors에서는 여러 도메인과 와일드카드까지 지원합니다. 예를 들어 다음과 같습니다.
Content-Security-Policy: frame-ancestors 'self' example.com *.example.net ;
안타깝게도 현재 Internet Explorer는 콘텐츠-보안-정책을 완전히 지원하지 않습니다.
업데이트: MDN이 사용되지 않는 주석을 제거했습니다.다음은 W3C의 콘텐츠 보안 정책 수준과 유사한 의견입니다.
그
frame-ancestors지시는 더 이상 쓸모가 없습니다.X-Frame-Options에 두 정책이 되어 있는 경우 리소스는 두 가지 정책을 모두 합니다.frame-ancestors정책을 시행해야 하며,X-Frame-Options정책은 무시해야 합니다.
RFC 7034에서:
하나의 ALLOW-FROM 문에 여러 도메인을 선언하는 와일드카드 또는 목록은 허용되지 않습니다.
그렇게,
X-Frame-Options: ALLOW-FROM이 하나 이상의 도메인을 지원하도록 설정하려면 어떻게 해야 합니까?
그럴수는 없어요.해결 방법으로 파트너별로 다른 URL을 사용할 수 있습니다.자체 을 사용할 수 .X-Frame-Options 를 들어 다음과 같습니다. 예:
partner iframe URL ALLOW-FROM
---------------------------------------
Facebook fb.yoursite.com facebook.com
VK.COM vk.yoursite.com vk.com
위해서yousite.com그냥 사용할 수 있습니다.X-Frame-Options: deny.
BTW, 현재 크롬(및 모든 웹킷 기반 브라우저)은 지원하지 않습니다. ALLOW-FROM일체의 진술
네크로맨싱.
제공된 답변이 불완전합니다.
먼저, 이미 말했듯이 여러 개의 허용 호스트를 추가할 수 없습니다. 이는 지원되지 않습니다.
둘째, HTTP 레퍼러에서 해당 값을 동적으로 추출해야 합니다. 즉, 항상 동일한 값이 아니기 때문에 Web.config에 값을 추가할 수 없습니다.
브라우저가 Chrom인 경우 allow-from을 추가하지 않도록 브라우저 탐지를 수행해야 합니다(디버깅 콘솔에서 오류가 발생하여 콘솔이 빠르게 채워지거나 응용 프로그램이 느려질 수 있습니다).또한 ASP.NET 브라우저 탐지가 Edge를 Chrome로 잘못 식별하므로 이를 수정해야 합니다.
이 작업은 ASP.NET에서 요청의 레퍼러에 따라 모든 요청에 대해 실행되고 모든 응답에 대해 HTTP 헤더를 추가하는 HTTP 모듈을 작성하여 수행할 수 있습니다.Chrome의 경우 Content-Security-Policy를 추가해야 합니다.
// https://stackoverflow.com/questions/31870789/check-whether-browser-is-chrome-or-edge
public class BrowserInfo
{
public System.Web.HttpBrowserCapabilities Browser { get; set; }
public string Name { get; set; }
public string Version { get; set; }
public string Platform { get; set; }
public bool IsMobileDevice { get; set; }
public string MobileBrand { get; set; }
public string MobileModel { get; set; }
public BrowserInfo(System.Web.HttpRequest request)
{
if (request.Browser != null)
{
if (request.UserAgent.Contains("Edge")
&& request.Browser.Browser != "Edge")
{
this.Name = "Edge";
}
else
{
this.Name = request.Browser.Browser;
this.Version = request.Browser.MajorVersion.ToString();
}
this.Browser = request.Browser;
this.Platform = request.Browser.Platform;
this.IsMobileDevice = request.Browser.IsMobileDevice;
if (IsMobileDevice)
{
this.Name = request.Browser.Browser;
}
}
}
}
void context_EndRequest(object sender, System.EventArgs e)
{
if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Response != null)
{
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
try
{
// response.Headers["P3P"] = "CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"":
// response.Headers.Set("P3P", "CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"");
// response.AddHeader("P3P", "CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"");
response.AppendHeader("P3P", "CP=\\\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\\\"");
// response.AppendHeader("X-Frame-Options", "DENY");
// response.AppendHeader("X-Frame-Options", "SAMEORIGIN");
// response.AppendHeader("X-Frame-Options", "AllowAll");
if (System.Web.HttpContext.Current.Request.UrlReferrer != null)
{
// "X-Frame-Options": "ALLOW-FROM " Not recognized in Chrome
string host = System.Web.HttpContext.Current.Request.UrlReferrer.Scheme + System.Uri.SchemeDelimiter
+ System.Web.HttpContext.Current.Request.UrlReferrer.Authority
;
string selfAuth = System.Web.HttpContext.Current.Request.Url.Authority;
string refAuth = System.Web.HttpContext.Current.Request.UrlReferrer.Authority;
// SQL.Log(System.Web.HttpContext.Current.Request.RawUrl, System.Web.HttpContext.Current.Request.UrlReferrer.OriginalString, refAuth);
if (IsHostAllowed(refAuth))
{
BrowserInfo bi = new BrowserInfo(System.Web.HttpContext.Current.Request);
// bi.Name = Firefox
// bi.Name = InternetExplorer
// bi.Name = Chrome
// Chrome wants entire path...
if (!System.StringComparer.OrdinalIgnoreCase.Equals(bi.Name, "Chrome"))
response.AppendHeader("X-Frame-Options", "ALLOW-FROM " + host);
// unsafe-eval: invalid JSON https://github.com/keen/keen-js/issues/394
// unsafe-inline: styles
// data: url(data:image/png:...)
// https://www.owasp.org/index.php/Clickjacking_Defense_Cheat_Sheet
// https://www.ietf.org/rfc/rfc7034.txt
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
// https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP
// https://stackoverflow.com/questions/10205192/x-frame-options-allow-from-multiple-domains
// https://content-security-policy.com/
// http://rehansaeed.com/content-security-policy-for-asp-net-mvc/
// This is for Chrome:
// response.AppendHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: *.msecnd.net vortex.data.microsoft.com " + selfAuth + " " + refAuth);
System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();
ls.Add("default-src");
ls.Add("'self'");
ls.Add("'unsafe-inline'");
ls.Add("'unsafe-eval'");
ls.Add("data:");
// http://az416426.vo.msecnd.net/scripts/a/ai.0.js
// ls.Add("*.msecnd.net");
// ls.Add("vortex.data.microsoft.com");
ls.Add(selfAuth);
ls.Add(refAuth);
string contentSecurityPolicy = string.Join(" ", ls.ToArray());
response.AppendHeader("Content-Security-Policy", contentSecurityPolicy);
}
else
{
response.AppendHeader("X-Frame-Options", "SAMEORIGIN");
}
}
else
response.AppendHeader("X-Frame-Options", "SAMEORIGIN");
}
catch (System.Exception ex)
{
// WTF ?
System.Console.WriteLine(ex.Message); // Suppress warning
}
} // End if (System.Web.HttpContext.Current != null && System.Web.HttpContext.Current.Response != null)
} // End Using context_EndRequest
private static string[] s_allowedHosts = new string[]
{
"localhost:49533"
,"localhost:52257"
,"vmcompany1"
,"vmcompany2"
,"vmpostalservices"
,"example.com"
};
public static bool IsHostAllowed(string host)
{
return Contains(s_allowedHosts, host);
} // End Function IsHostAllowed
public static bool Contains(string[] allowed, string current)
{
for (int i = 0; i < allowed.Length; ++i)
{
if (System.StringComparer.OrdinalIgnoreCase.Equals(allowed[i], current))
return true;
} // Next i
return false;
} // End Function Contains
HTTP-module Init 함수에 context_EndRequest 함수를 등록해야 합니다.
public class RequestLanguageChanger : System.Web.IHttpModule
{
void System.Web.IHttpModule.Dispose()
{
// throw new NotImplementedException();
}
void System.Web.IHttpModule.Init(System.Web.HttpApplication context)
{
// https://stackoverflow.com/questions/441421/httpmodule-event-execution-order
context.EndRequest += new System.EventHandler(context_EndRequest);
}
// context_EndRequest Code from above comes here
}
그런 다음 응용 프로그램에 모듈을 추가해야 합니다.다음과 같이 HttpApplication의 Init 기능을 재정의하여 Global.asax에서 프로그래밍 방식으로 이 작업을 수행할 수 있습니다.
namespace ChangeRequestLanguage
{
public class Global : System.Web.HttpApplication
{
System.Web.IHttpModule mod = new libRequestLanguageChanger.RequestLanguageChanger();
public override void Init()
{
mod.Init(this);
base.Init();
}
protected void Application_Start(object sender, System.EventArgs e)
{
}
protected void Session_Start(object sender, System.EventArgs e)
{
}
protected void Application_BeginRequest(object sender, System.EventArgs e)
{
}
protected void Application_AuthenticateRequest(object sender, System.EventArgs e)
{
}
protected void Application_Error(object sender, System.EventArgs e)
{
}
protected void Session_End(object sender, System.EventArgs e)
{
}
protected void Application_End(object sender, System.EventArgs e)
{
}
}
}
또는 응용 프로그램 소스 코드가 없는 경우 Web.config에 항목을 추가할 수 있습니다.
<httpModules>
<add name="RequestLanguageChanger" type= "libRequestLanguageChanger.RequestLanguageChanger, libRequestLanguageChanger" />
</httpModules>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<add name="RequestLanguageChanger" type="libRequestLanguageChanger.RequestLanguageChanger, libRequestLanguageChanger" />
</modules>
</system.webServer>
</configuration>
시의항다니목. 하나인 용입니다.webServer는 시스템의 다른 IIS7+용입니다.6을 것입니다.
run AllManagedModulesForAllRequests' true라는 파일이 있습니다.
형식입니다."Namespace.Class, Assembly"를 C#프로젝트에 대해 C# 신 VB처럼 .NET으로 어셈블리를 작성하면 VB는 각 프로젝트에 대해 기본 네임스페이스를 생성하므로 문자열은 다음과 같습니다.
"[DefaultNameSpace.Namespace].Class, Assembly"
이 문제를 방지하려면 DLL을 C#으로 작성합니다.
여러 도메인을 허용할 뿐만 아니라 동적 도메인도 허용하는 접근 방식은 어떻습니까?
여기서 사용 사례는 iframe을 통해 Sharepoint 내부에 우리 사이트를 로드하는 Sharepoint 앱 파트입니다.문제는 쉐어포인트가 https://yoursite.sharepoint.com 와 같은 동적 하위 도메인을 가지고 있다는 것입니다.따라서 IE의 경우 ALLOW-FROM을 지정해야 합니다. https://.sharepoint.com
까다로운 비즈니스지만 다음 두 가지 사실을 알고 완료할 수 있습니다.
iframe이 로드되면 첫 번째 요청에 대한 X-Frame-Options만 유효성을 검사합니다.iframe이 로드되면 iframe 내에서 탐색할 수 있으며 이후 요청 시 헤더가 확인되지 않습니다.
또한 iframe이 로드되면 HTTP 참조자가 상위 iframe URL이 됩니다.
이 두 가지 사실을 서버 측면에서 활용할 수 있습니다.루비에서 저는 다음 코드를 사용하고 있습니다.
uri = URI.parse(request.referer)
if uri.host.match(/\.sharepoint\.com$/)
url = "https://#{uri.host}"
response.headers['X-Frame-Options'] = "ALLOW-FROM #{url}"
end
여기서는 상위 도메인을 기반으로 도메인을 동적으로 허용할 수 있습니다.이 경우 호스트가 sharepoint.com 에서 종료되어 클릭재킹으로부터 사이트를 안전하게 보호합니다.
이 접근 방식에 대한 피드백을 듣고 싶습니다.
MDN 사양에 따라,X-Frame-Options: ALLOW-FROM는 Chrome에서 지원되지 않으며 Edge 및 Opera에서 지원되지 않습니다.
Content-Security-Policy: frame-ancestors오버라이드X-Frame-Options(이 W3 사양에 따름), 그러나frame-ancestors호환성이 제한되어 있습니다.이 MDN 사양에 따르면 IE 또는 Edge에서는 지원되지 않습니다.
HTTP 헤더 필드 X-Frame-Options에 대한 RFC는 X-Frame-Options 헤더 값의 "ALLOW-FROM" 필드가 하나의 도메인만 포함할 수 있다고 명시합니다.여러 도메인은 허용되지 않습니다.
RFC는 이 문제에 대한 해결책을 제안합니다.해결 방법은 iframe srcurl에 url 매개 변수로 도메인 이름을 지정하는 것입니다.그런 다음 iframe srcurl을 호스트하는 서버는 url 매개 변수에 지정된 도메인 이름을 확인할 수 있습니다.도메인 이름이 유효한 도메인 이름 목록과 일치하는 경우, 서버는 "ALLOW-FROM domain-name" 값으로 X-Frame-Options 헤더를 보낼 수 있습니다. 여기서 domain name은 원격 콘텐츠를 포함하려는 도메인의 이름입니다.도메인 이름이 지정되지 않았거나 유효하지 않은 경우 X-Frame-Options 헤더를 "deny" 값으로 보낼 수 있습니다.
엄밀하게 말하면 안 됩니다.
그러나 지정할 수 있습니다.X-Frame-Options: mysite.com그러므로 허용합니다.subdomain1.mysite.com그리고.subdomain2.mysite.com하지만 네, 그것은 여전히 하나의 영역입니다.이에 대한 몇 가지 해결 방법이 있지만 RFC 사양에서 직접 읽는 것이 가장 쉬울 것 같습니다. https://www.rfc-editor.org/rfc/rfc7034
또한 CSP(Content-Security-Policy) 헤더의frame-ancestordirective는 X-Frame-Options를 폐지합니다.자세한 내용은 여기를 참조하십시오.
같지는 가 있을 수 : . 다른 옵션이 있습니다.ALLOWALL 프로덕션 할 수 있습니다. 이는 테스트/사전 프로덕션 환경에서 유용할 수 있습니다.
IE용 X-Frame-Options와 다른 브라우저용 Content-Security-Policy를 추가해야 했습니다.그래서 저는 다음과 같은 것을 했습니다.
if allowed_domains.present?
request_host = URI.parse(request.referer)
_domain = allowed_domains.split(" ").include?(request_host.host) ? "#{request_host.scheme}://#{request_host.host}" : app_host
response.headers['Content-Security-Policy'] = "frame-ancestors #{_domain}"
response.headers['X-Frame-Options'] = "ALLOW-FROM #{_domain}"
else
response.headers.except! 'X-Frame-Options'
end
여러 도메인 및 하위 도메인에 대해 사용할 수 있는 규칙Apache그리고..htaccess아래와 같습니다.
Header always append Content-Security-Policy "frame-ancestors 'self' site1 site2;"
예:
은 아규래칙허니다합용다음만은▁only다니만 허용합니다.yoursite (self),https://example1.com/그리고.https://example2.com을 놓다iFrameyoursite.
Header always append Content-Security-Policy "frame-ancestors 'self' https://example1.com/ https://example.com;"
여기 참조 링크가 있습니다.
동일한 코드를 next.config.js에 넣습니다.
module.exports = {
async headers() {
return [
{
source: '/((?!embed).*)',
headers: [
{
key: 'X-Frame-Options',
value: 'SAMEORIGIN',
}
]
}
];
}
}
한 가지 가능한 해결 방법은 여기에 설명된 대로 "프레임 차단기" 스크립트를 사용하는 것입니다.
허용된 도메인을 확인하려면 "if" 문을 변경하기만 하면 됩니다.
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
//your domain check goes here
if(top.location.host != "allowed.domain1.com" && top.location.host == "allowed.domain2.com")
top.location = self.location;
}
Javascript가 활성화되지 않으면 악의적인 웹 사이트의 페이지 프레임 구성에 대한 보안 문제가 발생하지 않기 때문에 이 해결 방법은 안전할 것입니다.
예. 이 메서드는 다중 도메인을 허용합니다.
VB.NET
response.headers.add("X-Frame-Options", "ALLOW-FROM " & request.urlreferer.tostring())
언급URL : https://stackoverflow.com/questions/10205192/x-frame-options-allow-from-multiple-domains
'codememo' 카테고리의 다른 글
| 컨트롤러에서 필터를 사용하는 방법은 무엇입니까? (0) | 2023.05.18 |
|---|---|
| LINQ를 사용하여 문자열[]을 코드 한 줄에서 int[]로 변환 (0) | 2023.05.18 |
| 호스트 대 Dnsafe 호스트 (0) | 2023.05.13 |
| 를 사용하여 Windows에서 팝업 "토스터" 알림을 만듭니다.그물 (0) | 2023.05.13 |
| 이벤트에서 모든 이벤트 핸들러를 제거하는 방법 (0) | 2023.05.13 |