You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Alamofire 4和OAuth2在Swift中发起POST请求时遇401错误

解决Reddit Application Only OAuth的401 Unauthorized问题

先给你捋清楚两个问题的优先级:你看到的CredStore - performQuery - Error copying matching creds. Error=-25300其实是系统钥匙串的一个警告,和你的授权失败没有直接关系——很多开发者用Alamofire请求HTTPS接口时都会碰到它,不用太在意,咱们重点解决导致401的核心问题。

你的代码里有几个关键错误,我帮你逐个拆解修正:

1. Grant Type 匹配错误

你采用的是Application Only OAuth模式,对应的grant_type必须是client_credentials,但你代码里用的https://oauth.reddit.com/grants/installed_clientInstalled App类型的授权参数,完全不匹配当前模式。

2. Basic认证字符串格式错误

Basic认证的规则是把客户端ID:密码(注意中间的冒号分隔符)转成Base64编码,你代码里写的String(format: "%@%@", username, password)少了关键的冒号,导致认证信息完全无效,这是401的核心原因之一。

3. 请求编码方式错误

Reddit的access_token接口要求用表单格式(application/x-www-form-urlencoded)提交参数,但你用了JSONEncoding.default,这会让服务端无法正确解析你的请求参数。

4. 多余参数干扰

Application Only OAuth不需要device_id参数,这个参数是给Installed App授权模式用的,直接删掉即可。

修正后的完整请求代码

把你AppDelegate里的请求部分替换成下面这段:

guard let url = URL(string: "https://www.reddit.com/api/v1/access_token") else { return false }

// Application Only OAuth仅需指定grant_type参数
let params: Parameters = [
    "grant_type": "client_credentials"
]

let username = "MY_CLIENT_ID"
let password = ""
// 注意添加客户端ID和密码之间的冒号
let loginString = String(format: "%@:%@", username, password)
guard let loginData = loginString.data(using: .utf8) else { return false }
let base64EncodedString = loginData.base64EncodedString()

let headers = ["Authorization": "Basic \(base64EncodedString)"]

// 使用URLEncoding.default适配表单提交要求
Alamofire.request(url, method: .post, parameters: params, encoding: URLEncoding.default, headers: headers).responseJSON { response in
    print(response)
}

最后再确认两个配置细节:

  • 你的Reddit开发者后台里,应用类型是不是设置成了Script?Application Only OAuth仅支持Script或Web App类型的应用;
  • 重定向URI是不是和你Info.plist里配置的APP_SCHEME完全一致?比如your-app-scheme://callback,确保授权后能正确跳转回应用。

这样修改后就能正常获取到access token了。

内容的提问来源于stack exchange,提问作者Garret Koontz

火山引擎 最新活动