在我的Rails应用中,我users
可以拥有多个projects
,而tasks
可以有多个class Task < ActiveRecord::Base
attr_accessible :project_id
end
。
模型:
class TasksController < ApplicationController
def create
@task = current_user.tasks.build(params[:task])
if @task.save
flash[:success] = "Task saved."
redirect_to edit_task_path(@task)
else
render :new
end
end
def update
if @task.update_attributes(params[:task])
flash[:success] = "Task updated."
redirect_to edit_task_path(@task)
else
render :edit
end
end
end
控制器:
project_ids
Rails的标准做法是确保用户 A 无法为用户 B 创建任务?
现在,我正在通过表单中的选择框选项限制用户可用的{{1}}。但是,这很容易通过浏览器控制台入侵,根本不安全。
如何改进?
感谢您的帮助。
答案 0 :(得分:1)
我会使用before过滤器检查所需项目是否属于当前用户:
class TasksController < ApplicationController
before_filter :find_project, only: :create
def create
@task = @project.tasks.build(params[:task])
if @task.save
flash[:success] = "Task saved."
redirect_to edit_task_path(@task)
else
render :new
end
end
private
def find_project
@project = current_user.projects.where( id: params[ :task ][ :project_id ] ).first
redirect_to( root_path, notice: 'No such project' ) unless @project
end
end
因此,如果给定的project_id与属于当前用户的项目不匹配,则会重定向。
更多的rails方式是使用嵌套资源:
resources :projects
resources :tasks, shallow: true
end
你会有这样的路线:
GET /projects/1/tasks (index)
GET /projects/1/tasks/new (new)
POST /projects/1/tasks (create)
GET /tasks/1 (show)
GET /tasks/1/edit (edit)
PUT /tasks/1 (update)
DELETE /tasks/1 (destroy)
但这不会有太大差异,你仍然需要检索Post:
class TasksController < ApplicationController
before_filter :find_project, only: [ :index, :new, :create ]
before_filter :find_task, only: [ :show, :edit, :update, :delete ]
# other actions
def create
@task = @project.tasks.build(params[:task])
if @task.save
flash[:success] = "Task saved."
redirect_to edit_task_path(@task)
else
render :new
end
end
private
def find_project
@project = current_user.projects.where( id: params[ :project_id ] ).first
redirect_to( root_path, notice: 'No such project' ) unless @project
end
def find_task
@task = current_user.tasks.where( id: params[ :id ] ).first
redirect_to( root_path, notice: 'No such task' ) unless @task
end
end
答案 1 :(得分:1)
最简单的方法是查找范围并利用#find
可以引发RecordNotFound
的事实。 Rails将拯救该异常并为您呈现404.
class TasksController < ApplicationController
helper_method :project
def create
@task = project.tasks.build(params[:task])
if @task.save
flash[:success] = "Task saved."
redirect_to edit_task_path(@task)
else
render :new
end
end
private
def project
@project ||= current_user.projects.find(params[:task][:project_id])
end
end
我还要补充一点,您还应该为其所属项目下的任务范围设置范围。使用嵌套资源的/projects/:project_id/tasks/:id
之类的东西。