如何防止其他用户删除ActiveStorage中关联自身产品的图片?
解决ActiveStorage图片的用户权限验证问题
要防止其他用户通过路由删除不属于自己的图片,核心是通过ActiveStorage附件关联到所属产品,再验证产品所有者与当前登录用户是否一致,具体实现步骤如下:
1. 基础验证:确保用户已登录
首先在ImagesController中添加登录验证(以Devise为例),拦截未登录用户的请求:
class ImagesController < ApplicationController before_action :authenticate_user! # 仅允许登录用户访问 end
2. 关联图片到所属用户
ActiveStorage的Attachment模型会记录record_type和record_id,对应图片所属的父模型(这里是Product)。我们可以通过这个关联反向找到Product,再通过Product的user_id验证权限:
完整的delete动作实现
class ImagesController < ApplicationController before_action :authenticate_user! before_action :set_attachment_and_product, only: [:delete] before_action :authorize_image_owner!, only: [:delete] def delete @attachment.purge_later # 异步删除图片,避免阻塞请求 flash[:notice] = "图片已删除" redirect_to product_path(@product) end private # 获取图片附件及所属产品 def set_attachment_and_product @attachment = ActiveStorage::Attachment.find(params[:id]) @product = @attachment.record # 直接通过attachment关联到Product end # 验证当前用户是否为图片所有者 def authorize_image_owner! unless @product.user_id == current_user.id flash[:alert] = "你无权删除这张图片" redirect_to products_path return false end end end
3. 特殊情况处理:如果路由ID是Blob的ID
如果你的路由:id对应的是ActiveStorage::Blob的ID(而非Attachment),需要先找到关联的Product Attachment再验证:
private def set_attachment_and_product blob = ActiveStorage::Blob.find(params[:id]) # 找到关联到Product的Attachment(确保只处理产品图片) @attachment = blob.attachments.find_by(record_type: "Product") @product = @attachment&.record # 如果找不到关联的产品,直接拦截 unless @product flash[:alert] = "图片不存在或不属于任何产品" redirect_to products_path return false end end
关键说明
- 不要直接通过
Blob验证权限:一个Blob可能被多个模型/记录引用,通过Attachment关联到具体的Product才能准确找到所属用户。 - 用
purge_later替代purge:异步删除图片可以提升请求响应速度,避免因文件IO阻塞请求。
内容的提问来源于stack exchange,提问作者Yurii
相关产品推荐
相关产品推荐

