向Akamai服务器发送多令牌HTTP请求时遇400授权头缺失错误
看起来你在调用Akamai的CCU缓存失效API时遇到了认证相关的问题,我来帮你拆解一下代码里的问题点,以及给出可行的解决方案:
核心问题分析
你的代码里有几个关键错误,直接导致了400错误:
1. JSONP不支持自定义请求头
你设置了dataType: 'jsonp',但JSONP是通过动态创建<script>标签实现跨域请求的,这种方式完全无法携带自定义HTTP请求头——包括你在beforeSend里设置的Authorization头,这就是服务器返回"Authorization Header Missing"的直接原因。
2. 请求方法不符合API规范
Akamai CCU v3的/invalidate/url/production接口要求使用POST请求,你当前用的type: 'get'不符合API要求,而且GET请求也无法正确提交缓存失效的URL列表。
3. 认证方式错误
Akamai API使用的是EdgeGrid认证协议,不是简单地把client_secret、access_token塞进请求头或者Authorization头里就能通过的。它需要根据请求内容(方法、路径、时间戳、随机数等)生成加密签名,最终的Authorization头格式应该是:
EG1-HMAC-SHA256 client_token=<你的token>,access_token=<你的token>,timestamp=<时间戳>,nonce=<随机数>,signature=<生成的签名>
4. 请求数据格式错误
你当前data里传的username和password不是CCU API需要的参数,API要求的请求体是包含objects数组(要失效的URL列表)和可选note字段的JSON结构。
解决方案
最佳实践:后端代理请求(推荐)
前端直接处理EdgeGrid认证会暴露client_secret等敏感信息,非常不安全。正确的做法是通过自己的后端服务代理请求,后端用Akamai官方SDK处理认证逻辑。
示例:Node.js后端代理
首先安装Akamai EdgeGrid SDK:
npm install akamai-edgegrid express
然后编写代理接口:
const express = require('express'); const EdgeGrid = require('akamai-edgegrid'); const app = express(); app.use(express.json()); // 配置Akamai认证信息 const eg = new EdgeGrid({ client_token: '你的client_token', client_secret: '你的client_secret', access_token: '你的access_token', host: '你的Akamai主机地址(比如xxxx.luna.akamaiapis.net)' }); // 前端调用的代理接口 app.post('/api/akamai/invalidate', (req, res) => { const { objects, note } = req.body; eg.auth({ path: '/ccu/v3/invalidate/url/production', method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ objects, note }) }); eg.send((error, response, body) => { if (error) { res.status(500).json({ error: error.message }); } else { res.status(response.statusCode).json(JSON.parse(body)); } }); }); app.listen(3000, () => console.log('代理服务运行在3000端口'));
前端修改后的代码
$(document).ready(function() { $("#test").click(function() { var request = $.ajax({ url: '/api/akamai/invalidate', // 指向自己的后端代理接口 cache: false, data: JSON.stringify({ objects: ["https://你的域名.com/需要失效的路径"], // 替换为实际要失效的URL note: "前端发起的缓存失效测试" }), contentType: 'application/json; charset=utf-8', type: 'POST' }); request.done(function(output) { // Akamai CCU返回的成功状态是"accepted",不是"success" if (output.status === 'accepted') { $("#nachricht").text("请求已接受,Akamai正在处理缓存失效"); } else { $("#nachricht").text(`处理失败: ${output.detail}`); } }); request.fail(function(jqXHR, textStatus) { $("#nachricht").text(`网络错误: ${textStatus}`); }); }); });
前端直接处理(不推荐,仅用于测试)
如果只是临时测试,可以使用浏览器版的EdgeGrid库,但注意不要在生产环境暴露敏感信息:
$(document).ready(function() { $("#test").click(function() { // 初始化EdgeGrid认证 const eg = new EdgeGrid({ clientToken: '你的client_token', clientSecret: '你的client_secret', accessToken: '你的access_token', baseUri: 'https://你的Akamai主机地址' }); const invalidationData = { objects: ["https://你的域名.com/需要失效的路径"], note: "测试缓存失效" }; // 生成认证头 eg.auth({ path: '/ccu/v3/invalidate/url/production', method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(invalidationData) }); // 发送请求 $.ajax({ url: `${eg.baseUri}/ccu/v3/invalidate/url/production`, type: 'POST', headers: eg.headers, data: JSON.stringify(invalidationData), contentType: 'application/json; charset=utf-8', crossDomain: true // 需要Akamai允许你的域名跨域 }).done(function(output) { if (output.status === 'accepted') { $("#nachricht").text("请求已接受"); } else { $("#nachricht").text(`失败: ${output.detail}`); } }).fail(function(jqXHR, textStatus) { $("#nachricht").text(`网络错误: ${textStatus}`); }); }); });
内容的提问来源于stack exchange,提问作者Hamza Alsancak

