Como armazenar em cache formulários com um proxy reverso e lidar com tokens de formulários obsoletos?

8

Quando a API do formulário gera um formulário, ela também gera um token que é distribuído com o formulário em um campo oculto e espera-se retornar. Se for, o formulário é processado.

Se um formulário renderizado estiver sempre em cache, digamos, por Varnish , esse mecanismo será interrompido. O primeiro usuário que enviar o formulário consumirá o token e as tentativas seguintes de usá-lo serão rejeitadas.

Quais estratégias estão disponíveis para manter os formulários funcionando enquanto o cache é processado?

Letharion
fonte
Você tem certeza disso? Criei sites com formulários e proxies reversos e não vi nenhum problema. A única coisa que você deve observar, em geral, é garantir que as páginas de resultados não sejam armazenadas em cache.
Alfred Armstrong
Eu adoraria provar que estou errado, pois isso resolveria meu problema, mas sim, tenho certeza. :) Verifique as funções form_ {g, s} et_cache para obter detalhes.
Letharion
Para usuários anônimos, tenho certeza de que uma página com um formulário pode ser armazenada em cache com segurança. Para usuários não anônimos, proxies reversos são problemáticos em qualquer caso.
Alfred Armstrong
2
(Tokens são gerados apenas quando um usuário tem uma identificação.)
Alfred Armstrong
11
Ah, isso faz sentido. Infelizmente, meus usuários neste caso são autenticados. Talvez a pergunta deva ser reformulada para incluir isso.
Letharion

Respostas:

5

Eu uso o BOA nos meus sites, mas, por padrão, o BOA simplesmente desativa o cache de front-end em tempo real para o envio de formulários. Além da minha experiência real, deparei com uma cruz de um ano de idade artificial sobre como o New Zealand Post lida com Drupal & Varnish e a questão do token de formulário. Santo John Wayne, é uma leitura obrigatória para o cache do Drupal - realmente. Focalizando apenas a questão do formulário:

A peça final do nosso quebra-cabeça é o módulo Cookie Cache Bypass Advanced , que define automaticamente um cookie NO_CACHE especial sempre que o usuário envia um formulário POST no site, incluindo itens como o formulário de login. Nosso Varnish está configurado para ignorar o cache da página (mas não o cache ESI) quando vê esse cookie.

Você também pode desativar os tokens de formulário quando a produção XSRF não for adquirida em form_alter (desmarcado ($ form ['# token']);) ou ($ form ['# token'] = FALSE;)

Um artigo de desempenho do Acquia Drupal apresenta um Authcache do módulo Drupal , mas, ao ler o documento no Authcache, ele realiza o cache com um espaço reservado para o formulário (sem armazenar o formulário):

O Authcache tenta interceptar qualquer conteúdo personalizado e configurar um espaço reservado no HTML. Depois que a página é carregada, um retorno de chamada do Ajax é usado para recuperar dados personalizados e preencher os espaços reservados, atualizando dinamicamente o HTML da página.

Marcadores de posição atuais do Authcache: tokens de formulário (somente usuários conectados; exigido por> Drupal para impedir ataques de falsificação de solicitação entre sites)

A estratégia é armazenar tudo em cache , exceto o formulário . Então, abordando todo o resto: talvez o Varnish não seja usado, Memcache & Redis? Minha estratégia seria usar o que o BOA oferece, porque eu uso o BOA e os assistentes por trás dele ( omega8.cc ) sabem muito mais do que eu. Eu não acho que exista um cache externo que resolva o problema. Todos eles parecem ignorar o formulário.

Faça cache parcial com o authcache acima mencionado e com os Views and Panels aprimorados, como mencionado no artigo da NZ Post e descrito pela confiança no cérebro do Wunderkraut - antigo, mas aborda o problema.

Use o Drupal ESI Module e o verniz é parcialmente compatível com ESI):

O ESI - ou Edge Side Include - é uma solução de cache de alto desempenho para usuários autenticados, mas também pode ser útil para usuários anônimos.

Normalmente, as páginas personalizadas para usuários autenticados (mesmo pequenas personalizações, como um bloco que diz "Conectado como manarth") impedirão que proxies reversos (que podem executar facilmente 100 vezes mais rápido que o Drupal) armazenem em cache a página, porque as mensagens destinado a um usuário pode ser visto por outro.

Espero que seja mais útil.

Tom
fonte
Uma rápida olhada no código sugere que o módulo ESI não faz nada em relação à validação de formulário; nenhuma menção ao manuseio de token, nem qualquer forma interessante é alterada. É possível que você simplesmente não tenha armazenado em cache nenhum formulário que exija autenticação em verniz, e é por isso que nunca viu esse problema?
Letharion
Acontece que é exatamente isso que está acontecendo, o BOA ignora o cache do front-end em tempo real para obter formulários (desculpe pela minha resposta incompleta / incorreta anteriormente). O ESI ainda é parte importante da estratégia "armazenar tudo em cache" agora na minha resposta, mesmo que não seja diretamente resolvida.
Tom
Esse artigo da NZ foi realmente muito interessante. No entanto, pelo que sei, ele aborda apenas o problema do token com: "Nos casos em que você tem certeza de que a proteção XSRF não é importante ... O Drupal fornece um mecanismo para desativar os tokens de formulário", o que não é útil em o meu caso.
Letharion
Muitas informações úteis e, definitivamente, outras pessoas poderão aplicá-las a seus problemas. +1 e, uma vez que faltam apenas uma hora, também posso estar ciente da recompensa. :)
Letharion
0

Uma solução em potencial seria desativar o token juntamente com $form[‘#token’] = FALSE;, substituir o retorno de chamada de envio para, em vez de realmente postar o comentário, gerar novamente o formulário original com um token e pedir ao usuário para confirmar a postagem.

Se o usuário suportar o ECMAScript , é possível melhorar a experiência do usuário com um recurso de serviços que expõe a geração de formulários de novos tokens de formulário e insere o formulário relevante no form_cache. Então, assim que o usuário se concentrar no formulário e, portanto, provavelmente quiser enviá-lo, desative o botão de envio, busque um novo token e insira-o no formulário já renderizado e ative o botão de envio novamente.

Letharion
fonte