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() }
额外注意事项
- 确保参数名大小写与后端完全一致(比如后端是
authToken,不要写成authtoken) - 若后端还有其他Header级别的授权验证(如JWT的Bearer Token),需补充对应的Header:
request.addValue("Bearer \(authToken)", forHTTPHeaderField: "Authorization") - 上传文件时,
Content-Type需匹配实际文件类型(如image/png、application/pdf等)
内容的提问来源于stack exchange,提问作者Brandon Bravos
相关产品推荐
相关产品推荐

