ruby-on-rails - 如何防止在 Rails 中篡改 URL
问题描述
我的 Rails 学生规划器应用程序存在一些关于 URL 篡改的问题。我相信他们可能都有类似的解决方案,但我遇到了困难。
查看students/:id/assignments/:id
作业assignments#show
( '想只是重定向回他们的主页。
同样,作业的编辑页面 ( students/:id/assignments/:id/edit
)、课程 ( students/:id/courses/:id
) 和课程的编辑页面 ( students/:id/courses/:id/edit
) 也会发生这种情况。有时我会Assignments#edit
在查看作业的编辑页面时收到“ArgumentError in”。
我相信这些应该能够在我的控制器中得到纠正,所以我已经包含了我的assignments_controller
and courses_controller
.
分配_控制器:
class AssignmentsController < ApplicationController
before_action :require_logged_in
before_action :set_student
def new
if @student && @student.id == current_student.id
@assignment = Assignment.new
@courses = Course.where(student_id: current_student.id)
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users assignments.'
end
end
def create
@assignment = Assignment.new(assignment_params)
@assignment.student_id = current_student.id if current_student
@courses = Course.where(student_id: current_student.id)
if @assignment.save
redirect_to student_assignments_path(@student)
else
render :new
end
end
def index
if @student && @student.id == current_student.id
@assignments = Assignment.where(student_id: current_student.id)
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users assignments.'
end
end
def show
#student = Student.find_by(id: params[:student_id])
if @student && @student.id == current_student.id
#@assignment = student.assignments.find_by(id: params[:id])
@assignment = Assignment.find_by(id: params[:id])
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users assignments.'
end
end
def edit
if @student && @student.id == current_student.id
@assignment = Assignment.find_by(id: params[:id])
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users assignments.'
end
end
def update
student = Student.find_by(id: params[:student_id])
@assignment = Assignment.find_by(id: params[:id])
@assignment.update(params.require(:assignment).permit(:title, :due_date))
redirect_to student_assignment_path(student, @assignment)
end
def destroy
@student = Student.find_by(id: params[:student_id])
@assignment = Assignment.find_by(id: params[:id]).destroy
redirect_to student_path(@student), notice: 'Assignment was successfully completed.'
end
private
def assignment_params
params.require(:assignment).permit(:title, :due_date, :course_id, :student_id)
end
def set_student
@student = Student.find_by(id: params[:student_id])
end
end
Courses_controller:
class CoursesController < ApplicationController
before_action :require_logged_in
before_action :set_student
def new
if @student && @student.id == current_student.id
@course = Course.new
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users courses.'
end
end
def create
if @student && @student.id == current_student.id
@course = Course.create(course_params)
@course.student_id = params[:student_id]
if @course.save
redirect_to student_courses_path(@student)
else
render :new
end
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users courses.'
end
end
def index
if @student && @student.id == current_student.id
@courses = Course.where(student_id: current_student.id)
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users courses.'
end
end
def show
@student = Student.find_by(id: params[:student_id])
if @student && @student.id == current_student.id
@course = @student.courses.find_by(id: params[:id])
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users courses.'
end
end
def edit
if @student && @student.id == current_student.id
@course = Course.find_by(id: params[:id])
else
redirect_to student_path(current_student), error: 'Sorry, you can\'t view another Users courses.'
end
end
def update
student = Student.find_by(id: params[:student_id])
@course = Course.find_by(id: params[:id])
@course.update(params.require(:course).permit(:course_name))
redirect_to student_course_path(student, @course)
end
def destroy
@student = Student.find_by(id: params[:student_id])
@course = Course.find_by(id: params[:id]).destroy
redirect_to student_path(@student), notice: 'Course was successfully deleted.'
end
private
def course_params
params.require(:course).permit(:course_name)
end
def set_student
@student = Student.find_by(id: params[:student_id])
end
end
解决方案
这条线是所有问题的根源:
@assignment = Assignment.find_by(id: params[:id])
这是一个巨大的错误。我认为您永远不会使用顶级模型来获取必须保护的记录。这段代码的失败状态是用户看到了一切。这是一个无法通过使用访问控制列表修补它来解决的问题。这些可能并非每次都正确应用,有人可能会发现漏洞。
相反,你这样做:
@assignment = @student.assignments.find_by(id: params[:id])
最坏的情况是您收到未找到的错误。任何人都无法通过破解 URL 来绕过这一点。这里的失败状态是没有找到记录。
如果您希望您的 URL 能够抵抗篡改,您还需要使用非顺序标识符。在 MySQL 上,通常最好专门为此目的创建一个辅助列,例如称为param
or slug
or ident
,无论您喜欢什么,并用随机且无害的东西填充它,例如:
before_validation :assign_slug
def assign_slug
self.slug ||= SecureRandom.uuid
end
在您的架构中索引的位置以便快速检索。你有学生关系的地方:
add_index :assignments, [ :student_id, :slug ]
Postgres 允许使用可能很冗长的 UUID 主键,但不允许人们修补和试验以公开信息。你真的不能“猜测”一个随机的 UUID 值。
推荐阅读
- git - 从 Git 源代码管理中删除多个文件实例
- flutter - Flutter:如何获取父小部件变量?
- django - 何时在 Django 中使用 annonate 和聚合?
- c++ -
西里尔字符有问题 - python - 终止任务管理器中的所有 excel.exe 进程 - Python
- python - python在yield之前引发异常
- ios - NavigationBar 右按钮未出现
- node.js - 在sails.js中通过积分和注册日期获取用户排名
- java - 在 Java 中正确显示文件中的文本
- javascript - 使用反应应用程序时出错 - 无法读取未定义的属性“照片”