[英]Rails Admin not authenticating with Cancancan or Devise
I tried this in the config: 我在配置中尝试了这个:
### Popular gems integration
config.authenticate_with do
warden.authenticate! scope: :user
end
config.current_user_method(&:current_user)
here, accessing /admin
gets me stuck in a login loop. 在这里,访问
/admin
会使我陷入登录循环中。 I login then get redirected to the login page. 我登录然后重定向到登录页面。
Previously I had tried 以前我尝试过
class Ability
include CanCan::Ability
def initialize(user)
# Define abilities for the passed in user here. For example:
#
user ||= User.new # guest user (not logged in)
if user.admin?
with the CanCanCan authentication in rails admin config. 在rails admin配置中使用CanCanCan身份验证。 This resulted in user always being nil.
这导致用户始终为零。 Even when I put in
即使我放进去
config.current_user_method(&:current_user)
How do I fix this to authenticate was an admin? 如何解决此问题以验证是否是管理员?
EDIT: in sessions controller 编辑:在会话控制器中
if user.admin
redirect_to rails_admin_url
else
render json: user
end
and I get stuck in the redirect back to signin. 而我陷入了重新登录的重定向中。
Routes: 路线:
Rails.application.routes.draw do
mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
devise_for :users, controllers: { sessions: :sessions },
path_names: { sign_in: :login }
... then many resources lines
EDIT: 编辑:
Sessions Controller: 会话控制器:
class SessionsController < Devise::SessionsController
protect_from_forgery with: :null_session
def create
user = User.find_by_email(sign_in_params[:email])
puts sign_in_params
if user && user.valid_password?(sign_in_params[:password])
user.generate_auth_token
user.save
if user.admin
redirect_to rails_admin_url
else
render json: user
end
else
render json: { errors: { 'email or password' => ['is invalid'] } }, status: :unprocessable_entity
end
end
end
Rails admin config, trying this: Rails管理员配置,请尝试以下操作:
### Popular gems integration
config.authenticate_with do
redirect_to merchants_path unless current_user.admin?
end
config.current_user_method(&:current_user)
In ApplicationController: 在ApplicationController中:
def current_user
@current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
Tried this, current_user is nil. 试过这个,current_user为nil。
You might need to define the after_sign_in_path_for method on the ApplicationController 您可能需要在ApplicationController上定义after_sign_in_path_for方法
By default, it first tries to find a valid resource_return_to key in the session, then it fallbacks to resource_root_path, otherwise it uses the root path. 默认情况下,它首先尝试在会话中找到有效的resource_return_to密钥,然后回退到resource_root_path,否则它将使用根路径。 For a user scope, you can define the default url in the following way:
对于用户范围,可以通过以下方式定义默认url:
get '/users' => 'users#index', as: :user_root # creates user_root_path
namespace :user do
root 'users#index' # creates user_root_path
end
If the resource root path is not defined, root_path is used. 如果未定义资源根路径,则使用root_path。 However, if this default is not enough, you can customize it, for example:
但是,如果此默认值还不够,则可以对其进行自定义,例如:
def after_sign_in_path_for(resource)
stored_location_for(resource) ||
if resource.is_a?(User) && resource.can_publish?
publisher_url
else
super
end
end
THE CONTROLLER LOGIC FOR REDIRECT 重定向控制器逻辑
The solution from Guillermo Siliceo Trueba will not work with your Users::SessionsController#create
action as you are not calling in the parent class create
action through the keyword super
. Guillermo Siliceo Trueba的解决方案不适用于您的
Users::SessionsController#create
操作,因为您没有通过关键字super
调用父类create
操作 。
The method create
from the class Devise::SessionsController
will run respond_with
in the last line using as location
the value returned from after_sign_in_path_for(resource)
该方法
create
从类Devise::SessionsController
运行respond_with
使用在上线location
,从返回的值after_sign_in_path_for(resource)
class Devise::SessionsController < DeviseController
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
end
I am using this solution in my Users::SessionsController
to handle html
and json
requests and you can implement the same. 我在我的
Users::SessionsController
使用此解决方案来处理html
和json
请求,您可以实现相同的解决方案。
If the controller receives the request
with format .json
, the code between format.json do .. end
is executed, if the request
arrives with format.html
the parent method is called (I cover all your scenarios). 如果控制器接收到该
request
与格式.json
,之间的代码format.json do .. end
被执行时,如果request
与到达format.html
父方法被称为(I涵盖所有的场景)。
Rails router identifies the request format from the .json
or .html
appended at the end of the url (for example GET https://localhost:3000/users.json
) Rails路由器从URL末尾附加的
.json
或.html
识别请求格式(例如GET https://localhost:3000/users.json
)
class Users::SessionsController < Devise::SessionsController
def create
respond_to do |format|
format.json do
self.resource = warden.authenticate!(scope: resource_name, recall: "#{controller_path}#new")
render status: 200, json: resource
end
format.html do
super
end
end
end
end
The html
request will be routed to the super
create action . html
请求将被路由到super
创建动作 。 You just need to override the method def after_sign_in_path_for(resource)
from the parent as I am doing in my ApplicationController
. 您只需要像我在
ApplicationController
所做的那样,从父类重写方法def after_sign_in_path_for(resource)
。
if resource.admin
then just return rails_admin_url
from this method and skip the other lines, otherwise follow the normal behavior and call super#after_sign_in_path_for(resource)
if resource.admin
则只需从此方法return rails_admin_url
并跳过其他行,否则按照正常行为并调用super#after_sign_in_path_for(resource)
def after_sign_in_path_for(resource)
return rails_admin_url if resource.admin
super
end
THE ERROR MESSAGES FOR AUTHENTICATION 认证错误信息
warned.authenticate!
will save inside self.resource.errors
the error messages. 将保存在
self.resource.errors
内部的错误消息。 You just need to display the errors on your device using json_response[:error]
and manipulating the response in your frontend. 您只需要使用
json_response[:error]
在设备上显示错误并在前端中处理响应即可。
I am rendering them in the SignInScreen
Component 我在
SignInScreen
组件中渲染它们
THE TOKEN AUTHENTICATION 令牌认证
user.generate_auth_token
user.save
I use the simple_token_authentication
for devise which also allows you to regenerate the token every time the user signs in . 我使用
simple_token_authentication
进行设计 ,这也使您每次用户登录时都可以重新生成令牌 。
You just install the gem and add acts_as_token_authenticatable
inside your user
model . 您只需安装gem并在
user
模型中添加acts_as_token_authenticatable
。
class User < ApplicationRecord
acts_as_token_authenticable
end
You pass headers X-User-Email
and X-User-Token
with the corresponding values as explained in their guide . 您按照标头指南中的说明传递标头
X-User-Email
和X-User-Token
。
Other alternatives to simple_token_authentication
simple_token_authentication
其他替代方法
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.