Kong配置key-auth插件后静态CSS/JS加载报401未授权问题
问题根因
浏览器加载页面内引用的CSS、JS、图片等静态资源属于被动发起的子资源请求,默认只会自动携带Cookie、同域基础请求头,不会主动将用户持有的api-key加入请求头,这类请求到达网关后会被key-auth插件直接拦截返回401,和主页面主动携带key可正常访问的逻辑不冲突。
解决方案
按改造成本从低到高、稳定性从高到低排序:
方案1:网关/代理层对静态资源做服务级放行(最推荐)
静态资源本身属于公开可访问的非敏感内容,不需要做用户级鉴权,直接在流量入口层给这类请求统一注入合法服务凭证即可,完全不用改前端代码,没有浏览器兼容问题:
- 如果鉴权逻辑在Nginx层实现:匹配所有静态资源路径,转发时自动注入有效api-key到请求头,参考配置:
# 匹配所有常见静态资源后缀 location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot|map)$ { # 转发到上游时自动注入提前生成的、仅用于静态资源访问的有效api-key proxy_set_header apikey "替换为你的静态资源专用固定api-key"; # 保留原有反向代理配置 proxy_pass http://your_backend_upstream; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } # 动态接口/主页面路径走原有鉴权逻辑,要求请求方自带合法用户级api-key location / { # 不自动注入key,未携带有效key的请求会被拦截返回401 proxy_pass http://your_backend_upstream; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; }
- 如果鉴权逻辑直接在Kong层实现:单独给静态资源路径创建匹配路由,给该路由配置key-auth插件时开启匿名访问,绑定一个仅授予静态资源访问权限的消费者即可,不需要额外注入请求头。
方案2:Cookie传key适配浏览器自动携带逻辑
如果需要对静态资源也做用户级鉴权,可以调整key-auth插件的读取规则,支持从Cookie中获取api-key:
- 修改key-auth插件配置,将密钥读取位置增加Cookie字段
- 用户首次访问主页面校验api-key合法后,由代理层给响应种下
apikey=对应用户有效key的Cookie,设置作用域为全站根路径 - 后续浏览器发起所有同域子资源请求时会自动携带该Cookie,网关即可正常校验通过
注意:该方案必须给Cookie配置HttpOnly、Secure(HTTPS环境下)、SameSite属性,避免密钥被XSS攻击窃取,安全性低于方案1。
方案3:前端动态加载静态资源并注入鉴权头
如果不想调整网关配置,也可以改造前端代码,手动控制所有静态资源的请求逻辑:
- 将用户的api-key统一存在全局变量或本地存储中
- 废弃原生的
<link>、<script>静态资源引入方式,通过fetch/XMLHttpRequest发起资源请求时手动带上apikey请求头,拿到资源内容后再动态插入到页面中
参考原生JS加载CSS的示例代码:
async function loadCss(url) { const res = await fetch(url, { headers: { "apikey": localStorage.getItem("user_api_key") } }); const cssText = await res.text(); const style = document.createElement('style'); style.textContent = cssText; document.head.appendChild(style); } // 调用加载目标CSS loadCss("myapp/r2/docs/stylesheets/library.css")
注意:该方案改造成本高,资源多的场景下会增加页面逻辑复杂度,仅适合小型单页应用临时使用。
避坑提醒
不要尝试在
<link>、<script>这类原生HTML标签上通过属性添加自定义请求头,浏览器标准不支持这类操作,所有声称可以直接在标签上配置api-key的方法都无效。
内容的提问来源于stack exchange,提问作者Danubio
相关产品推荐
相关产品推荐

