Rails 6.1.3.2 不允许的参数和用户必须存在

Rails 6.1.3.2 Unpermitted parameter and User must exist

几年前我在 Rails 4 中开发 aps,现在很多事情都变了。

我在本例中使用 Shire GEM 上传照片:

好的,我的模特:

照片模特:

class Photo < ApplicationRecord

    include ImageUploader::Attachment(:image)

    belongs_to :user

end

用户模型(我只放了几行):

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :validatable
    

  has_one :profile, :dependent => :destroy
  has_many :photos, :dependent => :destroy

end

照片控制器:

class PhotosController < ApplicationController

    before_action :set_photo, only: %i[ show edit update destroy ]
    before_action :authenticate_user!

 def create
    @photo = Photo.new(photo_params)

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

private
    # Use callbacks to share common setup or constraints between actions.
    def set_photo
       @photo = Photo.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def photo_params
      params.require(:photo).permit(:title, :image_data, :image, :user_id)
    end


 end

    

用户控制器:

class UsersController < ApplicationController


  private

  # Only allow a list of trusted parameters through.

     def set_user
       @user = User.find(params[:id])
     end

     def user_params
       params.require(:user).permit(:id)
     end

 end

现在最后一件事,用于在视图中添加照片的表单:

 <%= form_with(model: photo) do |form| %>
   <% if photo.errors.any? %>
     <div id="error_explanation">
      <h2><%= pluralize(photo.errors.count, "error") %> prohibited this photo from being saved:</h2>

      <ul>
         <% photo.errors.each do |error| %>
           <li><%= error.full_message %></li>
         <% end %>
      </ul>
     </div>
   <% end %>

   <div class="field">
     <%= form.label :title %>
     <%= form.text_field :title %>
   </div>

   <div class="field">
     <%= form.label :image %>
     <%= form.file_field :image %>
   </div>
   <%= current_user.id %> // SHOWS USER ID

   //// THIS GENERATE ERROR ////
   <%#= form.hidden_field :user_id => current_user.id %>

   <div class="actions">
     <%= form.submit %>
   </div>
 <% end %>

我哪里有问题。当我以这种方式使用它时,我在日志中看到未经允许的参数:user_id.

但是当我提交表单时,我看到错误“用户必须存在”。

我在 PhotosController 这一行中找到了解决方案和更改:

def create
   @photo = Photo.new(photo_params)

至:

def create
   @photo = current_user.photos.new(photo_params)

它开始工作了。照片在 table 中有 user_id。但我想知道为什么我不能为视图中的照片添加 user_id,例如:

 <%= form.hidden_field :user_id => current_user.id %>

切勿通过参数将用户 ID 作为明文传递。而是从会话中获取它。对于任何恶意用户来说,使用网络检查器并简单地填写隐藏的输入,然后以任何用户身份上传一张不合时宜的图片都是微不足道的。

会话 cookie 已加密,更难篡改。

class PhotosController < ApplicationController
  before_action :authenticate_user!
  
  def create
    # build the record off the current_user
    @photo = current_user.photos.new(photo_params)
    respond_to do |format|
      if @photo.save
        format.html { redirect_to @photo, notice: "Photo was successfully created." }
        format.json { render :show, status: :created, location: @photo }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @photo.errors, status: :unprocessable_entity }
      end
    end
  end 
  
  private
  # Only allow a list of trusted parameters through.
  def photo_params
    params.require(:photo).permit(:title, :image_data, :image)
  end
end

But I want to know why I can't add user_id for photos in form in view like:

<%= form.hidden_field :user_id => current_user.id %>

因为您在调用方法时使用了错误的参数。 signature is hidden_field(object_name, method, options = {}) 但如前所述,这是个坏主意。