Vue+ASP.NET Web API部署实战:解决跨域、路由404与Token失效

📅 发布时间:2026/9/13 21:06:08
Vue+ASP.NET Web API部署实战:解决跨域、路由404与Token失效
1. 项目概述为什么“Vue ASP.NET Web API”发布部署总让人头疼你是不是也经历过这样的场景本地开发一切顺利Vue页面跑得飞快ASP.NET Web API接口调用丝滑流畅可一到发布部署环节就突然冒出一堆莫名其妙的问题——Vue打包后的静态资源404、API请求跨域报错、登录态失效、路由刷新404、生产环境Token验证失败、甚至IIS里连Web API根路径都返回404我带过6个前后端分离项目落地其中4个用的就是Vue ASP.NET Web API技术栈每次部署前团队都要集体加班通宵排查不是因为代码写得差而是因为发布部署不是简单地把文件拷过去而是一场涉及构建产物结构、HTTP服务行为、身份认证链路、静态资源托管策略、反向代理规则的系统级协同校准。这个标题里的关键词——Vue、ASP.NET、Web API、前后端分离、发布部署——每一个都不是孤立存在。Vue决定前端产物形态单页应用SPA、history模式路由、public目录资源映射ASP.NET Web API决定后端服务契约RESTful设计、CORS配置、JWT签发与验证、IIS集成模式“前后端分离”则意味着前后端物理隔离、域名/端口不同、通信必须走HTTP协议、状态管理完全解耦而“发布部署”就是把这两套独立运行的系统在真实服务器环境中重新建立可信、稳定、可维护的协作关系。它不考你能不能写组件而考你是否真正理解Vue的构建机制、ASP.NET的请求管道、IIS的模块加载顺序、以及浏览器同源策略在真实网络中的具体表现。适合谁来读这篇如果你是刚从Vue CLI脚手架起步、还没碰过IIS部署的前端同学如果你是熟悉ASP.NET MVC但第一次对接Vue SPA的后端开发者如果你是负责上线交付的全栈工程师或运维同事——这篇文章不会教你从零搭建项目而是聚焦在发布部署这个临门一脚的关键阶段把那些文档里没写、教程里跳过的、报错信息里藏起来的细节一条条掰开揉碎讲清楚。比如为什么vue.config.js里的publicPath设成/和./在IIS下表现天差地别为什么ASP.NET Web API的Startup.cs里CORS中间件的位置错了半行整个前端就收不到响应头为什么IIS的“默认文档”设置会悄悄劫持你的Vue Router history模式这些不是玄学是可复现、可验证、可调试的具体行为。接下来我们就从整体架构设计开始一层层拆解这套组合拳的落地逻辑。2. 整体架构设计与思路拆解先想清楚“谁管什么”再动手拷文件很多人部署失败根源在于没理清前后端分离项目的职责边界。Vue和ASP.NET Web API不是“两个程序放一起就行”而是两个独立进程、两种服务模型、三类资源归属的精密配合。我们先画一张不用代码的“部署地图”明确每个环节的Owner和关键约束。2.1 三层资源归属与服务角色划分资源类型所属方部署位置关键约束典型问题诱因Vue静态资源HTML/CSS/JS/图片前端工程产物IIS网站根目录或子应用目录必须由Web服务器直接提供不经过ASP.NET管线index.html被ASP.NET路由拦截、/static/js/app.xxx.js404ASP.NET Web API接口/api/values,/auth/login等后端工程编译结果IIS应用程序池托管的.NET Core/.NET Framework应用必须由ASP.NET运行时处理响应JSON数据/api路径返回IIS默认404、CORS头缺失导致前端跨域拒绝混合资源如/favicon.ico,/robots.txt双方都可能需要通常由IIS静态文件模块统一处理需明确优先级静态文件 ASP.NET路由Vue的public目录文件被ASP.NET路由覆盖这张表不是理论是实操铁律。我见过最典型的错误把Vue打包后的dist目录整个扔进ASP.NET项目的wwwroot里然后用app.UseStaticFiles()去serve——这看似省事实则埋下三大雷第一ASP.NET的UseStaticFiles默认不启用目录浏览index.html必须显式配置为默认文档第二所有/api/*请求仍需经过ASP.NET管线哪怕你只是想访问一个纯静态JS文件第三当Vue Router使用history模式时任意非根路径刷新如/user/profile会被ASP.NET的MVC路由引擎捕获返回404而非index.html。这不是Bug是设计使然。2.2 两种主流部署模式对比子应用 vs 独立站点实际落地中90%的团队会选以下两种模式之一选择依据不是技术先进性而是运维习惯、域名策略和安全合规要求。模式一IIS子应用推荐给中小团队Vue前端部署为IIS下的一个子应用如https://yourdomain.com/app/ASP.NET Web API部署为同一域名下的另一个子应用如https://yourdomain.com/api/优势单域名、免HTTPS证书管理、防火墙策略统一、运维操作集中关键配置点Vue的vue.config.js中publicPath: /app/必须带尾部斜杠axios基础URL设为/api/利用浏览器相对路径自动补全主域名IIS中两个子应用需独立应用程序池避免.NET Framework与.NET Core冲突模式二完全独立站点推荐给大型系统或微服务架构Vue前端部署为独立IIS站点https://web.yourdomain.comASP.NET Web API部署为另一独立IIS站点https://api.yourdomain.com优势彻底解耦、可独立扩缩容、故障隔离强、CDN接入方便关键配置点Vue中axios基础URL必须写死为https://api.yourdomain.comASP.NET Web API必须显式配置CORS允许https://web.yourdomain.com来源若使用JWT Token需确保Access-Control-Allow-Credentials: true且前端axios.defaults.withCredentials true提示不要迷信“一个站点搞定所有”。我曾接手一个把Vue和Web API硬塞进同一个ASP.NET项目、用UseSpa()托管的遗留系统结果每次API升级都要重启整个前端服务用户正在上传文件时页面直接白屏。分离不是增加复杂度而是把可控的复杂度放在正确的位置。2.3 构建产物结构决定部署方式Vue CLI的dist目录不是“扔进去就完事”Vue CLI的dist目录结构直接决定了你在IIS里怎么建站。常见误区是认为“只要index.html能打开其他就OK”。错。我们来看一个标准npm run build后的dist目录dist/ ├── index.html ← SPA入口所有路由都靠它 ├── css/ │ └── app.xxx.css ← CSS文件含哈希值防缓存 ├── js/ │ ├── chunk-vendors.xxx.js ← 第三方库打包 │ └── app.xxx.js ← 业务代码打包 ├── img/ │ └── logo.png ← public目录下的静态资源 └── favicon.ico ← 默认图标关键点有三个index.html的script和link标签里的路径全是相对路径如/js/app.xxx.js这意味着它必须被Web服务器以根路径/提供。如果你把dist目录放到IIS的/myapp/子目录下而index.html里写的是/js/app.xxx.js浏览器就会去请求https://domain.com/js/app.xxx.js404而不是https://domain.com/myapp/js/app.xxx.js。解决方案只有两个要么改vue.config.js的publicPath为/myapp/要么在IIS里把/myapp/配置为网站根目录即物理路径指向dist。public目录下的文件如favicon.ico会原样复制到dist根目录它们不经过Webpack打包路径固定。所以public/favicon.ico→dist/favicon.ico访问时就是/favicon.ico。Vue Router的history模式依赖Web服务器重写规则。当用户访问/user/123时浏览器直接向服务器请求该路径。IIS默认没有该文件会返回404。正确做法是让IIS对所有非静态资源的请求即不存在.js/.css/.png等扩展名的请求全部重写到/index.html由Vue Router接管路由。这需要URL重写模块URL Rewrite Module和精准的规则配置后面会详解。3. 核心细节解析与实操要点IIS、Vue、ASP.NET三者的“握手协议”部署不是堆砌配置而是让三个系统达成一致的“握手协议”。下面拆解三个核心环节的实操细节每个点都来自真实踩坑记录。3.1 Vue端构建配置与环境变量的生死线Vue CLI的vue.config.js不是可有可无的配置文件它是连接开发与生产环境的唯一可信信道。很多部署问题根源就在这个文件没配对。// vue.config.js const isProduction process.env.NODE_ENV production module.exports { // 【关键1】publicPath决定所有静态资源的基准路径 // 开发时用 /生产部署到子目录必须改为 /subdir/ publicPath: isProduction ? /app/ : /, // 【关键2】outputDir构建产物输出目录必须与IIS物理路径一致 outputDir: dist, // 【关键3】assetsDir静态资源子目录影响CSS/JS引用路径 // 默认assets若IIS中需调整此处同步修改 assetsDir: static, // 【关键4】configureWebpack生产环境特有优化 configureWebpack: config { if (isProduction) { return { optimization: { splitChunks: { chunks: all, cacheGroups: { vendor: { name: chunk-vendors, test: /[\\/]node_modules[\\/]/, priority: 10, chunks: initial } } } } } } }, // 【关键5】devServer仅开发用但影响proxy配置逻辑 devServer: { port: 8080, proxy: { /api: { target: https://localhost:5001, // 对应ASP.NET Web API本地地址 changeOrigin: true, secure: false } } } }为什么publicPath设错会导致满盘皆输假设你部署到https://domain.com/myapp/但publicPath仍为/那么index.html里会生成link href/css/app.xxx.css relstylesheet script src/js/app.xxx.js/script浏览器请求https://domain.com/css/app.xxx.css→ 404。正确配置publicPath: /myapp/后生成link href/myapp/css/app.xxx.css relstylesheet script src/myapp/js/app.xxx.js/scriptIIS收到/myapp/css/app.xxx.css请求自然能找到dist/css/app.xxx.css。注意publicPath末尾必须带斜杠否则/myappcss/app.xxx.css会变成/myappcss/app.xxx.css。环境变量如何安全传递API地址不要在代码里硬编码axios.create({baseURL: https://api.domain.com})。用.env.production文件# .env.production VUE_APP_API_BASE_URLhttps://api.domain.com然后在src/utils/request.js中import axios from axios const service axios.create({ baseURL: process.env.VUE_APP_API_BASE_URL || /api/, // 开发时走proxy生产时用环境变量 timeout: 10000 })这样同一份代码通过不同.env文件就能切换API地址无需改代码。3.2 ASP.NET Web API端CORS、JWT、路由的三位一体配置ASP.NET Web API不是“写完Controller就完事”它必须主动声明自己愿意被谁调用、如何验证身份、如何暴露接口。尤其在前后端分离下这三个配置缺一不可。CORS配置不是加一行代码就完事.NET Core 3.1 的CORS配置必须严格遵循注册顺序和策略命名// Startup.cs public void ConfigureServices(IServiceCollection services) { // 【关键】先注册CORS服务再AddControllers services.AddCors(options { options.AddPolicy(AllowVueApp, builder { builder.WithOrigins(https://web.domain.com) // 生产前端域名 .AllowAnyMethod() .AllowAnyHeader() .WithCredentials(); // 若需携带Cookie或Authorization头 }); }); services.AddControllers(); // ... 其他服务 } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 【关键】CORS中间件必须在UseRouting()之后、UseEndpoints()之前 app.UseRouting(); app.UseCors(AllowVueApp); // 必须用注册时的策略名 app.UseAuthentication(); app.UseAuthorization(); app.UseEndpoints(endpoints { endpoints.MapControllers(); }); }为什么顺序错了就失效UseCors必须在UseRouting之后因为CORS需要读取路由信息判断是否匹配又必须在UseAuthentication之前因为CORS预检请求OPTIONS不带Token如果鉴权中间件先执行会直接返回401CORS头根本没机会写入响应。我亲眼见过一个项目把UseCors放在UseAuthentication后面结果前端所有请求都卡在OPTIONS预检控制台只显示CORS header ‘Access-Control-Allow-Origin’ missing查了三天才发现中间件顺序问题。JWT Token验证前端传的Token后端必须能验前后端分离下登录成功后前端拿到JWT后续所有请求都在Authorization头里带上Bearer token。ASP.NET必须配置JWT验证// Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options { options.TokenValidationParameters new TokenValidationParameters { ValidateIssuer true, ValidateAudience true, ValidateLifetime true, ValidateIssuerSigningKey true, ValidIssuer Configuration[Jwt:Issuer], ValidAudience Configuration[Jwt:Audience], IssuerSigningKey new SymmetricSecurityKey( Encoding.UTF8.GetBytes(Configuration[Jwt:Key])) }; }); services.AddAuthorization(); }关键点ValidIssuer和ValidAudience必须与前端生成Token时填写的一致通常在登录接口里用JwtSecurityTokenHandler创建IssuerSigningKey的密钥字符串必须与前端生成Token时用的密钥完全相同Base64编码或原始字符串需统一若前端用axios.defaults.headers.common[Authorization] Bearer token后端AddJwtBearer会自动提取并验证Web API路由别让MVC路由抢了API的饭碗如果你的ASP.NET项目同时用了MVC和Web API务必确认Controller的基类// 正确继承ControllerBase专用于API [ApiController] [Route(api/[controller])] public class ValuesController : ControllerBase { [HttpGet] public ActionResultIEnumerablestring Get() new string[] { value1, value2 }; } // 错误继承Controller会走MVC视图引擎 public class HomeController : Controller // 这个会尝试找View导致API返回HTML { public IActionResult Index() View(); // 不是API }ControllerBase不渲染视图只返回数据Controller会寻找View若找不到就返回空或404。部署时若发现/api/values返回空白页八成是Controller基类写错了。3.3 IIS端URL重写、MIME类型、应用程序池的底层控制IIS不是“把文件放进去就运行”它是Windows上最成熟的Web服务器但默认配置是为传统ASP.NET Web Forms设计的。Vue SPA需要它“放下身段”做三件事重写路由、识别新文件类型、正确加载.NET运行时。URL重写规则Vue Router history模式的生命线安装IIS URL Rewrite模块后在web.config中添加?xml version1.0 encodingUTF-8? configuration system.webServer rewrite rules !-- 【关键规则】将所有非静态资源请求重写到index.html -- rule nameVueRouter stopProcessingtrue match url.* / conditions logicalGroupingMatchAll !-- 排除真实存在的文件.js/.css/.png等 -- add input{REQUEST_FILENAME} matchTypeIsFile negatetrue / !-- 排除真实存在的目录 -- add input{REQUEST_FILENAME} matchTypeIsDirectory negatetrue / !-- 排除API请求避免把/api/xxx重写到index.html -- add input{REQUEST_URI} pattern^/api/ negatetrue / !-- 排除静态资源目录 -- add input{REQUEST_URI} pattern^/static/ negatetrue / /conditions action typeRewrite url/index.html / /rule /rules /rewrite !-- 【关键】静态文件MIME类型确保浏览器正确解析 -- staticContent remove fileExtension.woff / remove fileExtension.woff2 / remove fileExtension.ttf / remove fileExtension.eot / remove fileExtension.svg / mimeMap fileExtension.woff mimeTypeapplication/font-woff / mimeMap fileExtension.woff2 mimeTypeapplication/font-woff2 / mimeMap fileExtension.ttf mimeTypeapplication/octet-stream / mimeMap fileExtension.eot mimeTypeapplication/vnd.ms-fontobject / mimeMap fileExtension.svg mimeTypeimage/svgxml / /staticContent /system.webServer /configuration为什么这个规则必须精确stopProcessingtrue匹配后立即停止避免后续规则干扰negatetrue条件取反即“不是文件”且“不是目录”且“不是API路径”才重写pattern^/api/正则开头锚定防止/api/v1/users被误判为/api子串若漏掉remove和mimeMapIIS会返回404.3 - MIME type not supported浏览器无法加载字体或SVG应用程序池.NET版本与托管管道模式的致命组合IIS中ASP.NET Web API应用必须配置正确的应用程序池.NET CLR版本ASP.NET Core 3.1 →.NET Core不是.NET FrameworkASP.NET Framework Web API →.NET Framework v4.0托管管道模式ASP.NET Core →Integrated必须ASP.NET Framework →Integrated推荐或Classic兼容旧版注意一个应用程序池只能运行一种.NET版本。若你同时部署.NET Core API和.NET Framework后台管理必须创建两个独立应用程序池否则启动失败。默认文档让IIS知道该先打开哪个文件在IIS管理器中进入网站 → “默认文档”确保index.html排在第一位。否则访问https://domain.com/时IIS可能尝试找default.aspx或iisstart.htm返回空白页。手动添加index.html并上移至顶部即可。4. 实操过程与核心环节实现从本地构建到IIS上线的完整流水线现在我们把前面所有理论串成一条可执行的实操流水线。以下步骤基于Windows Server 2019 IIS 10 .NET Core 3.1环境每一步都标注了“为什么这么做”和“不这么做会怎样”。4.1 前端Vue构建与产物准备步骤1确认环境变量与构建命令在Vue项目根目录确保有.env.productionNODE_ENVproduction VUE_APP_API_BASE_URLhttps://api.domain.com执行构建npm install npm run build构建完成后检查dist目录结构是否完整特别关注index.html是否存在且内容正常打开浏览器本地双击应能运行js/和css/目录下是否有带哈希值的文件证明代码分割生效public/下的favicon.ico是否在dist/根目录步骤2验证构建产物的路径正确性用VS Code打开dist/index.html搜索script和link确认所有src和href属性以/app/开头若publicPath设为/app/。例如link href/app/css/app.xxx.css relstylesheet script src/app/js/app.xxx.js/script如果看到/css/或./js/说明vue.config.js的publicPath没生效需检查是否在process.env.NODE_ENV production分支里。步骤3本地模拟IIS环境测试安装http-server全局npm install -g http-server进入dist目录启动服务cd dist http-server -p 8080此时访问http://localhost:8080/app/注意路径应能正常打开Vue应用且所有路由如/app/user刷新不报404。若报404说明URL重写规则未生效需检查web.config是否已放入dist目录。4.2 后端ASP.NET Web API发布步骤1清理与发布在Visual Studio中右键Web API项目 → “发布” → 选择“IIS、FTP、Azure等” → “IIS” → “新建配置文件”。关键设置目标位置\\server\c$\inetpub\wwwroot\api\物理路径配置Release部署模式框架依赖型部署推荐服务器需装.NET Core Runtime目标运行时win-x64匹配服务器CPU架构点击“发布”VS会自动生成web.config和所有DLL文件到目标目录。步骤2验证API是否可访问在服务器上用浏览器访问http://localhost/api/values应返回JSON数组[value1,value2]。若返回404检查应用程序池是否启动且.NET版本正确web.config中aspNetCore节点的processPath是否指向正确的exe如dotnet.exestdoutLogEnabledtrue并检查logs目录下的日志常见错误如Failed to load assembly缺少依赖步骤3CORS与JWT联调验证用Postman发送请求GEThttp://localhost/api/values→ 应返回200及JSONPOSThttp://localhost/api/auth/login带用户名密码→ 应返回200及JWT TokenGEThttp://localhost/api/values带HeaderAuthorization: Bearer token→ 应返回200若第三步失败检查JWT密钥是否前后端一致、ValidIssuer/Audience是否匹配。4.3 IIS配置与最终联调步骤1创建前端网站打开IIS管理器 → “网站” → “添加网站”网站名称vue-app物理路径C:\inetpub\wwwroot\app\即Vuedist目录绑定https主机名留空或填web.domain.comSSL端口443应用程序池新建一个.NET CLR版本选No Managed Code纯静态站点步骤2创建后端应用在IIS中右键刚建的vue-app网站 → “添加应用程序”别名api物理路径C:\inetpub\wwwroot\api\即ASP.NET发布目录应用程序池新建一个.NET CLR版本选.NET Core托管管道模式Integrated步骤3配置URL重写与MIME类型将前面写的web.config文件复制到C:\inetpub\wwwroot\app\目录下。确保IIS已安装URL Rewrite模块若未安装从微软官网下载安装。步骤4最终联调与问题定位访问https://web.domain.com/app/打开浏览器开发者工具F12→ Network标签页检查index.html、/app/js/app.xxx.js等静态资源是否200GET /api/values是否200Response Headers中是否有Access-Control-Allow-Origin: https://web.domain.com登录后POST /api/auth/login返回的Token是否被前端正确存储后续请求的Request Headers中是否有Authorization: Bearer token若某一步失败按此顺序排查浏览器Console是否有JS错误如axios is not definedNetwork中对应请求的状态码和Response内容IIS日志C:\inetpub\logs\LogFiles\W3SVC1\中是否有500错误ASP.NETlogs目录下的stdout日志5. 常见问题与排查技巧实录那些让你凌晨三点还在看日志的坑部署问题千奇百怪但90%集中在几个高频场景。我把近三年遇到的真实案例整理成速查表并附上独家排查技巧。5.1 静态资源404不是文件丢了是路径错了现象可能原因排查技巧解决方案GET /js/app.xxx.js 404publicPath未设为子目录路径在dist/index.html中搜索app.xxx.js看src属性值修改vue.config.js的publicPath重新npm run buildGET /app/css/app.xxx.css 404IIS物理路径未指向dist目录而是指向dist的父目录在IIS中右键网站 → “探索”看打开的文件夹是否含index.html在IIS中修改网站“物理路径”为C:\path\to\distGET /favicon.ico 404web.config中MIME类型未配置.ico在IIS中网站 → “MIME类型”搜索.ico是否存在在web.config的staticContent中添加mimeMap fileExtension.ico mimeTypeimage/x-icon /独家技巧用IIS的“失败请求跟踪”定位404在IIS中网站 → “失败请求跟踪规则” → 启用状态码404的跟踪。重现404请求后打开C:\inetpub\logs\FailedReqLogFiles\下的XML日志查看MODULE_SET_RESPONSE_STATUS_FROM_CACHE节点能精准定位是哪个模块StaticFileModule还是AspNetCoreModule返回了404。5.2 API请求跨域失败CORS不是开关是协议现象可能原因排查技巧解决方案浏览器Console报CORS header ‘Access-Control-Allow-Origin’ missingCORS中间件未启用或策略名不匹配在ASP.NETStartup.cs中app.UseCors(xxx)的xxx是否与AddPolicy(xxx)一致统一策略名确保UseCors在UseRouting后、UseAuthentication前OPTIONS /api/values 204但后续GET仍失败WithCredentials()未开启但前端withCredentialstrue检查前端axios是否设置了withCredentials: true前后端同步开启后端WithCredentials()前端axios.defaults.withCredentials truePOST /api/login 400且无响应体ASP.NET Model Binding失败如DTO属性名与前端JSON字段名不一致在Controller方法参数上加[FromBody]并在方法内try-catch捕获ModelState.IsValid使用[JsonPropertyName(username)]特性标注DTO属性或前端确保字段名与C#属性驼峰一致独家技巧用curl绕过浏览器CORS限制验证API在服务器上执行curl -H Origin: https://web.domain.com -H Access-Control-Request-Method: GET -X OPTIONS https://localhost/api/values若返回200且Headers含Access-Control-Allow-Origin证明CORS配置正确若返回404或无CORS头说明ASP.NET配置有问题。5.3 Vue Router刷新404不是Vue错了是IIS没听话现象可能原因排查技巧解决方案访问https://domain.com/app/user返回IIS 404URL重写规则未生效或web.config未放在dist目录在IIS中网站 → “处理程序映射”确认UrlRoutingModule-4.0是否启用确保web.config在dist目录且IIS已安装URL Rewrite模块https://domain.com/app/user返回空白页Network中index.html200但无JS加载index.html中script路径错误指向了/js/而非/app/js/查看dist/index.html源码确认script src的路径重新npm run build确保vue.config.js的publicPath正确刷新后登录态丢失JWT Token存在localStorage但axios未在每次请求自动携带在src/utils/request.js中检查service.interceptors.request.use是否设置了Token添加拦截器config.headers.Authorization Bearer localStorage.getItem(token)独家技巧用IIS的“重写规则测试”功能验证规则在IIS中网站 → “URL重写” → 右侧“测试规则”输入URL如/app/user选择规则VueRouter点击“测试”。若显示“匹配”则规则生效若显示“不匹配”检查conditions中的正则表达式是否写错。5.4 Token验证失败密钥、时间、颁发者一个都不能少现象可能原因排查技巧解决方案Authorization: Bearer xxx返回401 UnauthorizedJWT密钥前后端不一致在ASP.NET中Console.WriteLine(Key: Configuration[Jwt:Key]);与前端对比统一密钥建议用环境变量注入避免硬编码401且日志报IDX10223: Lifetime validation failedToken过期时间exp已到或服务器时间与客户端偏差大在JWT官网https://jwt.io粘贴Token查看exp时间戳换算为北京时间同步服务器与客户端时间或延长Token有效期如2小时401且日志报IDX10205: Issuer validation failedValidIssuer与Token中iss字段不匹配解码Token查看iss字段值与Configuration[Jwt:Issuer]对比确保登录接口生成Token时new JwtSecurityToken(issuer: https://api.domain.com, ...)中的issuer与后端配置一致独家技巧用Postman模拟Token验证全流程POST /api/auth/login获取Token复制Token用https://jwt.io验证其payload是否含iss、aud、expGET /api/valuesHeader加Authorization: Bearer token若第3步失败对比jwt.io显示的iss与后端ValidIssuer一字不差才算匹配。我在实际项目中发现最常被忽略的是时间同步。有一次生产环境Token总是秒过期查了两天最后发现服务器BIOS电池没电系统时间比真实时间慢了3分钟。给服务器换电池后问题消失。所以部署前务必执行w32tm /resync同步时间。最后再分享一个小技巧Vue项目上线后如果用户反馈“页面白屏”第一时间不是看代码而是打开浏览器开发者工具切换到Application标签页点击“Clear storage” →