新手问题 站点启用 https 协议后,任何 post 请求都会:Can't verify CSRF token authenticity (基于 homeland 的 docker 部署)

imwildcat · December 03, 2016 · Last by kooglezhang replied at December 06, 2016 · 4697 hits

站点启用 https 协议后,任何 post 请求都会:Can't verify CSRF token authenticity。 get 请求一切正常。 附(nginx 配置文件,基于 homeland):

# nginx.conf
# DOT not change this.
user root;
worker_processes auto;
pid /var/www/pids/nginx.pid;
daemon off;

load_module modules/ngx_http_geoip_module.so;

events {
  worker_connections 65535;
  multi_accept on;
  use epoll;
}

http {
  sendfile on;
  client_max_body_size 8m;

  tcp_nopush off;
  tcp_nodelay on;

  limit_conn_zone $binary_remote_addr zone=one:100m;
  keepalive_timeout 15;
  types_hash_max_size 2048;

  include /etc/nginx/mime.types;
  default_type application/octet-stream;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  access_log /var/www/log/nginx-access.log;
  error_log /var/www/log/nginx-error.log;

  # DO NOT CHANGE THIS
  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  # DO NOT CHANGE THIS
  include /etc/nginx/conf.d/*.conf;
}
# DO NOT CHANGE THIS
proxy_cache_path /var/www/cache/uploads-thumb levels=1:2 keys_zone=uploads_thumb:10m max_size=50G;

upstream app_backend {
  server app:7000 fail_timeout=0;
  keepalive 3;
}

log_format timed_combined '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent" '
                          '$request_time $upstream_response_time $pipe';

server {
  listen 80 default_server;
  listen 443 ssl http2;

  location /nginx_status {
    allow 127.0.0.1;
    deny all;
    stub_status on;
  }

  root /var/www/[myapp]/public;

  access_log /var/www/log/[myapp]-access.log timed_combined buffer=1k;
  error_log  /var/www/log/[myapp]-error.log;

  # ssl_certificate     /var/www/ssl/your-host.crt;
  # ssl_certificate_key /var/www/ssl/your-host.key;

  # DO NOT CHANGE THIS
  location ~ (/system|/avatar.png|/favicon.ico|/*.txt) {
    access_log        off;
    expires           7d;
    gzip_static on;
    add_header  Cache-Control public;
  }

  location /404.png {
    root /etc/nginx/html;
    rewrite ^ /404.png break;
  }

  location /415.png {
    root /etc/nginx/html;
    rewrite ^ /415.png break;
  }

  # DO NOT CHANGE THIS
  location /assets {
    access_log        off;
    expires           365d;
    gzip_static on;
    add_header  Cache-Control public;
  }

  # DO NOT CHANGE THIS
  # Generate image thumb on the fly
  location /uploads {
    expires 7d;
    gzip_static on;

    add_header Cache-Control public;
    # add_header X-Pownered "nginx_image_filter";
    add_header X-Cache-Status $upstream_cache_status;

    proxy_pass http://127.0.0.1/_img/uploads;
    proxy_cache uploads_thumb;
    proxy_cache_bypass $http_pragma;
    proxy_cache_key "$host$document_uri";
    proxy_cache_valid 200 7d;
    proxy_cache_use_stale error timeout invalid_header updating;
    proxy_cache_revalidate on;
    proxy_intercept_errors on;
    error_page   415 = /415.png;
    error_page   404 = /404.png;
  }

  location ~* /_img/uploads/(.+)!(large|lg|md|sm|xs)$ {
    set $filename /uploads/$1;

    if (-f $filename) {
      break;
    }

    set $img_version $2;
    set $img_type resize;
    set $img_w    -;
    set $img_h    -;
    if ($img_version = 'large') {
      set $img_type resize;
      set $img_w    1920;
    }
    if ($img_version = 'lg') {
      set $img_type crop;
      set $img_w    192;
      set $img_h    192;
    }
    if ($img_version = 'md') {
      set $img_type crop;
      set $img_w    96;
      set $img_h    96;
    }
    if ($img_version = 'sm') {
      set $img_type crop;
      set $img_w    48;
      set $img_h    48;
    }
    if ($img_version = 'xs') {
      set $img_type crop;
      set $img_w    32;
      set $img_h    32;
    }
    rewrite ^ /_$img_type;
  }

  location /_img/uploads {
    alias /var/www/[myapp]/public/uploads/$filename;
    expires 7d;
  }

  # location /_resize {
  #   alias /var/www/[myapp]/public$filename;
  #   image_filter resize $img_w $img_h;
  #   image_filter_jpeg_quality 95;
  #   image_filter_buffer         20M;
  #   image_filter_interlace      on;
  # }

  # location /_crop {
  #   alias /var/www/[myapp]/public$filename;
  #   image_filter crop $img_w $img_h;
  #   image_filter_jpeg_quality 95;
  #   image_filter_buffer         20M;
  #   image_filter_interlace      on;
  # }

  # DO NOT CHANGE THIS
  location / {
    proxy_redirect     off;
    proxy_set_header   Host $host;
    proxy_set_header   X-Forwarded-Host $host;
    proxy_set_header   X-Forwarded-Server $host;
    proxy_set_header   X-Real-IP        $remote_addr;
    proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
    proxy_buffering    on;
    proxy_http_version 1.1;
    proxy_set_header   Upgrade $http_upgrade;
    proxy_set_header   Connection "Upgrade";
    proxy_set_header   X-Forwarded-Proto $scheme;
    proxy_pass         http://app_backend;
    gzip on;
  }
}

楼主我遇到过类似的情况,但是因为你的环境我不是很了解。是不是 Rails5?如果是 Rails5 的话,请定位到:

config/initializers/new_framework_defaults.rb

Rails.application.config.action_controller.forgery_protection_origin_check = true

改为

Rails.application.config.action_controller.forgery_protection_origin_check = false

看问题是否得到解决。

#1 楼 @sefier #1 楼 @sefier 直接取消 forgery_protection_origin_check 有点太粗暴了。

修改了 nginx.conf

user root;
worker_processes 4;
pid /var/www/pids/nginx.pid;
daemon off;

events {
    worker_connections 768;
    # multi_accept on;
}

http {

    ##
    # Basic Settings
    ##

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    # server_tokens off;

    # server_names_hash_bucket_size 64;
    # server_name_in_redirect off;

    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    ##
    # Logging Settings
    ##

    access_log /var/www/log/nginx-access.log;
  error_log /var/www/log/nginx-error.log;

    ##
    # Gzip Settings
    ##

    gzip on;
    gzip_disable "msie6";

    # gzip_vary on;
    # gzip_proxied any;
    # gzip_comp_level 6;
    # gzip_buffers 16 8k;
    # gzip_http_version 1.1;
    # gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    ##
    # nginx-naxsi config
    ##
    # Uncomment it if you installed nginx-naxsi
    ##

    #include /etc/nginx/naxsi_core.rules;

    ##
    # nginx-passenger config
    ##
    # Uncomment it if you installed nginx-passenger
    ##

    #passenger_root /usr;
    #passenger_ruby /usr/bin/ruby;

    ##
    # Virtual Host Configs
    ##

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}


#mail {
#   # See sample authentication script at:
#   # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
#   # auth_http localhost/auth.php;
#   # pop3_capabilities "TOP" "USER";
#   # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
#   server {
#       listen     localhost:110;
#       protocol   pop3;
#       proxy      on;
#   }
#
#   server {
#       listen     localhost:143;
#       protocol   imap;
#       proxy      on;
#   }
#}
upstream [app]_backend {
  server app:7000 fail_timeout=0;
  keepalive 3;
}

server {
  listen 80;
  listen 443 ssl http2;
  server_name [xxx];

  # ~2 seconds is often enough for most folks to parse HTML/CSS and
  # retrieve needed images/icons/frames, connections are cheap in
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;

  # path for static files
  root /var/www/[app]/public;
  access_log /var/www/log/[app]-access.log;
  error_log  /var/www/log/[app]-error.log;

  # this rewrites all the requests to the maintenance.html
  # page if it exists in the doc root. This is for capistrano's
  # disable web task
  if (-f $document_root/maintenance.html) {
    rewrite  ^(.*)$  /maintenance.html last;
    break;
  }

  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;

    # If the file exists as a static file serve it directly without
    # running all the other rewrite tests on it
    if (-f $request_filename) {
      break;
    }

    # check for index.html for directory index
    # if it's there on the filesystem then rewrite
    # the url to add /index.html to the end of it
    # and then break to send it to the next config rules.
    if (-f $request_filename/index.html) {
      rewrite (.*) $1/index.html break;
    }

    # this is the meat of the rack page caching config
    # it adds .html to the end of the url and then checks
    # the filesystem for that file. If it exists, then we
    # rewrite the url to have explicit .html on the end
    # and then send it on its way to the next config rule.
    # if there is no file on the fs then it sets all the
    # necessary headers and proxies to our upstream pumas
    if (-f $request_filename.html) {
      rewrite (.*) $1.html break;
    }

    if (!-f $request_filename) {
      proxy_pass http://[app]_backend;
      break;
    }
  }

  # Now this supposedly should work as it gets the filenames with querystrings that Rails provides.
  # BUT there's a chance it could break the ajax calls.
  location ~* \.(ico|css|gif|jpe?g|png|js)(\?[0-9]+)?$ {
     expires max;
     break;
  }

  # Error pages
  # error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/www/[app]/public;
  }
}

#2 楼 @imwildcat 没有让你将这个作为最终解决方案;测试过这个之后看看,就可以明确是不是这个原因导致的,如果是,你再考虑解决方案。

是不是在 application_controller.rb 文件里没有注释掉这行

#protect_from_forgery with: :exception
You need to Sign in before reply, if you don't have an account, please Sign up first.