Postman可正常请求的Bearer Token认证,Swift App返回401问题排查
问题:Swift App中Bearer Token认证返回401,Postman可正常访问
我用Vapor搭建了服务器,采用Bearer Token认证机制。已经成功登录获取到Token,在Postman中使用该Token能正常访问受保护的/residents路由并得到Resident数组响应,但在Swift App中发起请求却返回401未授权。
我的App请求代码如下:
func getResidents() async throws -> [Resident] { let session = URLSession.shared var request = URLRequest(url: URL(string: "\(API.url)/residents")!) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("Bearer \(token?.value)", forHTTPHeaderField: "Authorization") // 发起请求 let (data, response) = try await session.data(for: request) print(response) // 验证响应状态码 guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else { throw GetResidentsError.unableToGetResidents } print(httpResponse.statusCode) let decoder = JSONDecoder() let residents = try decoder.decode([Resident].self, from: data) print(residents) return residents }
Postman中配置Bearer Token的GET请求可正常通过认证(请求头的Authorization字段格式为Bearer [有效Token])。
排查与解决
核心问题:可选值拼接导致Authorization头格式错误
代码中"Bearer \(token?.value)"的写法存在问题:
- 当
token为nil时,会生成Bearer nil的无效认证头; - 即使
token不为nil,字符串插值对可选值的处理可能引入不必要的格式问题。
修复代码
先确保token及其value存在,再生成正确的Authorization头:
func getResidents() async throws -> [Resident] { let session = URLSession.shared guard let url = URL(string: "\(API.url)/residents") else { throw GetResidentsError.invalidURL } var request = URLRequest(url: url) request.httpMethod = "GET" request.setValue("application/json", forHTTPHeaderField: "Content-Type") // 先解包token,避免可选值问题 guard let tokenValue = token?.value else { throw GetResidentsError.missingToken } request.setValue("Bearer \(tokenValue)", forHTTPHeaderField: "Authorization") let (data, response) = try await session.data(for: request) guard let httpResponse = response as? HTTPURLResponse else { throw GetResidentsError.invalidResponse } print("响应状态码:\(httpResponse.statusCode)") guard httpResponse.statusCode == 200 else { throw GetResidentsError.unableToGetResidents } let decoder = JSONDecoder() let residents = try decoder.decode([Resident].self, from: data) return residents }
额外排查点
- Token一致性:确认
tokenValue和Postman中使用的Token完全一致,无空格、换行或大小写差异; - URL正确性:检查请求URL是否和Postman中的完全相同,包括协议(HTTP/HTTPS)、路径拼写;
- 打印验证:添加打印语句确认最终的Authorization头格式:
print("Authorization头:\(request.value(forHTTPHeaderField: "Authorization") ?? "无认证头")")
内容的提问来源于stack exchange,提问作者AFinch
相关产品推荐
相关产品推荐

