Rails API 用户身份验证接受来自 React 代理的 api 调用,但不直接来自主机 url

Posted

技术标签:

【中文标题】Rails API 用户身份验证接受来自 React 代理的 api 调用,但不直接来自主机 url【英文标题】:Rails API user auth accepts api calls from React proxy but not directly from host url 【发布时间】:2021-11-05 12:57:09 【问题描述】:

我目前正在尝试部署一个 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 时一切正常,但当我明确调用它时,rails 找不到 session[:user_id] 进行身份验证时会发生这种情况?我花了几天时间尝试不同的东西,寻找解决方案......

【问题讨论】:

【参考方案1】:

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

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

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

【讨论】:

以上是关于Rails API 用户身份验证接受来自 React 代理的 api 调用,但不直接来自主机 url的主要内容,如果未能解决你的问题,请参考以下文章

Rails API:实现身份验证的最佳方式?

SOA:Rails 多个客户端的用户身份验证和 api 授权

Rails API - 无法创建用户,密码是FILTERED并返回所有验证错误

Rails JSON API 的简单令牌认证注销

这个 Rails JSON 身份验证 API(使用 Devise)安全吗?

rails 3中的api身份验证