【问题标题】:How to properely post html form to controller in Ruby on rails 5.2.3如何在 Ruby on rails 5.2.3 中将 html 表单正确发布到控制器
【发布时间】:2022-03-25 08:46:04
【问题描述】:

我是 ruby​​ on rails 的新手。这里我试图将 html 表单发布到 ruby​​ on rails (5.2.3 版本) 为此,我参考了此处找到的解决方案link

<form accept-charset="UTF-8" method='post' action='http://localhost:3000/user1s'>

      
        <label for='name'>Name</label>
            <input type="text" name='name' placeholder='Enter your name'> <br>
        <label for='password'>password</label>
            <input type="text" name='password' placeholder='Enter your password'> <br>
        <label for='email'>confirm pass</label>
            <input type="text" name='password_confirmation' placeholder='Enter your password_confirmation'> <br>
     
            <input type="submit" value='Save'>
    </form>

user1 控制器

class User1sController < ApplicationController
    

  # POST /user1s
  # POST /user1s.json
  def create
    @name = params[:name]
    @password = params[:password]
    @password_confirmation = params[:password_confirmation]
    @user1 = User1.new(name=>@name, password=>@password , password_confirmation=>@password_confirmation)

    respond_to do |format|
      if @user1.save
        format.html { redirect_to @user1, notice: 'User1 was successfully created.' }
        format.json { render :show, status: :created, location: @user1 }
        #format.json {status: :created }
      else
        format.html { render :new }
        format.json { render json: @user1.errors, status: :unprocessable_entity }
      end
    end
  end

  
end

这里是 config/routes.rb

Rails.application.routes.draw do
  #resources :user1s
  post '/user1s', to: 'user1s#create', as: 'user1s'  
end

当我运行代码时出现以下错误

浏览器为打开了基于来源的伪造保护的请求返回了“空”来源。 这通常意味着您启用了 'no-referrer' Referrer-Policy 标头,或者 该请求来自一个拒绝提供其来源的网站。 这使得 Rails 无法验证请求的来源。 可能最好的解决方案是将您的推荐人政策更改为不那么严格的政策,例如 同源或严格同源。如果您无法更改引荐来源网址策略,则可以禁用来源检查 使用 Rails.application.config.action_controller.forgery_protection_origin_check 设置。

为了减轻上述错误,我在此处引用了链接,该链接建议了以下解决方案,但无法使其正常工作。 link 2

在 config/application.rb 我有

Bundler.require(*Rails.groups)

module Saverecord
  class Application < Rails::Application
    Rails.application.config.action_controller.forgery_protection_origin_check = false
    config.action_controller.allow_forgery_protection = false

    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

  end
end

在我的应用控制器上

class ApplicationController < ActionController::Base   
  # Prevent CSRF attacks by raising an exception.   
  # For APIs, you may want to use :null_session instead.   
  #protect_from_forgery with: :exception   
  protect_from_forgery with: :null_session

  
end  

【问题讨论】:

  • 如果此应用仅用于测试目的,您可以通过将protect_from_forgery with: :null_session 更改为skip_before_action :verify_authenticity_token 来禁用protect_from_forgery
  • 但您也可以通过添加 &lt;%= csrf_meta_tags %&gt; 将 csrf 令牌添加到您的表单中
  • 谢谢尤里。错误现在消失了。现在,当我尝试提交表单时。它说参数丢失或值为空。我也尝试实现下面的代码,但没有运气 @user1 = User1.new(user1_params) def user1_params params.require(:user1).permit(:name, :password, :password_confirmation) end
  • 如果它是你的表单,贴在这里,你应该修复,看看devise gem 中的示例,强烈建议在 Rails 中设置的用户github.com/RailsApps/rails-devise/blob/master/app/views/devise/…
  • 非常感谢 Yurij

标签: ruby-on-rails


【解决方案1】:

如果您只遵循 Rails 约定,这会容易得多。

首先使用strong parameters,而不是从参数哈希中复制两次变量。

class User1sController < ApplicationController
  # POST /user1s
  # POST /user1s.json
  def create
    # Use strong parameters instead  
    @user1 = User1.new(user1_parameters)

    respond_to do |format|
      if @user1.save
        format.html { redirect_to @user1, notice: 'User1 was successfully created.' }
        format.json { render :show, status: :created, location: @user1 }
        #format.json {status: :created }
      else
        format.html { render :new }
        format.json { render json: @user1.errors, status: :unprocessable_entity }
      end
    end
  end

  # ...
  private 
  def user1_parameters
    params.require(:user1).permit(:name, :email, :password, :password_confirmation)
  end
end

Ruby(和 Rails)在处理哈希方面具有出色的功能。如果您曾经手动将密钥从一个哈希复制到另一个哈希,那您就做错了。

然后使用form helper而不是手动创建表单:

<%= form_with(model: @user1) do |form| %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>
  <div class="field">
    <%= form.label :email %>
    <%= form.email_field :email %>
  </div>
  <div class="field">
    <%= form.label :password %>
    <%= form.password_field :password %>
  </div>
  <div class="field">
    <%= form.label :password_confirmation %>
    <%= form.password_field :password_confirmation %>
  </div>
  <div class="actions">
    <% form.submit %>
  </div>
<% end %>

Rails 内置了Cross Site Reference Forgery (CSRF) countermeasures,这意味着 Rails 将拒绝不包含有效 CSRF 令牌的表单提交。当您使用form_with(或旧的form_tagform_for)创建表单时,Rails 会在表单中包含一个 CSRF 令牌作为隐藏输入。

这意味着你手工制作的表单是行不通的,除非你禁用 CSRF 保护或提供比仅使用表单助手更复杂的令牌。

您的表单也没有为嵌套哈希使用正确的name 属性。按照惯例,Rails 使用嵌套哈希:

{
  users1: {
    name: 'foo',
    email: 'foo@example.com'
    ...
  }
}

表单助手通过在输入上设置正确的名称属性来做到这一点:

<input type="email" name='user1[email]' ...>

适用于params.require(:user1).permit(...)。您的表单将给出ActionController::ParameterMissing 错误。您可以解决此问题以使用平面散列,但您不妨学习 Rails 方式,它可以避免潜在的名称冲突。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-14
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    相关资源
    最近更新 更多