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

Swift中如何使用字符串格式证书发起REST API POST请求

解决带PEM格式客户端证书的POST请求问题

你的核心问题是PEM格式的证书字符串包含非Base64内容,导致解码失败。以下是完整的解决步骤:

1. 清理PEM证书字符串

PEM证书里的-----BEGIN CERTIFICATE-----、-----END CERTIFICATE-----标记和换行符都不属于Base64编码内容,必须先移除:

let rawPemString = """
-----BEGIN CERTIFICATE-----

MIID9jCCAt6gAwIBAgIQNwHqBnL+445eqCUKVWroxDANBgkqhkiG9w0BAQsFADCB

XufZCQ4mDV3MU0z+wsS4alR7b410V5Wet36pjUkrWtHEI2dBWZFzCOay19Vpb2V2

0M/zl07YpoZYxw==

-----END CERTIFICATE-----
"""

// 清理无关内容,只保留纯Base64字符串
let cleanedCertString = rawPemString
    .replacingOccurrences(of: "-----BEGIN CERTIFICATE-----", with: "")
    .replacingOccurrences(of: "-----END CERTIFICATE-----", with: "")
    .replacingOccurrences(of: "\n", with: "")
    .trimmingCharacters(in: .whitespacesAndNewlines)

2. 将清理后的字符串转为Data

现在可以正常进行Base64解码:

guard let certData = Data(base64Encoded: cleanedCertString) else {
    // 替换为你的错误处理逻辑
    print("证书Base64解码失败")
    return
}

3. 创建SecCertificate对象

用解码后的Data生成系统可识别的证书对象:

guard let clientCert = SecCertificateCreateWithData(nil, certData as CFData) else {
    print("生成SecCertificate失败")
    return
}

4. 配置URLSession以使用客户端证书

需要自定义代理处理服务器的证书验证请求,提供客户端证书:

class CertAuthDelegate: NSObject, URLSessionDelegate {
    private let clientCertificate: SecCertificate
    
    init(cert: SecCertificate) {
        self.clientCertificate = cert
        super.init()
    }
    
    func urlSession(_ session: URLSession, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
        // 仅处理客户端证书验证挑战
        guard challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodClientCertificate else {
            completionHandler(.performDefaultHandling, nil)
            return
        }
        
        // 创建包含客户端证书的凭证
        let credential = URLCredential(
            certificate: clientCertificate,
            persistent: false
        )
        completionHandler(.useCredential, credential)
    }
}

5. 发起POST请求

用配置好的URLSession发送请求:

// 初始化代理和Session
let authDelegate = CertAuthDelegate(cert: clientCert)
let session = URLSession(configuration: .default, delegate: authDelegate, delegateQueue: .main)

// 构建请求
guard let endpointURL = URL(string: "https://your-target-endpoint.com") else {
    print("无效的端点URL")
    return
}

var postRequest = URLRequest(url: endpointURL)
postRequest.httpMethod = "POST"
postRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")

// 设置请求体(根据实际需求调整)
let requestBody = ["param1": "value1", "param2": "value2"]
do {
    postRequest.httpBody = try JSONSerialization.data(withJSONObject: requestBody)
} catch {
    print("构建请求体失败:\(error)")
    return
}

// 发送请求
let task = session.dataTask(with: postRequest) { data, response, error in
    if let error = error {
        print("请求出错:\(error.localizedDescription)")
        return
    }
    
    guard let httpResp = response as? HTTPURLResponse, (200...299).contains(httpResp.statusCode) else {
        print("请求返回错误状态码")
        return
    }
    
    if let responseData = data, let respString = String(data: responseData, encoding: .utf8) {
        print("请求成功,返回内容:\(respString)")
    }
}

task.resume()

额外说明

  • 如果证书链包含多个证书(如客户端证书+中间证书),需要分别清理每个证书字符串,生成对应的SecCertificate数组,然后用URLCredential(certificates: [clientCert, intermediateCert], persistent: false)创建凭证
  • 替换代码中的端点URL、请求体内容为实际业务数据
  • 上线代码请替换示例中的print为正式的错误处理逻辑

内容的提问来源于stack exchange,提问作者Azeem Muzammil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 02:45:17