You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Axios在React Native中无需withCredentials即可发送Cookie?

问题:Next.js网站与React Native应用的Axios Cookie配置差异

我拥有一个基于NextJs/React的网站和一个React Native应用。在通过Axios向REST API端点发送携带accessToken的Cookie时,网站端的请求需要添加withCredentials参数,但React Native端的请求无需指定该参数即可正常工作。以下是两端的代码实现:

网站端代码

import axios from 'axios';

//right here
const axiosPrivate = axios.create({
    baseURL: process.env.NEXT_PUBLIC_API_BEDAPP2,
    withCredentials: true
});

axiosPrivate.interceptors.request.use(
    config => {
        config.timeout = 5000;
        return config;
    }, (error) => Promise.reject(error)
);

axiosPrivate.interceptors.response.use(
    response => response,
    async (error) => {
        const prevRequest = error?.config;
        if (error.response?.status === 401 && error.response.data?.code === 'AccessTokenExpired' && !prevRequest.sent) {
            prevRequest.sent = true;
            const refreshToken = localStorage.getItem('refreshToken');
            try {
                const { data } = await axios.post(process.env.NEXT_PUBLIC_API_BEDAPP2 + '/auth/refresh-token',
                    { refreshToken },
                    { withCredentials: true });
                localStorage.setItem('refreshToken', data.refreshToken);
                return axiosPrivate(prevRequest);
            } catch (error) {
                localStorage.clear;
                return Promise.reject(error);
            }
        } else if (error.response?.status === 401 && !prevRequest.sent) {
            prevRequest.sent = true;
            try {
                const { data } = await axios.post(process.env.NEXT_PUBLIC_API_BEDAPP2 + '/auth/login',
                    {
                        name: process.env.NEXT_PUBLIC_API_USERNAME,
                        password: process.env.NEXT_PUBLIC_API_PASSWORD
                    },
                    { withCredentials: true });
                localStorage.setItem('refreshToken', data.refreshToken);
                return axiosPrivate(prevRequest);
            } catch (error) {
                return Promise.reject(error);
            }
        }

        return Promise.reject(error);
    }
);

export default axiosPrivate;

React Native端代码

import { useEffect } from 'react';
import axios from 'axios';
import { useDispatch } from 'react-redux';
import AsyncStorage from '@react-native-async-storage/async-storage';

import { getData } from '../common';
import { login } from '../store/userSlice';

//righ here
const axiosPrivate = axios.create({
    baseURL: 'https://xxxx.site.com.br',
});

export default useAxiosPrivate = () => {

    const dispatch = useDispatch();

    useEffect(() => {
        const requestIntercept = axiosPrivate.interceptors.request.use(
            config => {
                config.timeout = 5000;
                return config;
            }, (error) => Promise.reject(error)
        );

        const responseIntercept = axiosPrivate.interceptors.response.use(
            response => response,
            async (error) => {
                const prevRequest = error?.config;
                if (error.response?.status === 401 && error.response.data?.code === 'AccessTokenExpired' && !prevRequest.sent) {
                    prevRequest.sent = true;
                    const { refreshToken } = await getData();
                    try {
                        const { data } = await axios.post('https://xxxx.site.com.br/auth/refresh-token', { refreshToken });
                        await AsyncStorage.mergeItem('@storage_Key', JSON.stringify({ refreshToken: data.refreshToken }));
                        return axiosPrivate(prevRequest);
                    } catch (error) {
                        await AsyncStorage.mergeItem('@storage_Key', JSON.stringify({ id: '', refreshToken: '' }));
                        dispatch(login({ name: '', id: '' }));
                        return Promise.reject(error);
                    }
                }
                    
                return Promise.reject(error);
            }
        );

        return () => {
            axiosPrivate.interceptors.request.eject(requestIntercept);
            axiosPrivate.interceptors.response.eject(responseIntercept);
        }
    }, [])

    return axiosPrivate;
}

差异原因解析

1. 浏览器的同源策略约束

网站运行在浏览器环境中,浏览器严格遵循同源策略:默认情况下,跨域请求不会自动携带Cookie(即使同域请求,部分场景也需要显式授权)。Axios的withCredentials: true就是明确告诉浏览器,允许在请求中携带Cookie、HTTP认证等凭证,否则浏览器会自动丢弃Cookie,导致API无法识别用户身份。

2. React Native无同源策略限制

React Native的网络请求底层依赖原生平台的网络组件(iOS的NSURLSession、Android的OkHttp),而非浏览器的XMLHttpRequest/Fetch API。这些原生组件没有同源策略限制,默认会自动管理Cookie:只要API返回的Cookie被存入原生Cookie容器,后续同域名请求就会自动携带对应的Cookie,无需额外配置withCredentials。

3. Cookie存储机制差异

  • 网站的Cookie由浏览器自身的Cookie存储管理,受同源策略约束,必须通过withCredentials授权才能在请求中携带。
  • React Native的Cookie存储由原生网络层维护,和浏览器完全隔离,只要请求域名一致,原生网络层就会自动匹配并发送Cookie,不需要额外配置。

内容的提问来源于stack exchange,提问作者Bruno Nobre

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 06:04:53