首页 > 解决方案 > Rails API 用户身份验证接受来自 React 代理的 api 调用,但不直接来自主机 url

问题描述

我目前正在尝试部署一个 React 前端和 Rails API Web 应用程序。在开发中,我在 package.json 中设置了一个代理来与我的 API 进行通信。用户身份验证和 CRUD 操作一切正常。现在,当我进入生产环境时,我的用户 auth 告诉我,即使我有会话令牌,我也无权进行除了登录之外的任何呼叫。

我的应用程序控制器似乎挂断了:

class ApplicationController < ActionController::API
include ActionController::Cookies
before_action :authorize

def authorize
  @current_user = User.find_by(id: session[:user_id])
  render json: {error:["Not authorized"]}, status: :unauthorized unless @current_user
end

当我注销或执行其他操作时,我的 Ruby 终端会输出类似这样的内容

Started DELETE "/logout" for ::1 at 2021-09-08 14:20:06 -0400
Processing by SessionsController#destroy as HTML
[active_model_serializers] Rendered ActiveModel::Serializer::Null with Hash (0.12ms)
Filter chain halted as :authorize rendered or redirected
Completed 401 Unauthorized in 1ms (Views: 0.6ms | ActiveRecord: 0.0ms | Allocations: 203)

这是我的用户控制器:

class UsersController < ApplicationController
wrap_parameters format: []

skip_before_action :authorize, only: [:create]
def create
    user = User.create(user_params)
    if user.valid?
        session[:user_id] = user.id 
        render json: user, status: :created
    else
        render json: {errors: user.errors.full_messages}, status: :unprocessable_entity
    end
end

def show 
    user = @current_user
    render json: user, status: :created
end

private

def user_params
    params.permit(:email, :username, :password, :password_confirmation, :bio, :join_date)
end

我的会话控制器:

class SessionsController < ApplicationController
skip_before_action :authorize, only: [:create]
def create
    user = User.find_by(username: params[:username])
    if user&.authenticate(params[:password])
        session[:user_id] = user.id
        render json: user, status: :created
    else
        render json: { errors: ["Invalid username or password"] }, status: :unauthorized
    end
end
def destroy
    session.delete(:user_id)
    head = :no_content  
end

我的 fetch 调用都是相当基本的,比如:

function signin(username, password) {
    setIsLoading(true);
    fetch("http://localhost:3000/login", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({ username, password }),
    }).then((r) => {
        setIsLoading(false);
        if (r.ok) {
            r.json().then((user) => {
                setUser(user);
            });
        } else {
            r.json().then((err) => setErrors(err.errors));
        }
    });
}

当我代理到 API URL 时一切正常但当我明确调用它时,为什么会发生这种情况session[:user_id]?我花了几天时间尝试不同的东西,寻找解决方案......

标签: reactjsruby-on-railsauthentication

解决方案


所以我的假设是,身份验证应该存储在一个 cookie 中,该 cookie 作为前端调用中的标头(隐式)传递,并且应该传递给 API。如果您 100% 确定代理在本地工作,那么我会看看您的生产设置有什么不同。

检查 cookie 标头是否正在发送到反应应用程序。检查 cookie 标头是否到达您的 rails 应用程序。

Cookie 可以具有安全设置,例如仅通过 HTTPS 发送或仅发送到特定域。您的生产设置可能会因您的 react 服务器或 rails 使用的默认安全设置而有所不同。


推荐阅读