Ruby on rails 是否在注册页面前添加条件?
我想问用户一个问题,只有当用户正确回答我的问题时,才允许他注册。我找过了,但我的箱子好像不在那里 有没有一种惯用的方法来处理这种情况 第一个想法可能是使用javascript,但答案存储在LDAP中,我希望在rails中处理这个问题会更容易 我还考虑禁用Ruby on rails 是否在注册页面前添加条件?,ruby-on-rails,devise,Ruby On Rails,Devise,我想问用户一个问题,只有当用户正确回答我的问题时,才允许他注册。我找过了,但我的箱子好像不在那里 有没有一种惯用的方法来处理这种情况 第一个想法可能是使用javascript,但答案存储在LDAP中,我希望在rails中处理这个问题会更容易 我还考虑禁用/users/sign\u路由,手动调用操作(design/registration\new)并呈现视图(design/registration/new) 我可以想到的另一种方法是运行后台守护程序,它将收集会话id,用户在其中正确回答了问题。回答
/users/sign\u
路由,手动调用操作(design/registration\new
)并呈现视图(design/registration/new
)
我可以想到的另一种方法是运行后台守护程序,它将收集会话id,用户在其中正确回答了问题。回答正确后,用户将被重定向到公开可用的注册页面,该页面将通过守护进程获取检查用户会话id。假设您已签署cookie数据(如Rails 3中的默认值),您可以按照您所说的做并使用会话:
# app/controllers/preauth_controller.rb
def new
end
def create
if params[:answer] == 'correct answer'
session[:preauthorized] = true
redirect_to sign_up_path
end
flash[:error] = 'Incorrect answer'
render :new
end
# app/controllers/users_controller.rb
before_filter :verify_preauth, only: [:new, :create]
def verify_preauth
redirect_to new_preauth_path unless session[:preauthorized]
end
但是,如果cookie数据没有签名,则预授权的
密钥可能会被客户端篡改,因此不应被信任
如果您的页面在传输过程中通过TLS使用HTTPS进行加密,并且您没有任何XSS漏洞,那么这应该足以满足您的需要。如果您觉得这是一段特别敏感的代码,那么您需要的不仅仅是StackOverflow用户传递的想法,而是指导和实现一种全面的方法来保护您的应用程序 我有一点不同的方法
#app/controllers/registration_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_filter :check_answered_or_not,only:[:create,:new]
def check_answered_or_not
if not session[:answered]==true
redirect_to question_path
end
end
private
def sign_up_params
params.require(:user).permit(:name,:phone,:password,:password_confirmation,:email)
end
def account_update_params
params.require(:user).permit(:name,:phone,:password,:password_confirmation,:email,:current_password)
end
end
#app/controllers/registration_controller.rb
类注册控制器<设计::注册控制器
筛选前:选中或不选中:[:创建,:新建]
def检查是否回答
如果不是会话[:应答]==真
重定向到问题路径
结束
结束
私有的
def注册参数
参数要求(:用户)。允许(:姓名,:电话,:密码,:密码确认,:电子邮件)
结束
def帐户更新参数
参数要求(:用户).允许(:姓名,:电话,:密码,:密码确认,:电子邮件,:当前密码)
结束
结束
我的两个孩子所以。。。可能它应该在
模块中可验证
这不是符合要求的解决方案,但我希望它能帮助您……我认为最简单的方法是将默认的Desive controller更改为自定义的Desive controller,其中包含
,然后再执行操作
:
# routes.rb
devise_for :users, :controllers => {:registrations => "registrations"}
通过以下控制器实现:
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_action :check_answers, only: :new # :new action is responsible for :sign_up route
private
def check_answers
unless session[:gave_answers]
redirect_to ask_questions_path
false
end
end
end
一旦此控制器继承自designe::RegistrationsController
所有行为都保持默认状态,但检查答案功能除外
关于您关于惯用方式的问题,请参阅。你的应用程序-你的逻辑,没问题
更新:
在评论中@bbozo用这个和其他答案指出了某些安全问题。为了使其更安全,您可以添加并设置一些随机的秘密令牌(更多信息请参见评论)。为了提高先前建议的安全性,最好的建议似乎是coreyward提供的,但它是不安全的(无论cookie是否加密-请参阅我在OP上的评论) 可选择做/玩的事情
Rails.cache
条目:expires\u在设置中如果你愿意,你通常希望它尽可能短,尽可能长:)但是rails默认的15分钟是相当不错的
server\u session
对象,该对象基本上与session
相同,但将数据存储在Rails.cache
中,并在session
中存储一个随机过期令牌,用于访问缓存项就像我们在这里做的一样Rails.cache
往返(redis、memcache、AR等)而需要更长的响应时间OK
如果您需要假设cookie数据是加密的,那么您就错了。Cookie数据在Rails中多年没有被加密,不是因为它在技术上很困难,而是因为担心程序员可能会使用它来保护客户端上的数据,这是一个坏消息practice@bbozo“恐惧”关于加密cookie数据,新手开发人员不会理解加密cookie仍然存在的安全问题,即劫持/固定和重放。我已经更新了我的答案,以反映加密实际上是不必要的,而且,代码将与Rails 3的签名cookies一样安全。还有一个事实,如果你不在cookie中添加额外的数据,它将允许任何人访问系统注册:不应该信任Pokiokcookcookie来保留客户端或中间人不愿意解密/伪造的数据。还考虑拥有一个被窃取的cookie,使用<代码>回答= true将导致立即和可重复的注册任何拥有Cookie的人的能力,您不能相信<代码>会话<代码>,以保持允许访问某人的会计会话的数据总是用来保持当前用户ID和数据关联。当前会话,这就是为什么窃取用户的cookies会让攻击者根据受害者的姓名进行操作。引用Rails指南:“因此,cookie充当临时身份验证
# app/controllers/registrations_controller.rb
class RegistrationsController < Devise::RegistrationsController
before_action :check_answers, only: :new # :new action is responsible for :sign_up route
private
def check_answers
unless session[:gave_answers]
redirect_to ask_questions_path
false
end
end
end
# somewhere in questions controller:
if answers_correct?
session[:gave_answers] = true
redirect_to new_registration_path
end
# app/controllers/preauth_controller.rb
def new
end
def create
if params[:answer] == 'correct answer'
# Create a secret value, the `token`, we will share it to the client
# through the `session` and store it on the server in `Rails.cache`
# (or you can use the database if you like)
#
# The fact that this token expires (by default) in 15 minutes is
# a bonus, it will secure the system against later use of a stolen
# cookie. The token is also secure against brute force attack
@token = SecureRandom.base64
session[:preauthorization_token] = @token
Rails.cache.write("users/preauthorization_tokens/#{@token}", "OK")
redirect_to sign_up_path
else
flash[:error] = 'Incorrect answer'
render :new
end
end
# app/controllers/users_controller.rb
before_filter :verify_preauth, only: [:new, :create]
def verify_preauth
# When we approve preauthorization we confirm that the
# `token` is known to the client, if the client knows the token
# let him sign up, else make him go away
token = session[:preauthorization_token]
redirect_to new_preauth_path unless token and Rails.cache.read("users/preauthorization_tokens/#{token}") == "OK"
end