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

iOS Swift使用URLSessionWebSocketTask对接Vapor时如何设置服务端session.data

解决方案

Vapor的session.data依赖请求携带的vapor_session Cookie识别用户会话,你可以通过以下两种方式从iOS端设置对应值:


方案1:WebSocket握手时携带查询参数(适合非敏感数据)

iOS端修改

将需要存入session的参数拼接到WebSocket请求的URL上,注意对值做URL编码:

func connect(completion: @escaping ()->() = { }) {
    guard webSocketTask == nil else { return }

    self.username = "Name"
    self.userID = UUID().uuidString

    // 拼接查询参数
    var urlComponents = URLComponents(string: "ws://localhost:8080/connect")!
    urlComponents.queryItems = [
        URLQueryItem(name: "nickname", value: username),
        URLQueryItem(name: "data", value: userID) // 替换为你要传的自定义数据
    ]
    guard let url = urlComponents.url else { return }
    
    webSocketTask = URLSession.shared.webSocketTask(with: url)
    webSocketTask?.receive(completionHandler: onReceive)
    webSocketTask?.resume()
}

Vapor端修改

握手时先读取URL参数写入session,再读取使用:

app.webSocket("connect") { request, ws in
    let controller = Controller()
    // 读取查询参数写入session
    if let nickname = try? request.query.get(String.self, at: "nickname") {
        request.session.data["nickname"] = nickname
    }
    if let customData = try? request.query.get(String.self, at: "data") {
        request.session.data["data"] = customData
    }
    // 现在就能读取到设置的值了
    let userName = request.session.data["nickname"] ?? "Unknown user"
    let data = request.session.data["data"] ?? "Empty Data"

    controller.addUser(userName, with: room, withConnection: ws)
    // 后续逻辑
}

方案2:先发起普通HTTP请求设置Session(适合敏感数据)

如果参数比较敏感不适合放在URL中,可以先调用一个普通HTTP接口完成session设置,再发起WebSocket连接,URLSession会自动存储和携带session cookie。

iOS端流程

// 第一步:先调用接口设置session
func preSetSessionThenConnect() {
    guard let url = URL(string: "http://localhost:8080/set-session") else { return }
    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    let body = ["nickname": "Name", "data": UUID().uuidString]
    request.httpBody = try? JSONEncoder().encode(body)
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    
    URLSession.shared.dataTask(with: request) { [weak self] _, _, _ in
        DispatchQueue.main.async {
            // 第二步:session设置完成后再连接WebSocket
            self?.connect()
        }
    }.resume()
}

// 原有connect方法无需修改参数
func connect(completion: @escaping ()->() = { }) {
    guard webSocketTask == nil else { return }
    let url = URL(string: "ws://localhost:8080/connect")!
    webSocketTask = URLSession.shared.webSocketTask(with: url)
    webSocketTask?.receive(completionHandler: onReceive)
    webSocketTask?.resume()
}

Vapor端新增接口+原有逻辑不变

// 新增设置session的POST接口
app.post("set-session") { request -> HTTPStatus in
    struct SessionParam: Content {
        let nickname: String
        let data: String
    }
    let param = try request.content.decode(SessionParam.self)
    request.session.data["nickname"] = param.nickname
    request.session.data["data"] = param.data
    return .ok
}

// 原有WebSocket逻辑无需修改
app.webSocket("connect") { request, ws in
    let controller = Controller()
    // 直接读取之前设置的session值即可
    let userName = request.session.data["nickname"] ?? "Unknown user"
    let data = request.session.data["data"] ?? "Empty Data"
    controller.addUser(userName, with: room, withConnection: ws)
    // 后续逻辑
}

注意事项

  • 确保Vapor项目已经开启Session中间件,Configure.swift中需要存在配置:app.middleware.use(app.sessions.middleware)
  • 不要修改URLSession的默认Cookie策略,否则会导致Session Cookie无法自动携带
  • 开发环境下Vapor默认使用内存存储Session,生产环境建议切换为Redis驱动避免数据丢失

内容的提问来源于stack exchange,提问作者George Heints

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 15:45:06