Superando "Exibição proibida por X-Frame-Options"


420

Estou escrevendo uma pequena página da Web cujo objetivo é enquadrar algumas outras páginas, simplesmente para consolidá-las em uma única janela do navegador para facilitar a visualização. Algumas das páginas que estou tentando enquadrar proíbem o enquadramento e lançam um "Recusou-se a exibir o documento porque a exibição é proibida pelo X-Frame-Options". erro no Chrome. Entendo que essa é uma limitação de segurança (por um bom motivo) e não tenho acesso para alterá-la.

Existe algum método alternativo de enquadramento ou não-enquadramento para exibir páginas em uma única janela que não seja acionada pelo cabeçalho X-Frame-Options?


117
Se forem suas páginas, remova o limitador de quadros. Caso contrário, respeite os desejos do autor da página e NÃO O QUADRO.
121311 Marc B

Se você está recebendo esse erro para um aplicativo do Facebook e usando chamadas AJAX, li em algum lugar que o Facebook realmente gosta de usar # tags para seu contato ajax, então tente alterar os links, funcionou para mim.
eric.itzhak

28
O @MarcB Chrome e Firefox enquadram eticamente sites não pertencentes ao chrome nativo da interface do usuário. Esses programas também permitem políticas relaxadas de mesma origem para seus proprietários, o FWIW. Como disse Garen-checkly: "Estou escrevendo uma pequena página da Web cujo objetivo é enquadrar algumas outras páginas, simplesmente para consolidá-las em uma única janela do navegador para facilitar a visualização". Isso basicamente estende o navegador da web e seria completamente ético. A intenção declarada não é diferente de escrever um script bash para abrir e organizar as janelas do navegador.
Samuel Danielson

1
Verifique Surfly . Pode fazer exatamente o que você precisa.
muodov

1
@ MarcB Isso não ajuda. O OP pode não se importar com os desejos do autor da página.
precisa saber é o seguinte

Respostas:


211

Eu tive um problema semelhante: estava tentando exibir o conteúdo de nosso próprio site em um iframe (como uma caixa de diálogo no estilo lightbox com o Colorbox ) e onde tínhamos um cabeçalho "X-Frame-Options SAMEORIGIN" em todo o servidor no servidor de origem impedindo que ele seja carregado em nosso servidor de teste.

Isso não parece estar documentado em nenhum lugar, mas se você pode editar as páginas que você está tentando iframe (por exemplo, são suas próprias páginas), basta enviar outro cabeçalho X-Frame-Options com qualquer sequência de caracteres desativada os comandos SAMEORIGIN ou DENY.

por exemplo. para PHP, colocando

<?php
    header('X-Frame-Options: GOFORIT'); 
?>

na parte superior da página, os navegadores combinam os dois, o que resulta em um cabeçalho de

X-Frame-Options SAMEORIGIN, GOFORIT

... e permite carregar a página em um iframe. Isso parece funcionar quando o comando SAMEORIGIN inicial foi definido no nível do servidor e você deseja substituí-lo em um caso de página por página.

Muito bem sucedida!


3
Eu tinha uma moldura em torno de um site. No meu site, estou redirecionando para o Instagram for OAUTH. Como o Instagram envia, X-Frame-Options: SAMEORIGINnão há como fazer isso dentro do quadro. Você deve usar um pop-up.
Steve Tauber

16
Com o PHP, provavelmente é melhor usar a nova header_removefunção, desde que você a tenha disponível (> = 5.3.0).
um gato

11
Ou você pode editar .htaccess se desejar remover o X-Frame-Options de um diretório inteiro. Basta adicionar a linha:Header always unset X-Frame-Options
Jay

4
@cawecoy: Bem, sim, o ponto principal é que é inválido. Ele conta com navegadores que ignoram o cabeçalho inválido e 'falham em abrir', que é um comportamento não especificado e bastante desonesto. GOFORIT(ou outro token inválido arbitrário aleatório) está violando deliberadamente uma medida de segurança aplicada por um servidor; se você tem o controle do servidor (o que você deve fazer por qualquer serviço público real), a coisa certa a fazer é configurar o servidor para não configurar o cabeçalho em primeiro lugar.
bobince

31
Parece que isso não funciona mais no Chrome. Valores inválidos fazem com que o valor padrão seja DENY.
jamesfm

159

Se você está recebendo esse erro em um vídeo do YouTube, em vez de usar o URL completo, use o URL incorporado nas opções de compartilhamento. Vai parecerhttp://www.youtube.com/embed/eCfDxZxTBW4

Você também pode substituir watch?v=com embed/modo http://www.youtube.com/watch?v=eCfDxZxTBW4torna-sehttp://www.youtube.com/embed/eCfDxZxTBW4


14
Ah, progresso ... Eu gostaria que eles nos redirecionassem para a página incorporada, em vez de causar um erro e me fazer reescrever meus scripts!
Joeytwiddle #

122

Se você estiver recebendo esse erro ao tentar incorporar um mapa do Google em um iframe, precisará adicionar &output=embedao link de origem.


120
Isso é verdade apenas para a incorporação de mapas do Google em um iframe, e não em uma "solução" geral.
Benjamin Wohlwend

17
Eu precisava incorporar um mapa do Google em uma mesa de luz, assim que esta "solução" foi perfeita
yitwail

5
Se você está tentando fazer isso com uma intenção na web do Twitter, esqueça. Acabamos de perder o dia todo tentando diferentes plugins de caixa de luz apenas para descobrir isso "Embora você possa fornecer links para intenções em IFRAMEs e widgets, as páginas resultantes não podem ser carregadas em um IFRAME." Fonte: site do Twitter.
Gubatron

6
Isso não funciona se você estiver tentando carregar o iframe src depois que o resto da página for carregado, mesmo se você adicionar&output=embed
pathfinder

1
@ pathfinder Isso funcionou para mim quando tive problemas ao carregar o iframe src depois que a página foi carregada
David Sykes

61

ATUALIZAÇÃO 2019: Você pode desvio X-Frame-Optionsem uma <iframe>usando apenas JavaScript e meu do lado do cliente X-Frame-Bypass Web Component. Aqui está uma demonstração: Hacker News em umX-Frame-Bypass . (Testado no Chrome e Firefox.)


3
Essa é uma solução interessante. Funciona bem no FF / Chrome / Opera, mas não funciona no IE / Edge. Alguém que sabe algo que vai?
Coletor

7
Isso não funciona mais. Ele fornece "Recusou-se a exibir ' news.ycombinator.com ' em um quadro, porque definiu 'X-Frame-Options' para 'DENY'." como esperado
g.pickardou 11/12/2015

2
@ g.pickardou Funciona para mim no Google Chrome 46, posso ver o Hacker News em um iframe.
Niutech

1
@niutech que mexe depois de recarregar a página no Chrome 64, mas a primeira vez que carrego a página não funciona. (Tente em incógnito.)
Carl Walsh

1
Obrigado, isso é incrível!
Andrew Gans

23

Adicionando um

  target='_top'

para o meu link na guia facebook corrigiu o problema para mim ...


1
Eu tive o mesmo problema com o iframe do Paypal contido em outro iframe. Funciona agora! Obrigado
Fabrizio Fortino

4
Também adicionei target = '_ top', mas o problema com esta solução é que o link agora é aberto fora do iframe em uma nova guia sem a tela do facebook.
sumitkanoje



13

Eu tive o mesmo problema quando tentei incorporar o moodle 2 no iframe, a solução é Site administration ► Security ► HTTP securitye verifiqueAllow frame embedding


bem feito para o método moodle, pois os outros métodos falham / são substituídos.
ericosg

7

Essa é a solução pessoal !!

FB.Event.subscribe('edge.create', function(response) {
    window.top.location.href = 'url';
});

A única coisa que funcionou para aplicativos do facebook!



6

Solução para carregar um site externo em um iFrame, mesmo sendo difícil, a opção x-frame está configurada para negar no site externo.

Se você deseja carregar outro site em um iFrame e receber o Display forbidden by X-Frame-Options”erro, poderá superá-lo criando um script proxy do lado do servidor.

O srcatributo do iFrame pode ter um URL parecido com este:/proxy.php?url=https://www.example.com/page&key=somekey

Então proxy.php seria algo como:

if (isValidRequest()) {
   echo file_get_contents($_GET['url']);
}

function isValidRequest() {
    return $_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['key']) && 
    $_GET['key'] === 'somekey';
}

Isso passa pelo bloco, porque é apenas uma solicitação GET que pode ter sido uma visita comum à página do navegador.

Esteja ciente: você pode querer melhorar a segurança neste script. Porque os hackers podem começar a carregar páginas da web por meio do seu script de proxy.


Eu estava fazendo isso há algumas semanas e quaisquer URLs relativos usados ​​na página externa não funcionam ao usar o eco. (Geralmente, CSS e / ou JS, então você pode não ter funcionalidade completa a menos que modifique os URLs antes de ecoar.) A menos que eu tenha perdido alguma coisa ...,
ultrageek

Não sabe por que isso acontece com você ... Ele deve funcionar como uma solicitação HTTP normal, assim como um usuário final faria ao visitar o URL. Portanto, o resultado de get_file_contents () deve ser uma página HTML completamente funcional.
Floris

5

Eu tentei quase todas as sugestões. No entanto, a única coisa que realmente resolveu o problema foi:

  1. Crie um .htaccessna mesma pasta onde está o seu arquivo PHP.

  2. Adicione esta linha ao htaccess:

    Header always unset X-Frame-Options

A incorporação do PHP por um iframe de outro domínio deve funcionar posteriormente.

Além disso, você pode adicionar no início do seu arquivo PHP:

header('X-Frame-Options: ALLOW');

O que, no entanto, não era necessário no meu caso.


Cabeçalho sempre desactivado X-Frame-Options em htaccess fez o truque para mim
Ujwal Dhakal

4

Eu tive o mesmo problema com o mediawiki, porque o servidor negou a incorporação da página em um iframe por motivos de segurança.

Eu resolvi escrever

$wgEditPageFrameOptions = "SAMEORIGIN"; 

no arquivo de configuração php mediawiki.

Espero que ajude.


3

FWIW:

Tivemos uma situação em que precisávamos matar o nosso iFramequando esse código "disjuntor" apareceu. Então, usei o PHP function get_headers($url);para verificar a URL remota antes de mostrá-la em iFrame. Para um melhor desempenho, armazenei em cache os resultados em um arquivo para não fazer uma conexão HTTP toda vez.


3

Eu estava usando o Tomcat 8.0.30, nenhuma das sugestões funcionou para mim. Como estamos procurando atualizar X-Frame-Optionse configurá-lo ALLOW, eis como eu configurei para permitir iframes incorporados:

  • Navegue para o diretório conf do Tomcat, edite o arquivo web.xml
  • Adicione o filtro abaixo:
<filter>
            <filter-name>httpHeaderSecurity</filter-name>
            <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
                   <init-param>
                           <param-name>hstsEnabled</param-name>
                           <param-value>true</param-value>
                   </init-param>
                   <init-param>
                           <param-name>antiClickJackingEnabled</param-name>
                           <param-value>true</param-value>
                   </init-param>
                   <init-param>
                           <param-name>antiClickJackingOption</param-name>
                           <param-value>ALLOW-FROM</param-value>
                   </init-param>
            <async-supported>true</async-supported>
       </filter>

       <filter-mapping>
                   <filter-name>httpHeaderSecurity</filter-name>
                   <url-pattern>/*</url-pattern>
                   <dispatcher>REQUEST</dispatcher>
       </filter-mapping> 
  • Reinicie o serviço Tomcat
  • Acesse os recursos usando um iFrame.

2

A única pergunta que tem um monte de respostas. Bem-vindo ao guia que eu gostaria de ter quando estava lutando para fazê-lo funcionar às 10:30 da noite no dia do prazo final ... O FB faz algumas coisas estranhas com aplicativos de tela e, bem, você foi avisado. Se você ainda estiver aqui e tiver um aplicativo Rails que aparecerá atrás de uma tela do Facebook, precisará de:

Gemfile:

gem "rack-facebook-signed-request", :git => 'git://github.com/cmer/rack-facebook-signed-request.git'

config / facebook.yml

facebook:
  key: "123123123123"
  secret: "123123123123123123secret12312"

config / application.rb

config.middleware.use Rack::Facebook::SignedRequest, app_id: "123123123123", secret: "123123123123123123secret12312", inject_facebook: false

config / inicializadores / omniauth.rb

OmniAuth.config.logger = Rails.logger
SERVICES = YAML.load(File.open("#{::Rails.root}/config/oauth.yml").read)
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :facebook, SERVICES['facebook']['key'], SERVICES['facebook']['secret'], iframe:   true
end

application_controller.rb

before_filter :add_xframe
def add_xframe
  headers['X-Frame-Options'] = 'GOFORIT'
end

Você precisa de um controlador para ligar a partir das configurações de tela do Facebook, usei /canvas/e fiz o percurso ser o principal SiteControllerpara este aplicativo:


class SiteController < ApplicationController
  def index
    @user = User.new
  end
  def canvas
    redirect_to '/auth/failure' if request.params['error'] == 'access_denied'
    url = params['code'] ? "/auth/facebook?signed_request=#{params['signed_request']}&state=canvas" : "/login"
    redirect_to url
  end
  def login
  end
end

login.html.erb


<% content_for :javascript do %>
  var oauth_url = 'https://www.facebook.com/dialog/oauth/';
  oauth_url += '?client_id=471466299609256';
  oauth_url += '&redirect_uri=' + encodeURIComponent('https://apps.facebook.com/wellbeingtracker/');
  oauth_url += '&scope=email,status_update,publish_stream';
console.log(oauth_url);
  top.location.href = oauth_url;
<% end %>

Fontes

  • Acho que a configuração veio do exemplo do omniauth.
  • O arquivo gem (que é a chave !!!) veio de: slideshare que eu aprendi ...
  • Essa questão da pilha tinha todo o ângulo do Xframe, então você terá um espaço em branco, se não colocar esse cabeçalho no controlador de aplicativo.
  • E meu homem @rafmagana escreveu este guia heroku , que agora você pode adotar para trilhos com esta resposta e os ombros dos gigantes com os quais você anda.

2

target = '_ pai'

Usando a idéia de Kevin Vella, tentei adicionar esse atributo para formar elementos criados pelo gerador de botões do PayPal. Trabalhou para mim para que o Paypal não abra em uma nova janela / guia do navegador.


Infelizmente, isso também não parece funcionar para o safari.
Wtower 30/06/16

1

Não tenho certeza de quão relevante é, mas criei uma solução alternativa para isso. No meu site, eu queria exibir o link em uma janela modal que continha um iframe que carrega o URL.

O que fiz foi vincular o evento click do link a essa função javascript. Tudo isso é fazer uma solicitação para um arquivo PHP que verifica os cabeçalhos de URL para X-FRAME-Options antes de decidir se deseja carregar o URL na janela modal ou redirecionar.

Aqui está a função:

  function opentheater(link, title){
        $.get( "url_origin_helper.php?url="+encodeURIComponent(link), function( data ) {
  if(data == "ya"){
      $(".modal-title").html("<h3 style='color:480060;'>"+title+"&nbsp;&nbsp;&nbsp;<small>"+link+"</small></h3>");
        $("#linkcontent").attr("src", link);
        $("#myModal").modal("show");
  }
  else{
      window.location.href = link;
      //alert(data);
  }
});


        }

Aqui está o código do arquivo PHP que o verifica:

<?php
$url = rawurldecode($_REQUEST['url']);
$header = get_headers($url, 1);
if(array_key_exists("X-Frame-Options", $header)){
    echo "nein";
}
else{
    echo "ya";
}


?>

Espero que isto ajude.


1

Me deparei com esse problema ao executar um site wordpress. Tentei todo o tipo de coisas para corrigi-lo e não sabia ao certo como, afinal, o problema era porque eu estava usando o encaminhamento de DNS com mascaramento e os links para sites externos não estavam sendo tratados adequadamente. ou seja, meu site estava hospedado em http: //123.456.789/index.html, mas foi ocultado para ser executado em http://somewebSite.com/index.html . Quando inseri http: //123.456.789/index.html no navegador, clicar nesses mesmos links não resultou em problemas de origens de quadros X no console JS, mas executando http://somewebSite.com/index.htmlfez. Para mascarar adequadamente, você deve adicionar os servidores de nomes DNS do host ao seu serviço de domínio, por exemplo, godaddy.com deve ter servidores de nomes, por exemplo, ns1.digitalocean.com, ns2.digitalocean.com, ns3.digitalocean.com, se você estiver usando digitalocean.com como seu serviço de hospedagem.


1
Acabei fazendo: remove_action( 'admin_init', 'send_frame_options_header',10);para ignorar este problema ...
majick

1

É surpreendente que ninguém aqui tenha mencionado Apacheas configurações ( *.confarquivos) do servidor ou .htaccesso próprio arquivo como causa deste erro. Pesquise seus arquivos de configuração .htaccessou Apache, certificando-se de que você não tenha o seguinte definido como DENY:

Header always set X-Frame-Options DENY

Mudar para SAMEORIGIN, faz as coisas funcionarem conforme o esperado:

Header always set X-Frame-Options SAMEORIGIN


já foi mencionado antes - veja o comentário de @Jay na resposta stackoverflow.com/a/6767901/1875965 #
Sandra

Eu configuro o arquivo .conf O cabeçalho sempre define X-Frame-Options SAMEORIGIN!
GeekHades

Mas como isso é relevante para a questão aqui, onde o cabeçalho vem de servidores estrangeiros , diretamente para o cliente , o IOW nem mesmo seu servidor está envolvido? Estou esquecendo de algo?
Sz.

1

A única resposta real, se você não controlar os cabeçalhos da sua fonte desejada no iframe, é procurá-la. Faça com que um servidor atue como cliente, receba a fonte, retire os cabeçalhos problemáticos, adicione CORS, se necessário, e faça ping no seu próprio servidor.

Há uma outra resposta explicando como escrever esse proxy. Não é difícil, mas eu tinha certeza de que alguém já tinha feito isso antes. Foi difícil encontrá-lo, por algum motivo.

Finalmente encontrei algumas fontes:

https://github.com/Rob--W/cors-anywhere/#documentation

^ preferido. Se você precisar de uso raro, acho que você pode simplesmente usar o aplicativo heroku dele. Caso contrário, é um código para executá-lo em seu próprio servidor. Observe com certeza quais são os limites.

Whateverorigin.org

Segunda opção, mas bastante antiga. opção supostamente mais recente em python: https://github.com/Eiledon/alloworigin

então há a terceira opção:

http://anyorigin.com/

O que parece permitir um pouco de uso gratuito, mas o colocará em uma lista pública de vergonha se você não pagar e usar uma quantia não especificada, da qual você só poderá ser removido se pagar a taxa ...


0

Não mencionado, mas pode ajudar em alguns casos:

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
    if (xhr.readyState !== 4) return;
    if (xhr.status === 200) {
        var doc = iframe.contentWindow.document;
        doc.open();
        doc.write(xhr.responseText);
        doc.close();
    }
}
xhr.open('GET', url, true);
xhr.send(null);

0

Use esta linha abaixo, em vez da header()função.

echo "<script>window.top.location = 'https://apps.facebook.com/yourappnamespace/';</script>";

0

Eu tive esse problema e resolvi-o editando o activationd.conf

<IfModule headers_module>
    <IfVersion >= 2.4.7 >
        Header always setifempty X-Frame-Options GOFORIT
    </IfVersion>
    <IfVersion < 2.4.7 >
        Header always merge X-Frame-Options GOFORIT
    </IfVersion>
</IfModule>

mudei SAMEORIGIN para GOFORIT e reiniciei o servidor


-1

Tente isso, acho que ninguém sugeriu isso no tópico. Isso resolverá 70% do seu problema. Em algumas outras páginas, você precisa refazer, eu tenho a solução completa, mas não para o público,

ADICIONE abaixo ao seu iframe

sandbox = "scripts de permissão com a mesma origem e scripts de permissão"


1
o sandboxing reduz privilégios, não os adiciona. consulte html5rocks.com/en/tutorials/security/sandboxed-iframes #
Kyle Baker

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.