type text_field_tag select_tag rails label_tag form_tag form_for check_box_tag bootstrap ruby-on-rails forms caching authenticity-token

text_field_tag - Ruby on Rails forma el almacenamiento en caché de la página incluyendo authenticity_token



select_tag rails (5)

Como publicó Matchu, puedes implementar el punto dos de esta publicación (el mismo enlace que publicó, pero también se encontró a través de mi Google). Esto agrega una dependencia en JavaScript, que puede o no ser algo que desea.

Alternativamente, usted podría mirar en caché de fragmentos . Esto le permite almacenar en caché ciertas partes de una página, pero aún así generar las partes dinámicas (como formularios con tokens de autenticidad). Usando esta técnica, podría almacenar en caché el resto de la página, pero generar un nuevo formulario para cada solicitud.

Una solución final (pero la menos favorable) es deshabilitar el token de autenticidad para esa acción específica. Puede hacer esto agregando lo siguiente al principio del controlador que genera ese formulario:

protect_from_forgery :except => [:your_action]

También puede desactivar protect_from_forgery para todo el controlador agregando lo siguiente al principio:

skip_before_filter :verify_authenticity_token

Tengo un formulario simple de Ruby on Rails que incluye una clave de autenticidad. Desafortunadamente, me perdí eso cuando la página almacena en caché esta página, entonces el token de autenticidad se vuelve inválido. Sin embargo, me alegro de haberlo descubierto.

¿Cómo resuelves el almacenamiento en caché en tal caso?


Como una solución más general, también puede reemplazar todas las identidades de autenticación en caché con las actuales:

module CacheHelper def cache_with_updated_csrf(*a, &block) Nokogiri::HTML::DocumentFragment.parse( capture { cache(*a,&block) } ).tap do |doc| doc.css("input[name=#{request_forgery_protection_token}]").each { |e| e[''value''] = form_authenticity_token } end.to_html.html_safe end end

Y use = cache_with_updated_csrf do lugar de - cache do en sus vistas. Felicitaciones a Bernard Potocki por la idea.


No parece ser un problema bien resuelto. El punto dos en esta publicación del blog describe cómo realizar la tarea utilizando jQuery, pero eso introduce una dependencia de Javascript. Sopesar sus opciones, supongo.


Puede representar una etiqueta personalizada en el marcado almacenado en caché y reemplazarla con el formulario representado en cada solicitud.

module CacheHelper # Our FORM is deeply nested in the CACHED_PARTIAl, which we # cache. It must be rendered on every request because of its # authenticity_token by protect_from_forgery. Instead of splitting up the # cache in multiple fragments, we replace a special tag with the custom # form. def cache_with_bla_form(resource, &block) form = nil doc = Nokogiri::HTML::DocumentFragment.parse( capture { cache("your_cache_key",&block) } ) doc.css(''uncachable_form'').each do |element| form ||= render(:partial => ''uncachable_form'', :resource => resource) element.replace form end doc.to_html end end

Y, en su opinión, simplemente genera una etiqueta uncachable_form vacía.

<%- cache_with_bla_form resource do %> # cachable stuff.. <uncachable_form /> # more cachable stuff <%- end %>

Sí, esto puede ser considerado como un Hack, pero no aflojará la protección de la falsificación, no necesita JS y disminuirá la ganancia de rendimiento por el almacenamiento en caché solo un poco. Creo que alguien implementó un patrón similar como un Rack Middleware.


Seguí la solución general de Niklas Hofer, pero descubrí que su implementación no coincidía con la semántica exacta del ayudante de caché de Rails. Es decir, intentó devolver el HTML almacenado en caché desde el ayudante, en lugar de escribirlo en el búfer usando safe_concat , que es lo que hace el ayudante de Rails.

El uso del ayudante de Rails es así:

- cache do = something

Mientras que su solución requería esta sintaxis:

= cache_with_updated_csrf do = something

Por coherencia, preferiría que estos funcionen de la misma manera. Por eso utilicé esta sintaxis:

- cache_form do = something

Aquí está mi implementación. También omitirá el almacenamiento en caché cuando el almacenamiento en caché está deshabilitado, como lo hace el ayudante de Rails.

module CacheHelper # Cache a form with a fresh CSRF def cache_form(name = {}, options = nil, &block) if controller.perform_caching fragment = fragment_for(name, options, &block) fragment_with_fresh_csrf = Nokogiri::HTML::DocumentFragment.parse( fragment ).tap do |doc| doc.css("input[name=#{request_forgery_protection_token}]").each { |e| e[''value''] = form_authenticity_token } end.to_html safe_concat fragment_with_fresh_csrf else yield end nil end end