Ado*_*obe 14 ruby-on-rails devise
我想问用户一个问题,并且只有在用户正确回答我的问题时才让他注册.我搜索了如何设法,但我的情况似乎并不存在.
有没有一种惯用的方法来处理这种情况?
第一个想法可能是使用javascript,但答案存储在LDAP中,我希望在rails中更容易处理.
我还在考虑禁用/users/sign_up
路由,devise/registration#new
手动调用action()并渲染视图(devise/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
Run Code Online (Sandbox Code Playgroud)
但是,如果cookie数据未签名,则preauthorized
密钥可能被客户端篡改,因此不应被信任.
如果您的页面在传输过程中使用HTTPS通过TLS加密,并且您没有任何XSS漏洞,那么这应该足够安全以满足您的需求.如果您认为这是一段特别敏感的代码,那么您需要的不仅仅是StackOverflow用户的想法,而是指导和实施保护应用程序安全的综合方法.
为了提高以前建议的安全性,最好的建议似乎是 coreyward 提出的,但它不安全(无论 cookie 是否加密 - 请参阅我对 OP 的评论)
# 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
Run Code Online (Sandbox Code Playgroud)
可选的事情做/玩......
Rails.cache
创建用户时删除成功使用的条目:expires_in
设置,通常你希望它尽可能短,并且根据需要长:),但 Rails 默认的 15 分钟非常好server_session
对象,其功能与 Cookie 基本相同,但使用随机的可过期令牌session
存储数据,该令牌存储在用于以大致相同的方式访问缓存条目我们在这里做Rails.cache
session
Rails.cache
(redis、memcache、AR...)而导致响应时间更长OK
您需要更多安全存储在主机上的数据来解决此问题,您可以存储值的哈希值,而不是存储到缓存值中