我正在考虑为 rails 编写一个自动垃圾邮件保护系统(也许我会写一个公共 gem)。
我的概念是在 application_controller fe 中包含一个辅助方法:
class ApplicationController < ActionController::Base
automatic_captcha_redirect(:min_time => 30.seconds :limit => 50)
...
end
然后我想在每个控制器中自动包含一个 before_filter,它检查当前请求是通过 post、put 还是 delete 方法。
如果用户的最后一个 post-request 小于 :min_time,那么该请求应该被重定向到一个 captcha-input-page(发布的用户数据驻留在隐藏的 html 字段中)。
# before_filter :check_spam
def check_spam
if !request.get? && session[:last_manipulation_at]
&& session[:last_manipulation_at] >= DateTime.now - 30.seconds
redirect_to captcha_path
# (doesn't know yet how to handle the post data to
# display in hidden fields in the spam-captcha-form)
end
end
在 captcha.haml
=form_tag
-request.params.each do |key, value|
=hidden_field_tag key, value
=captcha_image
=submit_button_tag
如果用户提交了正确的验证码,他的数据将被发布到正确的操作中。
你认为这可以实现吗?有什么批评或建议吗?或者一个想法如何实现这种行为?
编辑:
- 这不应该通过所有的 ActiveRecord 堆栈;不能作为中间件挂钩(Rails Rack)实现吗?
- 是的,这是个好主意——但我对 rails rack 不是很熟悉:/
- 文件上传呢?(您不能将其存储在隐藏文件中)
- 嗯...也许检查一下帖子中是否有文件?(这怎么可能实现?)
- Ajax 的发布呢?
- 也许发回 http-status 代码(fe 503 服务暂时不可用)
- 为什么只有 POST 而不是 PUT 和 DELETE?
- 在我的问题中纠正了这一点
编辑:
第一种处理结构(作为非机架应用程序 - 我不知道如何编写机架应用程序):
0) environment.rb 中的设置
auto_recaptcha[:limit] = 10
auto_recaptcha[:min_time] = 1.minute
1)用户发布数据
检查 last_manipulation 和最大值。application_controller.rb 中允许的操作量
class ApplicationController < ActionController::Base
before_filter :automatic_captcha_redirect
def automatic_captcha_redirect
session[:last_manipulation_at][:manipultation] = [] unless session[:last_manipulation_at][:manipultation]
# Checks if requests are falling under the specifications for showing captcha
if !request.get?
&& session[:last_manipulation_at][:date] > DateTime.now - auto_recaptcha[:min_time]
&& session[:last_manipulation_at][:manipultation].count < auto_recaptcha[:limit]
# If user answered captcha, verify it
if !verify_captcha(params)
@url = request.url
@params = request.params
render "layouts/captcha.haml"
else
# Add successfull manipulation to counter
session[:last_manipulation_at][:manipultation] << DateTime.now
session[:last_manipulation_at][:date] = DateTime.now
end
end
end
end
验证码
-form_tag @url do
-request.params.each do |key, value|
=hidden_field_tag key, value
=captcha_image
=submit_button_tag
2)………………
最后)将用户数据发布到正确的位置
post(params) => users_path # path "/users" with method: post