LoginSignup
0
0

More than 3 years have passed since last update.

[Rails][Turbolinks] inline Javascript が実行されない 解決法

Posted at

Javascript周り の取り扱いが難しい Turbolinks

起こったこと

ページ毎に任意のJavascript を実行したいが
普通に書いたら以下エラー。

ページ遷移でも同様。

ChromeDeveloperConsole
Refused to execute inline script because it violates the following Content Security Policy directive: 
"script-src 'self' https: 'unsafe-inline' 'nonce-UiVx2CiP0HHN9jOOSEG43g=='". 
Note that 'unsafe-inline' is ignored if either a hash or nonce value is present in the source list.

Content-Security-Policy (CSP) (Cross Site Scripting (XSS) や data injection 攻撃を防ぐための HTTP の仕様)のために
ブラウザでの Javascript 実行が制限されている。

解決法

Rails 側で nonce を発行し、Javascript を認証する。
(HTTPヘッダに追加)

views/layouts/head.html.slim
= csp_meta_tag
config/initializers/content_security_policy.rb
Rails.application.config.content_security_policy_nonce_generator = -> (request) do
  # use the same csp nonce for turbolinks requests
  if request.env['HTTP_TURBOLINKS_REFERRER'].present?
    request.env['HTTP_X_TURBOLINKS_NONCE']
  else
    SecureRandom.base64(16)
  end

script タグに nonce をつける

some_page.html.slim
= javascript_tag, nonce: true
 | console.log('JS here');

Turbolinks のEvent に合わせて、nonce を入れ替える。

application.js
document.addEventListener('turbolinks:request-start', function(event) {
  var nonceTag = document.querySelector("meta[name='csp-nonce']");
  if (nonceTag) event.data.xhr.setRequestHeader('X-Turbolinks-Nonce', nonceTag.content);
});
document.addEventListener('turbolinks:before-cache', function() {
  Array.prototype.forEach.call(document.querySelectorAll('script[nonce]'), function(element) {
    if (element.nonce) element.setAttribute('nonce', element.nonce);
  });
});

Turbolinks Event list

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0