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
相关产品推荐
相关产品推荐

