我在rails应用程序中使用sidekiq。 默认情况下,任何人都可以通过在网址后附加“/ sidekiq”来访问Sidekiq。 我想密码保护/验证sidekiq部分。我怎么能这样做?
答案 0 :(得分:92)
将以下内容放入sidekiq初始化程序
require 'sidekiq'
require 'sidekiq/web'
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
[user, password] == ["sidekiqadmin", "yourpassword"]
end
在路线档案中:
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end
答案 1 :(得分:14)
请参阅https://github.com/mperham/sidekiq/wiki/Monitoring
下的“安全性”Sidekiq :: Web使用Rack::Protection来保护您的应用免受典型的网络攻击(例如CSRF,XSS等)。如果发现您的请求不符合安全要求,Rack :: Protection会使您的会话无效并引发
这样的情况和解决方案Forbidden
错误。其中一种可能的情况是让您的应用程序在反向代理之后工作,而不是将重要的标头传递给它(X-Forwarded-For
,X-Forwarded-Proto
)。可以找到in this article和issue #2560 ...
答案 2 :(得分:11)
很抱歉迟到了,但Sidekiq's wiki推荐以下设计:
允许任何经过身份验证的User
:
# config/routes.rb
authenticate :user do
mount Sidekiq::Web => '/sidekiq'
end
限制对User.admin?
# config/routes.rb
authenticate :user, lambda { |u| u.admin? } do
mount Sidekiq::Web => '/sidekiq'
end
This wiki post还有许多其他安全方案。
使用Rails 5.1.3,Devise 4.3和Sidekiq 5.0
测试答案 3 :(得分:10)
如果您正在使用Devise(或其他基于Warden的身份验证),则可以执行此操作,假设您的应用中有AdminUser模型。
# config/routes.rb
# This defines the authentication constraint
constraint = lambda do |request|
request.env['warden'].authenticate!({ scope: :admin_user })
end
# This mounts the route using the constraint.
# You could use any other path to make it less obvious
constraints constraint do
mount Sidekiq::Web => '/sidekiq'
end
答案 4 :(得分:7)
如果您要滚动自己的自定义身份验证,则可以使用文档here中引用的以下示例。
# lib/admin_constraint.rb
class AdminConstraint
def matches?(request)
return false unless request.session[:user_id]
user = User.find request.session[:user_id]
user && user.admin?
end
end
# config/routes.rb
require 'sidekiq/web'
require 'admin_constraint'
mount Sidekiq::Web => '/sidekiq', :constraints => AdminConstraint.new
答案 5 :(得分:0)
另一种选择是添加CanCan和基于角色的特殊访问。
答案 6 :(得分:0)
如果您使用Sorcery进行身份验证,则可以使用how to use Rails routes constraints来保护某些路由。
在这里从巫术维基复制以获得冗余:
本教程介绍如何在Sorcery gem中使用Rails路由约束。感谢@anthonator写作!
首先,定义将用于所有约束的printf("%s", txt);
模块:
UserConstraint
然后,定义该模块,您可以指定特定的约束类。在这些示例中,第一条路线仅在没有用户登录时才起作用,第二条路线仅适用于作为管理员的登录用户:
module RouteConstraints::UserConstraint
def current_user(request)
User.find_by_id(request.session[:user_id])
end
end
最后,您可以将约束添加到class RouteConstraints::NoUserRequiredConstraint
include RouteConstraints::UserConstraint
def matches?(request)
!current_user(request).present?
end
end
class RouteConstraints::AdminRequiredConstraint
include RouteConstraints::UserConstraint
def matches?(request)
user = current_user(request)
user.present? && user.is_admin?
end
end
:
config/routes.rb
答案 7 :(得分:0)
可接受的答案很好,但是我认为它可以更安全地实现,例如Sidekiq documentation mentions。
要保护您的应用不受定时攻击,请使用ActiveSupport::SecurityUtils.secure_compare
。
此外,请使用&
(不要使用&&
),以免短路。
最后,使用摘要阻止长度信息泄漏(Active Support 5中的默认值为secure_compare
)。
活动支持5 :由于Rails PR #24510,默认情况下,传递给secure_compare
的参数将通过Digest::SHA256.hexdigest
。
require 'active_support/security_utils'
require 'sidekiq'
require 'sidekiq/web'
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
# Protect against timing attacks:
# - See https://codahale.com/a-lesson-in-timing-attacks/
# - See https://thisdata.com/blog/timing-attacks-against-string-comparison/
# - Use & (do not use &&) so that it doesn't short circuit.
# - Use digests to stop length information leaking
ActiveSupport::SecurityUtils.secure_compare(user, ENV["SIDEKIQ_ADMIN_USER"]) &
ActiveSupport::SecurityUtils.secure_compare(password, ENV["SIDEKIQ_ADMIN_PASSWORD"])
end
活动支持4 :
require 'active_support/security_utils'
require 'sidekiq'
require 'sidekiq/web'
Sidekiq::Web.use(Rack::Auth::Basic) do |user, password|
# Protect against timing attacks:
# - See https://codahale.com/a-lesson-in-timing-attacks/
# - See https://thisdata.com/blog/timing-attacks-against-string-comparison/
# - Use & (do not use &&) so that it doesn't short circuit.
# - Use digests to stop length information leaking
ActiveSupport::SecurityUtils.secure_compare(
::Digest::SHA256.hexdigest(user),
::Digest::SHA256.hexdigest(ENV["SIDEKIQ_ADMIN_USER"])
) &
ActiveSupport::SecurityUtils.secure_compare(
::Digest::SHA256.hexdigest(password),
::Digest::SHA256.hexdigest(ENV["SIDEKIQ_ADMIN_PASSWORD"])
)
end