Devise会话超时重定向至当前路径的原因及Rails Admin循环问题解析
timeoutable: Why Redirect to Current Path, and When Does This Make Sense? Great question—this behavior can feel super counterintuitive at first, especially when it throws you into those annoying redirect loops like you’re seeing in Rails Admin. Let’s break this down step by step.
First: Why Does This Happen?
Devise's timeoutable module leans on Warden's failure handling system, where the attempted_path (the exact URL the user was trying to access) gets stored before triggering the failure app. The default logic redirects back to this path instead of directly to the login page with a clear intent: preserving the user's intended workflow. The idea is that once the user logs back in, they should land exactly where they were trying to go, not just a generic login page.
The redirect loop happens because of a edge case: if the attempted_path is a route that requires authentication (like every route in Rails Admin), redirecting there immediately triggers another authentication failure (since the user is still logged out), which restarts the cycle all over again.
When This Design Works Well
This redirect logic shines in most standard Rails applications where:
- There are public, unauthenticated routes: If a user's session times out while they're browsing a public page (e.g., a blog post, product listing, or help article), redirecting back to that page makes perfect sense. No login is required, so no loop, and the user's flow isn't interrupted at all.
- The login flow handles post-login redirection properly: Even for authenticated routes, this logic works seamlessly if your login action checks for the stored
attempted_pathand redirects the user there after successful authentication. In standard Devise setups, this is handled automatically—so the expected flow (user tries Page X → timeout → redirect to login → login → back to Page X) should work as intended. If you're seeing a direct redirect to Page X, it might be due to a custom failure app override or an older Devise version with different default logic.
Why Rails Admin Causes a Loop
Rails Admin's entire namespace is locked down to authenticated users. So when a session times out, the attempted_path is always an admin route (e.g., /admin/users or /admin/dashboard). If Devise redirects directly to that route, the request hits the authentication check again, triggers the failure app, and redirects back to the same route—creating an infinite loop.
Fixing the Loop (Bonus)
If you're stuck with this in Rails Admin, you can override the failure app to redirect to the admin login page instead of the attempted_path for admin routes. Here's a quick example:
# app/lib/custom_failure_app.rb class CustomFailureApp < Devise::FailureApp def redirect_url if request.path.start_with?('/admin') admin_session_path else super end end end # config/initializers/devise.rb config.warden do |manager| manager.failure_app = CustomFailureApp end
This way, admin users get redirected to the admin login page on timeout, and after logging in, they'll still be sent back to their intended admin route.
内容的提问来源于stack exchange,提问作者brahmana

