无法使用JWT身份验证在Rails后端中创建用户对象

时间:2019-10-14 16:53:26

标签: ruby-on-rails reactjs authentication jwt

我正在尝试使用JWT身份验证在Rails PostgreSQL数据库中创建User对象。当我从React前端触发create user方法时,没有在后端创建用户,我怀疑这与控制器的设置有关。

这是我在Rails后端中的用户控制器:

class Api::V1::UsersController < ApplicationController
  before_action :find_user, only: [:show]
  skip_before_action :authorized, only: [:index, :create]

  def index
    @users = User.all
    render json: @users
  end

  def show
    render json: @user
  end

  def create
    @user = User.create(user_params)
    if @user.valid?
      @token = encode_token(user_id: @user.id)
      render json: { user: UserSerializer.new(@user), jwt: @token }, status: :created
    else
      render json: {error: "Could not create user"}, status: :unprocessible_entity
    end
  end

end

private

def user_params
  params.permit(:username, :password)
end

def find_user
  @user = User.find(params[:id])
end

这是我对JWT的“认证”控制器:

class Api::V1::AuthController < ApplicationController
  skip_before_action :authorized, only: [:create]

  def create # POST /api/v1/login
    @user = User.find_by(username: user_login_params[:username])
    if @user && @user.authenticate(user_login_params[:password])
      @token = encode_token({ user_id: @user.id })
      render json: { user: UserSerializer.new(@user), jwt: @token }, status: :accepted
    else
      render json: { message: 'Invalid username or password' }, status: :unauthorized
    end
  end

  private

  def user_login_params
    params.require(:user).permit(:username, :password)
  end
end

还有我的应用程序控制器(我怀疑问题出在这里,与我编码和解码令牌的方式有关)

class ApplicationController < ActionController::API
  before_action :authorized

  def encode_token(payload) 
    JWT.encode(payload, ENV["jwt_secret"]) 
  end

  def auth_header
    request.headers['Authorization']
  end

  def decoded_token
    if auth_header()
      token = auth_header.split(' ')[1] 
      begin
        JWT.decode(token, ENV["jwt_secret"], true, algorithm: 'HS256')
      rescue JWT::DecodeError
        nil
      end
    end
  end

  def current_user
    if decoded_token()
      user_id = decoded_token[0]['user_id'] 
      @user = User.find_by(id: user_id)
    else
      nil
    end
  end

  def logged_in?
    !!current_user
  end

  def authorized
    render json: { message: 'Please log in' }, status: :unauthorized unless logged_in?
  end
end

从前端开始,我正在使用fetch方法将POST张贴到/ users /端点,如下所示:

export const signupUser = (username, password) => {
  return(dispatch) => {
    const data = {user: {username, password} }
    fetch('http://localhost:3000/api/v1/users',{
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Accept: 'application/json'
      },
      body: JSON.stringify(data)
    })
    .then(r=>r.json())
    .then(r=>{
      localStorage.setItem('jwt', r.jwt)
      dispatch({
        type: SET_CURRENT_USER,
        payload: r.user
      })
    })
  }
}

很抱歉,这是漫长的。我想包括所有必要的代码来解决这个问题。任何援助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我注意到您在使用函数创建用户时没有保存用户对象。请检查app/controllers/api/v1/users_controller.rb并使用valid将以下内容修改为save方法

def create
    @user = User.create(user_params)
    if @user.valid?
      @token = encode_token(user_id: @user.id)
      render json: { user: UserSerializer.new(@user), jwt: @token }, status: :created
    else
      render json: {error: "Could not create user"}, status: :unprocessible_entity
    end
  end

将行@user.valid?更改为@user.save

def create
    @user = User.create(user_params)
    if @user.save
      @token = encode_token(user_id: @user.id)
      render json: { user: UserSerializer.new(@user), jwt: @token }, status: :created
    else
      render json: {error: "Could not create user"}, status: :unprocessible_entity
    end
  end

请注意.valid吗?用于验证和检查是否有任何错误,.save用于保存错误。您只是在检查验证而没有实际保存,验证会自动发生,因此这里不需要此方法。