盡管我沒有修改任何代碼,但登錄功能卻無法作業,而這一功能一直在作業。即使我輸入了正確的電子郵件地址和密碼,它也會被重定向到登錄頁面。 我沒有使用devise。
首先,我認為有些編碼是錯誤的,但根據日志,它說電子郵件地址和密碼是正確的,它試圖正確地重定向到頂頁。
接下來,我使用了Burp Suite工具,該工具在瀏覽器和服務器(本地代理)之間跟蹤會話ID等資料。
我發現在登錄后,會話ID沒有被給出,它帶來了authenticate_user引起的錯誤,所以登錄失敗了。
我想找出原因并解決它。
此外,我使用了工具ngrok,它使用戶能夠訪問我的本地主機。
然后令人驚訝的是,我本地環境之外的用戶能夠成功登錄。
而Burp Suite顯示,在這種情況下,會話ID被賦予了屬性。
因此,只有當我試圖從我的本地環境登錄時,會話ID才沒有被賦予。 最近,我沒有編輯任何代碼,而是做了以下這些作業。
- 安裝Git.
- 通過Git將我的 "app1 "推送到GitHub. 。
- 安裝SourseTree,并與我的GitHub連接。
- 通過SourceTree從GitHub克隆我的 "app1",并將其命名為 "app2"。
在做這些作業之前,我添加了下面這段代碼。但是,即使我把它注釋掉,也沒有改變情況。
application.rb
config.session_store :cookie_store, expire_after: 8.hours
所有問題都發生在這些任務之后。
代碼
routes.rb
get "login" => " users#login_form"
post "login" => "users#login".
post "logout" => "users#logout".
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :set_current_user
skip_before_action :verify_authenticity_token
caches_action :set_current_user, :authenticate_user, :forbid_login_user.
def set_current_user>>
@current_user = User.find_by(id: session[:user_id] )
end
def authenticate_user
if @current_user == nil
flash[:notice] = "你需要登錄"。
redirect_to("/login"/span>)
結束。
end end
def forbid_login_user>>
if @current_user
flash[:notice] = "你已經登錄了"。
redirect_to("/"/span>)
結束。
結束。
end end
users_controller.rb
before_action :authenticate_user, {except: [:new, :create, : login_form, : login]}。
before_action :forbid_login_user, {only:/span> [: new, : create, : login_form, : login]}。
before_action :sure_correct_user, {only: [:edit, :update]}.
before_action :sure_correct_user_account, {only: [:set_password, : update_password, :set_email, :update_email, :delete_account, :destroy]}。
caches_action :index, :show, :follow, :new, 。 創建, :編輯, :user_params, :更新, : destroy, :login_form, :login, :logout, : likes, :sure_correct_user, :followings, :followers, :top
def login
@user = User.find_by(email: params[:email] )
if @user && @user.authenticate(params[:password] )
session[:user_id] = @user.id
flash[:notice] = "您已成功登錄"。
redirect_to("/"/span>)
else
@error_message = "Email address or password is incorrect"。
@email = params[:email]
@password = params[:password]
render(" users/login_form")
結束。
結束。
def login_form
end
def logout
session[:user_id] = nil
flash[:notice] = "您已成功登出"。
redirect_to("/login"/span>)
結束。
當用戶成功登錄后,會重定向到"/"(首頁)。
日志
這是我試圖登錄時的日志。看到Started GET "/",用戶似乎成功登錄了。但隨后日志說 過濾鏈停止了,因為 :authenticate_user 呈現或重定向,并且重定向到 "/login"。
Started POST "/login"/span> for :: 1在2021-08-24 14。 44:31 0900
處理 by UsersController#login as HTML
Parameters: {"utf8"=>"?", " authenticity_token"=> "JBcKtTsdCT0JXgyIfzjKVqi/8KEz4pRmUXB2Kybn8eHcnz7UKXoMsbBRknoUqwnIdi4hUkZ/6oQKFVqMyG/g==", "email"/span>=> "hoge", "password"=>"[FILTERED]"}。
User Load (35.1ms) SELECT `users`. * FROM `users` WHERE `users`。 `id` IS NULL limit 1
? app/controllers/application_controller.rb:9
User Load (0.6ms) SELECT `users`. * FROM `users` WHERE `users`。 `email` = 'hoge' LIMIT 1.
? app/controllers/users_controller.rb:255
重定向到http:/localhost:3000/。
完成 302 發現 in 422ms (ActiveRecord: 41.9ms)
Started GET "/" for : 。 1在2021-08-24 14。 44:32 0900
處理由UsersController#top 作為 HTML
User Load (0.6ms) SELECT `users`. * FROM `users` WHERE `users`。 `id` IS NULL limit 1
? app/controllers/application_controller.rb:9
重定向到http:/localhost:3000/login。
過濾器鏈停止 因為 :authenticate_user呈現或重定向了
完成 302 發現 in 6ms (活動記錄: 0.6ms)
Started GET "/login" for :: 1在2021-08-24 14。 44:32 0900
處理由UsersController#login_form as HTML進行處理。
User Load (0.5ms) SELECT `users`. * FROM `users` WHERE `users`。 `id` IS NULL limit 1
? app/controllers/application_controller.rb:9
渲染 users/login_form.html.erb在layouts/application內
已更新 users/login_form.html.erb在layouts/application內(0.9ms)。
CACHE User Load (0. 1ms) SELECT `users`. * FROM `users` WHERE `users`。 `id` IS NULL limit 1
? app/views/layouts/application.html.erb: 51
完成 200 OK in 244ms(Views: 233.9ms | ActiveRecord: 0.5ms)
Burp套件的顯示
當我使用ngrok時,當用戶從外部登錄時,如何給出會話ID。你可以看到 "Cookie "和 "Set-Cookie "都被顯示。
。
當我嘗試從本地環境登錄時。Cookie "和 "Set-Cookie "都不能被看到。
我已經嘗試了什么
重新啟動服務器和我的電腦并沒有解決這個問題。 幾個瀏覽器(Google Chrome、Firefox和Brave)顯示了相同的結果。版本
Ruby 2.6.4p104 RubyGems 3.0.3 Rails 5.2.3 Burp套件社區版2021.8.2
Postscript
這些作業并沒有改變情況。- 把
bundle exec rake tmp:cache:clear放在一個命令上。 - 將
rails tmp:clear放在一個命令上。 - 在
users_controller.rb中洗掉會話歷史。
def login_form
重置會話
session[:user_id] =nil
session.delete(:user_id)
end
uj5u.com熱心網友回復:
一個更好的認證方法是:
# app/errors/authentication_error.rb
class AuthenticationError < StandardError; end
class ApplicationController < ActionController::Base
protect_from_forgery with: :null_session
before_action :authenticate_user!
rescue_from 'AuthenticationError', with: :deny_access
私有
def current_user
@current_user ||= User.find_by(id: session[:user_id] )
end
def user_signed_in?
current_user.present?
end
def authenticate_user!
raise AuthenticationError unless user_signed_in?
end
def deny_access
flash[:notice] = "您需要登錄"。
redirect_to login_path
end
end
不要用回呼來設定當前用戶,而是使用一個方法來記憶其值。這就消除了與回呼順序相關的潛在問題。這應該是唯一知道用戶在會話中如何被持久化的方法。
使用默認安全方法而不是顯式驗證。這意味著不要呼叫 before_action :authenticate_user, {except: [:new, :create, :login_form, :login]}你呼叫skip_before_action :authenticate_user, only: [:new, :create, :login_form, :login]來選擇不接受授權。
如果用戶未被認證,則會引發錯誤,這將為您在測驗時節省大量的除錯時間,因為您可以禁用rescue_from以確保引發錯誤。
不要把所有的東西都塞進一個巨大的UsersController中,而是創建一個控制器,它只負責用戶的簽入和簽出。
scope controller: 'session'/span> do
獲取 :login, 動作: :new, as: :login
post :login, action: :create.
洗掉 :logout, 動作: :destroy, 作為: :logout
得到:logout, 動作: :destroy, as: :logout
end
class SessionsController < ApplicationController
skip_before_action :authenticate_user!
before_action :deny_access_to_signed_in_users, if: :user_signed_in? ,
# GET /login, :user_signed_in?
def new
@user = User.new
end @user = User.new
# POST /login
def create
@user = User.find_by(email: params[:email] )
if @user && @user.authenticate(params[:password] )
session[:user_id] = @user.id
flash[:notice] = "您已成功登錄"。
重定向到root_path
else>
flash[:notice] = "電子郵件地址或密碼不正確"。
@user = User.new(**params.permit(:email, :password)
呈現:new。
end end
end
# DELETE /logout
def destroy
session[:user_id] = nil
flash[:notice] = "您已成功登出"。
redirect_to login_path
end
私有
def deny_access_to_signed_in_users
flash[:notice] = "You are already logged in!"
redirect_to root_path
end
end
# app/views/sessions/new.html.erb
<h1>Sign in</h1>
<%= form_with(model: @user, path: login_path, method: :post, local: true) do |form| %>
<div class="field">
<%= form.label :email %>
<%= form.email_field :email %>
</div>
<div class="field">
<%= form.label :password %>
<%= form.email_field :email %>
</div>
<div class="actions">
<%= form.submit 'Sign in' %>
</div>
<% end %>
uj5u.com熱心網友回復:
我自己能夠解決這個問題。
我過去做了session_store.rb這個檔案,它就是原因。
config > initializers > session_store.rb
app_name = "app_name"
Rails.application.config.session_store :cookie_store, key: "_app_name_session", expire_after: 8.hours, secure: true。
secure: true禁止http傳遞cookie,所以我不能只在localhost上登錄。我忘了洗掉這個檔案。
我洗掉了session_store.rb,并在application.rb中寫了以下代碼。
config.session_store :cookie_store, expire_after: 8. hours, secure: Rails.env.production?
現在,登錄功能在localhost上也能作業了。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/319163.html
標籤:
