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

AngularJS请求外部API获取Token返回400错误(unsupported_grant_type)

解决AngularJS调用外部API获取Token时返回400 (unsupported_grant_type)的问题

你的问题核心在于请求体中的参数分隔符使用了HTML实体&而非标准的&,导致外部API的OAuth认证中间件无法正确解析grant_type参数,从而抛出unsupported_grant_type错误。

问题分析

虽然你的本地登录代码也用了&并能成功,但这大概率是因为本地ASP.NET Web API的中间件自动兼容了HTML实体转义;而外部API的认证逻辑没有处理这种情况,严格遵循x-www-form-urlencoded格式要求——参数必须用&分隔,而非转义后的&。

对比Postman的请求体(标准格式:grant_type=password&username=xxx&password=xxx)和你AngularJS代码发送的请求体(grant_type=password&username=xxx&password=xxx),就能看到明显差异。

解决方案

方案1:直接修复参数拼接的分隔符

把手动拼接字符串中的&替换成普通的&:

var _transferPersoon = function (portal, data) {
    var externalAPI = "";
    if (portal == "portal1") {
        externalAPI = "https://urltoportal/webapi/";
    } else if (portal == "portal2") {
        externalAPI = "https://urltoportal/webapi/";
    } else if (portal == "portal3") {
        externalAPI = "https://urltoportal/webapi/";
    } else if (portal == "portal4") {
        externalAPI = "https://urltoportal/webapi/";
    } else {
        externalAPI = serviceBase;
    }
    // 修复分隔符为&,而非&
    var data = ["grant_type=password&username=", "transferaccount", "&password=", "password"].join('');
    return $http.post([externalAPI, "token"].join(''), data, {
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    }).then(function (response) {
        return response.data.access_token;
    })
}

注意:建议用then()替代已废弃的success()/error()方法,AngularJS 1.6+推荐使用标准Promise语法。

方案2:使用AngularJS内置序列化工具(更可靠)

手动拼接字符串容易出错,推荐使用$httpParamSerializerJQLike来自动序列化参数对象,它会严格按照x-www-form-urlencoded格式生成请求体:

// 记得在服务中注入$httpParamSerializerJQLike
var _transferPersoon = function (portal, data) {
    var externalAPI = "";
    if (portal == "portal1") {
        externalAPI = "https://urltoportal/webapi/";
    } else if (portal == "portal2") {
        externalAPI = "https://urltoportal/webapi/";
    } else if (portal == "portal3") {
        externalAPI = "https://urltoportal/webapi/";
    } else if (portal == "portal4") {
        externalAPI = "https://urltoportal/webapi/";
    } else {
        externalAPI = serviceBase;
    }
    var tokenParams = {
        grant_type: "password",
        username: "transferaccount",
        password: "password"
    };
    return $http.post([externalAPI, "token"].join(''), $httpParamSerializerJQLike(tokenParams), {
        headers: { "Content-Type": "application/x-www-form-urlencoded" }
    }).then(function (response) {
        return response.data.access_token;
    })
}

验证方法

修改后,打开浏览器开发者工具的Network面板,查看请求的Form Data或Request Payload,确认参数格式和Postman发送的完全一致,即可解决问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:26:01