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

Swift向.NET Core发起POST请求失败,返回未授权问题排查

问题分析与解决方案

一、getInfo接口POST请求未授权问题

核心原因

.NET Core对简单类型参数(string、int等)的默认绑定规则:

  • GET请求:自动从URL的Query String读取参数
  • POST请求:默认从Form表单(application/x-www-form-urlencoded)或Query String读取,不会自动解析JSON请求体

你当前的Swift代码是把参数放在JSON请求体中发送,但后端getInfo方法的参数没有添加[FromBody]特性,导致后端无法获取到authToken等参数,进而触发未授权错误。

解决办法

方案1:修改后端代码(优先推荐,若允许修改)

将参数封装为模型类,并添加[FromBody]特性:

[HttpGet, HttpPost]
public async Task<ActionResult<string>> getInfo([FromBody] GetInfoRequest model)
{
    // 使用model.Number、model.AuthToken、model.ProfileName进行逻辑处理
}

// 定义请求模型
public class GetInfoRequest
{
    public string Number { get; set; }
    public string AuthToken { get; set; }
    public string ProfileName { get; set; }
}

方案2:修改Swift代码(无法修改后端时使用)

两种可选方式:

方式A:参数拼入URL的Query String(和GET请求一致)
var components = URLComponents(string: fullURL)!
components.queryItems = [
    URLQueryItem(name: "number", value: number),
    URLQueryItem(name: "authToken", value: authToken),
    URLQueryItem(name: "profileName", value: profileName)
]
var request = URLRequest(url: components.url!)
request.httpMethod = "POST"
方式B:用application/x-www-form-urlencoded格式发送参数
let params = [
    "number": number,
    "authToken": authToken,
    "profileName": profileName
]
// 编码为表单格式字符串
let queryString = params.map { 
    "\($0.key)=\($0.value.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)"
}.joined(separator: "&")

var request = URLRequest(url: URL(string: fullURL)!)
request.httpMethod = "POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpBody = queryString.data(using: .utf8)

二、uploadImage接口调用方案

由于接口包含List<IFormFile>类型参数,必须使用multipart/form-data格式发送请求,不能用JSON。Swift代码实现如下:

func uploadImage(files: [URL], 
                 authToken: String, 
                 number: String, 
                 profileName: String, 
                 profileNum: Int, 
                 id: String, 
                 fullURL: String) {
    
    var request = URLRequest(url: URL(string: fullURL)!)
    request.httpMethod = "POST"
    
    // 生成multipart边界标识
    let boundary = "Boundary-\(UUID().uuidString)"
    request.addValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
    
    var body = Data()
    
    // 添加文本参数
    let textParams = [
        "authToken": authToken,
        "number": number,
        "profileName": profileName,
        "profileNum": String(profileNum),
        "ID": id
    ]
    for (key, value) in textParams {
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n".data(using: .utf8)!)
        body.append("\(value)\r\n".data(using: .utf8)!)
    }
    
    // 添加文件(此处以图片为例,需根据实际文件类型修改Content-Type)
    for fileURL in files {
        let fileName = fileURL.lastPathComponent
        guard let fileData = try? Data(contentsOf: fileURL) else { continue }
        
        body.append("--\(boundary)\r\n".data(using: .utf8)!)
        body.append("Content-Disposition: form-data; name=\"files\"; filename=\"\(fileName)\"\r\n".data(using: .utf8)!)
        body.append("Content-Type: image/jpeg\r\n\r\n".data(using: .utf8)!)
        body.append(fileData)
        body.append("\r\n".data(using: .utf8)!)
    }
    
    // 结束multipart边界
    body.append("--\(boundary)--\r\n".data(using: .utf8)!)
    
    request.httpBody = body
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
        // 此处处理接口响应
    }
    task.resume()
}

额外注意事项

  1. 确保参数名大小写与后端完全一致(比如后端是authToken,不要写成authtoken)
  2. 若后端还有其他Header级别的授权验证(如JWT的Bearer Token),需补充对应的Header:
    request.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization")
    
  3. 上传文件时,Content-Type需匹配实际文件类型(如image/png、application/pdf等)

内容的提问来源于stack exchange,提问作者Brandon Bravos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 08:45:46