无需登录的Rails API鉴权实现:公开数据访问权限管控
嘿,这个需求其实挺常见的——既要给API加上必要的访问限制防止滥用,又得保持物品列表对所有用户(包括未登录的)开放查看。下面给你几个实用的方案,你可以根据实际场景组合使用:
这是最基础也最有效的保护方式,能避免爬虫或者恶意脚本频繁刷你的API。推荐用rack-attack这个Rails生态里的成熟工具:
先在Gemfile里添加依赖:
gem 'rack-attack'运行
bundle install安装。生成初始化配置文件:
rails generate rack:attack在
config/initializers/rack_attack.rb里配置限流规则,比如给匿名用户限制每分钟最多10次请求(数值可以根据你的业务调整):# 针对匿名用户的物品列表接口限流 Rack::Attack.throttle('anon/items', limit: 10, period: 1.minute) do |req| if req.path == '/items' && req.get? # 用IP地址标识匿名用户 req.ip end end # 如果有登录用户,可以给他们放宽限制 Rack::Attack.throttle('auth/items', limit: 100, period: 1.minute) do |req| if req.path == '/items' && req.get? && req.session[:user_id].present? req.session[:user_id] end end
这样既拦住了恶意请求,完全不影响正常用户查看列表。
既然你的前端和API是同域的(都是localhost:3000),可以开启Rails的CSRF保护,确保请求只能来自你的官方站点,防止跨站伪造请求:
在
app/controllers/application_controller.rb里确保CSRF保护生效:class ApplicationController < ActionController::API include ActionController::RequestForgeryProtection # 针对JSON请求也开启CSRF保护(需要前端配合传递token) protect_from_forgery with: :exception end前端这边要在axios请求里带上CSRF token:
先在页面布局里添加meta标签:<meta name="csrf-token" content="<%= form_authenticity_token %>">然后在axios的全局配置里设置:
import axios from 'axios'; const csrfToken = document.querySelector('meta[name="csrf-token"]').content; axios.defaults.headers.common['X-CSRF-Token'] = csrfToken;
这样只有来自你自己站点的请求才能成功调用API,避免其他网站伪造请求。
如果你的Items控制器还有创建、修改、删除这类敏感动作,可以用权限gem(比如Pundit)来做细粒度控制,只开放index动作给匿名用户:
安装Pundit:
gem 'pundit'运行
bundle install后生成配置:rails generate pundit:install创建Item的权限策略:
rails generate pundit:policy item在
app/policies/item_policy.rb里配置权限:class ItemPolicy < ApplicationPolicy # 允许所有用户(包括匿名)查看列表 def index? true end # 只有登录用户才能创建物品 def create? user.present? end # 其他动作(比如update/destroy)可以按需配置权限 end在Items控制器里应用权限控制:
class ItemsController < ApplicationController # 除了index,其他动作都需要登录 before_action :authenticate_user!, except: [:index] after_action :verify_authorized, except: [:index] def index @items = Item.all render json: @items end # 其他动作... end
这样既保护了修改类的敏感接口,又完全不影响匿名用户查看物品列表。
总结
你可以根据实际需求组合这些方案:
- 如果主要担心API被滥用,优先用方案1的限流;
- 同域场景下,加上方案2的CSRF保护会更安全;
- 有敏感操作的话,用方案3的权限控制区分不同动作的访问权限。
内容的提问来源于stack exchange,提问作者Evita

