为了redirect users to a custom web page each time params
contain a redirect_uri
value我正在评估使用custom redirect_to
method这种方式(@kiddorails):
class ApplicationController < ActionController::Base
def custom_redirect_to(url)
redirect_to (params[:redirect_uri].present? ? params[:redirect_uri] : url)
end
end
def create
@post = Post.new(params)
if @post.save
custom_redirect_to @post
else
render 'new'
end
end
但是,我想知道可能的缺点,并获得采用上述解决方案的支持。
答案 0 :(得分:1)
允许通过网址参数设置重定向目标而不进行任何验证对您的用户来说可能会有危险,因为它可以让捕鱼尝试更轻松。
攻击者可以向您的用户发送链接,例如
,许多用户只会看到域部分,并且无法在点击该链接后意识到他们最终的位置。
Open Web Application Security Project(OWASP)因此considers this a vulnerability:
Web应用程序可以实现未经验证的重定向和转发 接受可能导致Web应用程序的不受信任的输入 将请求重定向到不受信任的输入中包含的URL。通过 攻击者可能会将不受信任的URL输入修改为恶意站点 成功启动网络钓鱼诈骗并窃取用户凭据。 因为修改后的链接中的服务器名称与 原始网站,网络钓鱼尝试可能会更值得信赖 出现。也可以使用未经验证的重定向和转发攻击 恶意制作一个可以通过应用程序访问的URL 控制检查然后将攻击者转发给特权函数 他们通常无法访问。
在执行重定向之前仔细检查redirect_uri参数非常重要。
但是,由于正确的验证很棘手并且容易出错,因此更好的想法是不首先接受URI参数,而是允许某些关键字指定用户将被重定向的位置。
class ApplicationController < ActionController::Base
protected
def dynamic_redirect_to(default_route, options)
options.stringify_keys!
redirect_to options.fetch(params[:redirect_to], default_route)
end
end
您现在可以提前定义任意数量的允许关键字,这些关键字可以用作?redirect_to=
参数:
def create
@post = Post.new(params)
if @post.save
dynamic_redirect_to post_path(@post), edit: edit_post_path(@post)
else
render 'new'
end
end
如果设置了?redirect_to=edit
,则会将用户重定向回编辑页面。如果未设置参数或包含未指定的关键字,则会将其重定向为默认post_path(@post)
。
答案 1 :(得分:1)
我同意janfoeh上面所说的话。 但为了实现您的要求,我在Rails code of redirection中进行了攻击,以使其更简单。
使用以下命令创建文件 config / initializers / redirecting.rb :
require 'abstract_controller/base'
module ActionController
module Redirecting
extend ActiveSupport::Concern
include AbstractController::Logger
include ActionController::RackDelegation
include ActionController::UrlFor
def _compute_redirect_to_location(options)
if redirect_url = session.delete(:redirect_uri)
options = redirect_url
end
case options
# The scheme name consist of a letter followed by any combination of
# letters, digits, and the plus ("+"), period ("."), or hyphen ("-")
# characters; and is terminated by a colon (":").
# See http://tools.ietf.org/html/rfc3986#section-3.1
# The protocol relative scheme starts with a double slash "//".
when /\A([a-z][a-z\d\-+\.]*:|\/\/).*/i
options
when String
request.protocol + request.host_with_port + options
when :back
request.headers["Referer"] or raise RedirectBackError
when Proc
_compute_redirect_to_location request, options.call
else
url_for(options)
end.delete("\0\r\n")
end
end
end
在 app / controllers / application_controller.rb :
中class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
before_action :set_redirect_uri
protect_from_forgery with: :exception
def set_redirect_uri
session[:redirect_uri] = params[:redirect_uri] if params[:redirect_uri].present?
end
end
而且瞧!现在,您可以继续使用原始redirect_to
,并且只要在网址中提供redirect_uri
,它就会在会话中设置该网址并自动覆盖。 :)
注意:仅在调用session[:redirect_uri]
时才会清除redirect_to
。您可以根据需要轻松修改该行为以重置此会话。