关注ruby on rails教程(https://www.railstutorial.org/book/log_in_log_out)。注销功能不起作用。我制作了一个'会话'控制器并定义了一个方法destroy to' log_out' ' current_user'这是一个实例变量,并在调用log_out方法时更改为nil。 ' log_out' sessions_helper.rb中的方法。
module SessionsHelper
def log_in(user)
session[:user_id] = user.id
end
def remember(user)
user.remember
cookies.permanent[:remember_token] = user.remember_token
cookies.permanent.signed[:user_id] = user.id
end
def current_user
if (user_id = session[:user_id])
@current_user ||= User.find_by(id: session[:user_id])
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies:[:remember_token])
log_in user
@current_user = user
end
end
end
def logged_in?
!current_user.nil?
end
def log_out
debugger
session.delete(:user_id)
@current_user = nil
end
end
我使用DELETE请求' / logout'。
delete 'logout' => 'sessions#destroy'
视图中布局的相关部分
<% if logged_in? %>
<ul class="text-center nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Account <span class="caret"></span></a>
<ul class="text-center dropdown-menu">
<li class="text-center"><%= link_to "Profile", current_user %></li>
<li class="text-center"><%= link_to "Settings", "#" %></li>
<li role="separator" class="divider"></li>
<li class="text-center"><%= link_to "Log Out", logout_path, :method => :delete %></li>
</ul>
</li>
</ul>
<% else %>
<li><a id="signin" href="/login">Sign In</a></li>
<% end %>
我认为log_out方法不起作用,因为视图没有改变,根据行<% if logged_in? %>
,logged_in方法应该阻止在删除会话时呈现视图部分。在哪里&#39; logged_in?&#39; method在sessions_helper.rb中定义,如果用户已登录,则返回布尔值true。
整个routes.rb
Rails.application.routes.draw do
root 'static_pages#home'
get 'about' => 'static_pages#about'
get 'help' => 'static_pages#help'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users
end
整个sessions_controller.rb
class SessionsController < ApplicationController
def new
end
def create
user = User.find_by(email: params[:session][:email].downcase)
if user && user.authenticate(params[:session][:password])
log_in user
remember user
redirect_to user
else
flash.now[:danger] = 'Invalid email/password combination'
render 'new'
end
end
def destroy
log_out
end
end
整个sessions_helper.rb
module SessionsHelper
def log_in(user)
session[:user_id] = user.id
end
def remember(user)
user.remember
cookies.permanent[:remember_token] = user.remember_token
cookies.permanent.signed[:user_id] = user.id
end
def current_user
if (user_id = session[:user_id])
@current_user ||= User.find_by(id: session[:user_id])
elsif (user_id = cookies.signed[:user_id])
user = User.find_by(id: user_id)
if user && user.authenticated?(cookies:[:remember_token])
log_in user
@current_user = user
end
end
end
def logged_in?
!current_user.nil?
end
def log_out
session.delete(:user_id)
@current_user = nil
end
end
答案 0 :(得分:7)
在Rails中记录用户的正确方法是by invalidating the session。
def log_out
reset_session
@current_user = nil
end
Rails中的会话工作是访问者在首次访问网站时发出带有会话ID(哈希)的cookie。这与存储的会话(也是cookie)相关联,rails跟踪哪些会话id有效。
reset_session
使服务器上的会话ID无效,如果您想避免会话固定和重放攻击等问题,这非常重要。它还会发出新的会话ID。
执行session.delete(:user_id)
仅操纵客户端持有的会话存储cookie。因此,如果客户端例如发送较旧的cookie,他们仍然会登录!
那为什么不在教程中?
微米。 Hartl的Rails教程书并没有得到官方批准,虽然它非常擅长解释它包含的很多关键概念,这是非常值得怀疑的。