没有路由匹配GET /sign_up,但我可以访问该页面?
No route matches GET /sign_up, but I can visit the page?
我的 Rails 4 应用程序的生产服务器上记录了一个奇怪的错误:
ActionController::RoutingError: No route matches [GET] "/sign_up"
这显然令人担忧,因为这意味着新用户无法注册。
但是,如果我访问那个 URL,无论是通过手动输入,还是通过单击我们主页上的按钮,我都可以看到注册页面。
没有重定向,URL 在 URL 栏中保持不变。
这是有问题的路线:
devise_scope :identity do
get 'sign_in', :to => 'devise/sessions#new'
get 'sign_up', :to => 'devise/registrations#new'
get 'sign_out', :to => 'devise/sessions#destroy'
end
由于主题破解,我们主页上的按钮是一个使用 GET 提交的表单。我认为这可能是个问题,但日志显示它正在正确接收 GET 请求。
这是怎么回事?我应该从哪里开始诊断?
更新
我们主页上的 hack,我的意思是,由于 bootstrap 不支持导航栏中的 <a class="btn...
,我们使用带有 GET 方法的表单来使用它的那种按钮确实支持 - 所以从服务器的角度来看,用户在单击该按钮时仍在发送 GET /sign_up 。这个按钮只是为了让他们进入 /sign_up 页面 (registration_controller#new),而不是他们用来提交包含所有详细信息的注册表单的按钮。
(注册表单本身是正常的,即发送 POST)
需要说明的是,我已经手动完成了整个注册过程,而且很有效。我从来没有收到 404。并且当我进行演练时,日志消息没有出现。
这是rake routes
的相关部分
Prefix Verb URI Pattern Controller#Action
new_identity_session GET /identities/sign_in(.:format) devise/sessions#new
identity_session POST /identities/sign_in(.:format) devise/sessions#create
destroy_identity_session DELETE /identities/sign_out(.:format) devise/sessions#destroy
cancel_identity_registration GET /identities/cancel(.:format) identities/registrations#cancel
identity_registration POST /identities(.:format) identities/registrations#create
new_identity_registration GET /identities/sign_up(.:format) identities/registrations#new
edit_identity_registration GET /identities/edit(.:format) identities/registrations#edit
PATCH /identities(.:format) identities/registrations#update
PUT /identities(.:format) identities/registrations#update
DELETE /identities(.:format) identities/registrations#destroy
sign_in GET /sign_in(.:format) devise/sessions#new
sign_up GET /sign_up(.:format) devise/registrations#new
sign_out GET /sign_out(.:format) devise/sessions#destroy
更新 2
我们的生产服务器上仍然记录了这个问题。
错误来自滚动条。
有趣的是,它没有出现在我们的生产日志中。
生产日志正在使用 one line logging。
我们无法在开发中重现它,这是访问页面的日志:
Started GET "/sign_up" for 127.0.0.1 at 2017-01-02 12:25:10 +0800
Processing by Devise::RegistrationsController#new as HTML
Rendered identities/shared/_sign_up.html.erb (203.5ms)
Rendered identities/registrations/new.html.erb within layouts/focused (277.2ms)
Rendered layouts/_social_headers.html.erb (39.1ms)
Rendered layouts/_google_analytics.html.erb (6.2ms)
Rendered layouts/_scripts.html.erb (3618.9ms)
Rendered layouts/_hotjar.html.erb (4.7ms)
Rendered layouts/_html_head.html.erb (3708.2ms)
Nation Load (4.5ms) SELECT "nations".* FROM "nations" WHERE "nations"."id" IS NULL ORDER BY "nations"."id" ASC LIMIT 1
Rendered layouts/_topnavbar.html.erb (101.0ms)
Rendered layouts/_breadcrumb.html.erb (7.4ms)
Rendered layouts/_flash.html.erb (31.4ms)
Rendered layouts/_footer2.html.erb (8.6ms)
Completed 200 OK in 4223ms (Views: 4203.2ms | ActiveRecord: 4.5ms)
原来这是由 Rollbar 造成的混乱。
Rollbar 按 class 聚合异常,默认情况下不是错误消息。因此,在发送错误报告时,报告会显示来自该异常的第一个实例的错误消息。
所以在我们的例子中,我们第一次使用 Rollbar 部署有一个错误导致 /sign_up 给我们一个 404 错误,这个错误已经修复,但在那之后,任何 404 都会产生相同的异常 class,所以当一个漏洞利用机器人请求时,比如 /wp-login.php 我们会收到一封来自 Rollbar 的电子邮件,上面写着:
ActionController::RoutingError: No route matches [GET] "/sign_up"
即使导致最近错误的实际路径不是 /sign_up
我们已通过更改分组下 Rollbar 的设置以打开 "Include Exception Message" 来解决此问题 - 这样新的 404 就不会与 /sign_up
分组在一起
我还将此添加到 config/initializers/rollbar.rb
以过滤掉其中一些 404,以免发送到 Rollbar。
# Ignore bots trying to hack non existent end-points
config.exception_level_filters.merge!('ActionController::RoutingError' => lambda { |e|
e.message =~ %r(No route matches \[[A-Z]+\] "/(.+)")
case .split("/").first.to_s.downcase
when *%w(myadmin phpmyadmin w00tw00t pma cgi-bin xmlrpc.php wp wordpress cfide)
'ignore'
else
'warning'
end
})
我的 Rails 4 应用程序的生产服务器上记录了一个奇怪的错误:
ActionController::RoutingError: No route matches [GET] "/sign_up"
这显然令人担忧,因为这意味着新用户无法注册。 但是,如果我访问那个 URL,无论是通过手动输入,还是通过单击我们主页上的按钮,我都可以看到注册页面。
没有重定向,URL 在 URL 栏中保持不变。
这是有问题的路线:
devise_scope :identity do
get 'sign_in', :to => 'devise/sessions#new'
get 'sign_up', :to => 'devise/registrations#new'
get 'sign_out', :to => 'devise/sessions#destroy'
end
由于主题破解,我们主页上的按钮是一个使用 GET 提交的表单。我认为这可能是个问题,但日志显示它正在正确接收 GET 请求。
这是怎么回事?我应该从哪里开始诊断?
更新
我们主页上的 hack,我的意思是,由于 bootstrap 不支持导航栏中的 <a class="btn...
,我们使用带有 GET 方法的表单来使用它的那种按钮确实支持 - 所以从服务器的角度来看,用户在单击该按钮时仍在发送 GET /sign_up 。这个按钮只是为了让他们进入 /sign_up 页面 (registration_controller#new),而不是他们用来提交包含所有详细信息的注册表单的按钮。
(注册表单本身是正常的,即发送 POST)
需要说明的是,我已经手动完成了整个注册过程,而且很有效。我从来没有收到 404。并且当我进行演练时,日志消息没有出现。
这是rake routes
Prefix Verb URI Pattern Controller#Action
new_identity_session GET /identities/sign_in(.:format) devise/sessions#new
identity_session POST /identities/sign_in(.:format) devise/sessions#create
destroy_identity_session DELETE /identities/sign_out(.:format) devise/sessions#destroy
cancel_identity_registration GET /identities/cancel(.:format) identities/registrations#cancel
identity_registration POST /identities(.:format) identities/registrations#create
new_identity_registration GET /identities/sign_up(.:format) identities/registrations#new
edit_identity_registration GET /identities/edit(.:format) identities/registrations#edit
PATCH /identities(.:format) identities/registrations#update
PUT /identities(.:format) identities/registrations#update
DELETE /identities(.:format) identities/registrations#destroy
sign_in GET /sign_in(.:format) devise/sessions#new
sign_up GET /sign_up(.:format) devise/registrations#new
sign_out GET /sign_out(.:format) devise/sessions#destroy
更新 2
我们的生产服务器上仍然记录了这个问题。 错误来自滚动条。 有趣的是,它没有出现在我们的生产日志中。 生产日志正在使用 one line logging。 我们无法在开发中重现它,这是访问页面的日志:
Started GET "/sign_up" for 127.0.0.1 at 2017-01-02 12:25:10 +0800
Processing by Devise::RegistrationsController#new as HTML
Rendered identities/shared/_sign_up.html.erb (203.5ms)
Rendered identities/registrations/new.html.erb within layouts/focused (277.2ms)
Rendered layouts/_social_headers.html.erb (39.1ms)
Rendered layouts/_google_analytics.html.erb (6.2ms)
Rendered layouts/_scripts.html.erb (3618.9ms)
Rendered layouts/_hotjar.html.erb (4.7ms)
Rendered layouts/_html_head.html.erb (3708.2ms)
Nation Load (4.5ms) SELECT "nations".* FROM "nations" WHERE "nations"."id" IS NULL ORDER BY "nations"."id" ASC LIMIT 1
Rendered layouts/_topnavbar.html.erb (101.0ms)
Rendered layouts/_breadcrumb.html.erb (7.4ms)
Rendered layouts/_flash.html.erb (31.4ms)
Rendered layouts/_footer2.html.erb (8.6ms)
Completed 200 OK in 4223ms (Views: 4203.2ms | ActiveRecord: 4.5ms)
原来这是由 Rollbar 造成的混乱。
Rollbar 按 class 聚合异常,默认情况下不是错误消息。因此,在发送错误报告时,报告会显示来自该异常的第一个实例的错误消息。
所以在我们的例子中,我们第一次使用 Rollbar 部署有一个错误导致 /sign_up 给我们一个 404 错误,这个错误已经修复,但在那之后,任何 404 都会产生相同的异常 class,所以当一个漏洞利用机器人请求时,比如 /wp-login.php 我们会收到一封来自 Rollbar 的电子邮件,上面写着:
ActionController::RoutingError: No route matches [GET] "/sign_up"
即使导致最近错误的实际路径不是 /sign_up
我们已通过更改分组下 Rollbar 的设置以打开 "Include Exception Message" 来解决此问题 - 这样新的 404 就不会与 /sign_up
分组在一起我还将此添加到 config/initializers/rollbar.rb
以过滤掉其中一些 404,以免发送到 Rollbar。
# Ignore bots trying to hack non existent end-points
config.exception_level_filters.merge!('ActionController::RoutingError' => lambda { |e|
e.message =~ %r(No route matches \[[A-Z]+\] "/(.+)")
case .split("/").first.to_s.downcase
when *%w(myadmin phpmyadmin w00tw00t pma cgi-bin xmlrpc.php wp wordpress cfide)
'ignore'
else
'warning'
end
})