React-Router+IIS+ASP.NET Core双参数URL访问400错误排查
忘记密码重置URL中Token丢失字符导致400错误的解决方案
基于React、React-Router、IIS和ASP.NET Core开发的忘记密码功能,通过邮件向用户发送包含userId和token的重置密码URL,但访问该URL时,第二个参数tokenId会丢失部分字符,进而触发「Bad Request - Invalid URL HTTP Error 400」错误。以下是相关代码信息及解决办法:
相关代码信息
1. 示例URL
http://www.example.com/update-password/d2ff3788-aa12-47b6-8759-8b52cca02a3b/Q2ZESjhQL1dOb0l3bGYxSW1XZktVbTN3ckx3SnAyNFB2Z2dhNXRBWVBlMWJyd3Jaa1ZEejV5WDA5TExtNi93djBPWUMwN1NyK1NrMG1VVnM5V1E2RmdsbXBkVXlUMFlXS0o1ZzlJVWxUQU9kSlJLWC9sUC9RRXdldEtRLzFZTnNOa216dXN5eEhub29MRi84Z1Q1SVVoc1c0MWFrWHkwVUN2YnAxa0VGWU1PenU4emFNc3hwNWN0K3BudDlmYktic2RPcVlpOSsraGo2RFc4d2EzOFdJUm1XMHc0L0dpeWNISG4vWUU4aU9FdGtmRlZh
2. React项目index.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap-grid.min.css" /> --> </head> <body> <div id="root"></div> <script type="module" src="./src/main.jsx"></script> </body> </html>
3. React路由配置
导入部分:
import { BrowserRouter as Router, // <-- import Router component Route, Routes } from 'react-router-dom'
路由定义:
<Route path='/update-password' element={<UpdatePassword />}> <Route path="/update-password/:userId/:tokenId" element={<UpdatePassword />} /> </Route>
4. Token信息
未编码的Token:
CfDJ8EHnmcjBPm9MoR2xSCwmz5BloVGwo3ncXBxlFX7ygpB2ukH2K3huzfxvWxY4mgBb7LtKRoUzggOICsZpfFOCqXHN02zYQiIYSZwG8AVZkEnFt4lZo102aojOHgyMR1R/QfqlYzn5F5to8ydt/8GgtQpVGqVzz5fa853R/AH18EtOK5zow1akfZ4LIx6ZO39Z+iSmFbhUWfL27vx6vmJ5U9BxUn3bUgHpnJPJY6CzNlcboSCGist9knfxNWjgR8T2Cg==
编码后的Token:
Q2ZESjhFSG5tY2pCUG05TW9SMnhTQ3dtejVCbG9WR3dvM25jWEJ4bEZYN3lncEIydWtIMkszaHV6Znh2V3hZNG1nQmI3THRLUm9VemdnT0lDc1pwZkZPQ3FYSE4wMnpZUWlJWVNad0c4QVZaa0VuRnQ0bFpvMTAyYW9qT0hneU1SMVIvUWZxbFl6bjVGNXRvOHlkdC84R2d0UXBWR3FWeno1ZmE4NTNSL0FIMThFdE9LNXpvdzFha2ZaNExJeDZaTzM5WitpU21GYmhVV2ZMMjd2eDZ2bUo1VTlCeFVuM2JVZ0hwbkpQSlk2Q3pObGNib1NDR2lzdDlrbmZ4TldqZ1I4VDJDZz09
5. C#后端代码
public async Task MailOnaylamaAsync(string eMail) { AppUser user = await _UserManager.FindByEmailAsync(eMail); if (user != null) { string mailToken = await _UserManager.GenerateEmailConfirmationTokenAsync(user); byte[] tokenBytes = Encoding.UTF8.GetBytes(mailToken); mailToken = WebEncoders.Base64UrlEncode(tokenBytes); await _mailService.SendMailOnayAsync(eMail, user.Id, mailToken); }
问题原因及解决办法
1. 路由配置错误
当前嵌套路由的子路径写了完整前缀,导致解析异常。修改为相对路径:
<Route path='/update-password' element={<UpdatePassword />}> <Route path=":userId/:tokenId" element={<UpdatePassword />} /> </Route>
或者直接定义为独立路由,避免嵌套问题:
<Route path='/update-password/:userId/:tokenId' element={<UpdatePassword />} />
2. IIS限制长URL或特殊字符
IIS默认的URL长度限制可能截断长Token,在项目的web.config中添加配置调整限制:
<system.webServer> <security> <requestFiltering> <!-- 根据实际Token长度调整maxUrl数值 --> <requestLimits maxUrl="8192" maxQueryString="4096" /> </requestFiltering> </security> </system.webServer>
3. Token编码/解码验证
确保后端接收Token时用对应的Base64UrlDecode还原:
// 接收重置请求时解码Token byte[] tokenBytes = WebEncoders.Base64UrlDecode(receivedToken); string originalToken = Encoding.UTF8.GetString(tokenBytes);
同时检查邮件模板中拼接URL时是否有换行、空格或截断,保证Token完整嵌入。
4. 改用QueryString传递Token
如果路径参数问题仍无法解决,将Token放在QueryString中传递:
http://www.example.com/update-password/d2ff3788-aa12-47b6-8759-8b52cca02a3b?tokenId=Q2ZESjhFSG5tY2pCUG05TW9SMnhTQ3dtejVCbG9WR3dvM25jWEJ4bEZYN3lncEIydWtIMkszaHV6Znh2V3hZNG1nQmI3THRLUm9VemdnT0lDc1pwZkZPQ3FYSE4wMnpZUWlJWVNad0c4QVZaa0VuRnQ0bFpvMTAyYW9qT0hneU1SMVIvUWZxbFl6bjVGNXRvOHlkdC84R2d0UXBWR3FWeno1ZmE4NTNSL0FIMThFdE9LNXpvdzFha2ZaNExJeDZaTzM5WitpU21GYmhVV2ZMMjd2eDZ2bUo1VTlCeFVuM2JVZ0hwbkpQSlk2Q3pObGNib1NDR2lzdDlrbmZ4TldqZ1I4VDJDZz09
然后在React组件中用useSearchParams获取Token:
import { useSearchParams } from 'react-router-dom'; function UpdatePassword() { const [searchParams] = useSearchParams(); const tokenId = searchParams.get('tokenId'); // 后续逻辑 }
内容的提问来源于stack exchange,提问作者Omar Dak Elbab
相关产品推荐
相关产品推荐

