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

React中如何正确解码URL参数特殊字符?解决Token匹配失败问题

问题:URL中Token的+号丢失导致认证匹配失败

我正在开发一款Web应用,支持用户通过包含Token的重定向URL完成认证。Token已生成,当前需从URL中提取Token并与本地存储的Token进行比对,但尝试两种方法后,Token中的+号都会丢失,导致两个Token无法匹配:

尝试的方法1:使用decodeURIComponent()

import React, { useEffect, useState } from 'react';
...
import { useLocation } from 'react-router-dom';
import { checkToken } from '../helper/token';

function ConfirmationPage(props) {
  const location = useLocation();

  const [token, setToken] = useState('');
  const [savedToken, setSavedToken] = useState('');

  useEffect(() => {
    const searchParams = new URLSearchParams(location.search);
    const paramsToken = decodeURIComponent(searchParams.get('token'));
        setToken(paramsToken);

    console.log('Params Token: ', paramsToken);
    console.log('State Token: ', token);

    const userToken = JSON.parse(localStorage.getItem('userToken'));
    setSavedToken(userToken.token);

    console.log('User Token: ', userToken.token);
  }, [location.search, token]);

  useEffect(() => {
    if (token && savedToken) {
      checkToken(token, savedToken);
    }
  }, [savedToken, token]);

  return (
    <>
      <LogoNavbar />
      <div className="vh-100 d-flex align-items-center justify-content-center">
        <NormalSpinner size="lg" />
        <p>Token: {token.toString()}</p>
      </div>
    </>
  );
}

export default ConfirmationPage;

尝试的方法2:使用.replace()

import React, { useEffect, useState } from 'react';
...
import { useLocation } from 'react-router-dom';
import { checkToken } from '../helper/token';

function ConfirmationPage(props) {
  const location = useLocation();

  const [token, setToken] = useState('');
  const [savedToken, setSavedToken] = useState('');

  useEffect(() => {
    const searchParams = new URLSearchParams(location.search);
    const paramsToken = searchParams.get('token');
    const decodedParamsToken = paramsToken.replace(/\+/g, '%2B');
    setToken(decodedParamsToken);

    console.log('Params Token: ', paramsToken);
    console.log('State Token: ', token);

    const userToken = JSON.parse(localStorage.getItem('userToken'));
    setSavedToken(userToken.token);

    console.log('User Token: ', userToken.token);
  }, [location.search, token]);

  useEffect(() => {
    if (token && savedToken) {
      checkToken(token, savedToken);
    }
  }, [savedToken, token]);

  return (
    <>
      <LogoNavbar />
      <div className="vh-100 d-flex align-items-center justify-content-center">
        <NormalSpinner size="lg" />
        <p>Token: {token.toString()}</p>
      </div>
    </>
  );
}

export default ConfirmationPage;

原因分析

URLSearchParams默认遵循application/x-www-form-urlencoded规范,会自动将参数中的+解码为空格——这就是你丢失+号的核心原因。你的两种处理方式要么重复解码,要么替换逻辑错误,都没解决这个本质问题。

解决方案及优化代码

方案1:规范URL生成逻辑(优先推荐)

在生成重定向URL时,必须用encodeURIComponent()对Token进行编码,这样Token中的+会被转为%2B,前端直接用URLSearchParams就能正确解码:

import React, { useEffect, useState } from 'react';
import { useLocation } from 'react-router-dom';
import { checkToken } from '../helper/token';

function ConfirmationPage(props) {
  const location = useLocation();
  const [token, setToken] = useState('');
  const [savedToken, setSavedToken] = useState('');

  useEffect(() => {
    // 直接提取解码后的Token,URL生成时已用encodeURIComponent编码
    const searchParams = new URLSearchParams(location.search);
    const paramsToken = searchParams.get('token');
    if (paramsToken) {
      setToken(paramsToken);
    }

    // 读取本地存储的Token
    const userToken = JSON.parse(localStorage.getItem('userToken'));
    if (userToken?.token) {
      setSavedToken(userToken.token);
    }
  }, [location.search]); // 移除token依赖,避免循环触发

  useEffect(() => {
    if (token && savedToken) {
      checkToken(token, savedToken);
    }
  }, [savedToken, token]);

  return (
    <>
      <LogoNavbar />
      <div className="vh-100 d-flex align-items-center justify-content-center">
        <NormalSpinner size="lg" />
        <p>Token: {token}</p>
      </div>
    </>
  );
}

export default ConfirmationPage;

方案2:无法控制URL生成时的兼容处理

如果重定向URL由第三方生成,无法修改编码逻辑,就用正则手动提取参数的原始字符串,再用decodeURIComponent()解码,绕过URLSearchParams的自动替换规则:

// 在useEffect中替换提取逻辑
const tokenMatch = location.search.match(/[?&]token=([^&]+)/);
if (tokenMatch) {
  const paramsToken = decodeURIComponent(tokenMatch[1]);
  setToken(paramsToken);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 14:46:02