Ios Swift NIO安全websocket服务器

Ios Swift NIO安全websocket服务器,ios,swift,websocket,server,swift-nio,Ios,Swift,Websocket,Server,Swift Nio,我正在尝试在我的iOS应用程序中创建websocket服务器和客户端,在这里的示例实现的帮助下,我成功地做到了这一点。()-所以当前的工作情况是,我在应用程序启动时运行websocket服务器,然后将客户端加载到可以连接到它的webview中 现在我的问题是我希望我的服务器是安全的websocket服务器(基本上是从HTTPS html页面连接到websocket服务器) 我是网络编程新手,至少可以说Swift nio文档是缺乏的。据我所知,我可以使用() 我找到了这个线程,这正是我所需要的--

我正在尝试在我的iOS应用程序中创建websocket服务器和客户端,在这里的示例实现的帮助下,我成功地做到了这一点。()-所以当前的工作情况是,我在应用程序启动时运行websocket服务器,然后将客户端加载到可以连接到它的webview中

现在我的问题是我希望我的服务器是安全的websocket服务器(基本上是从HTTPS html页面连接到websocket服务器)

我是网络编程新手,至少可以说Swift nio文档是缺乏的。据我所知,我可以使用()

我找到了这个线程,这正是我所需要的--我可以禁用TLS身份验证,因为我不在乎我的用例,只要我可以连接websocket

所以我的问题是如何扩展我的客户机()和服务器()以使用swift nio传输服务

我可以添加
NIOSSLContext
之类的东西,但我想我需要添加
EventLoopGroup
和新的
bootstrap
方法。我知道答案就在那里。。。。但我似乎无法准确地指出这一点

任何指示都将不胜感激


谢谢

要将简单的
NIO
服务器转换为
NIOTransportServices
服务器,您需要进行以下更改:

  • 将对
    NIOTransportServices
    的依赖项添加到服务器
  • multi-threadedeventloopgroup
    更改为
    NIOTSEventLoopGroup
  • ClientBootstrap
    更改为
    niotconnectionbootstrap
  • ServerBootstrap
    更改为
    niotlistenerbootstrap
  • 构建并运行代码
  • 一些
    ChannelOption
    s在
    NIOTransportServices
    中不起作用,但大多数都起作用:确认事情正常运行的最简单方法是快速测试公共流

    这不会给您的应用程序添加任何额外的功能,但它会使用iOS API为您提供相同的功能

    要将TLS添加到
    niotConnectionBootstrap
    niotListenerBootstrap
    ,可以使用
    .tlsOptions
    函数。例如:

    NiotListenerBootstrap(组:组)
    .tlsOptions(myTLSOptions())
    
    配置
    NWProtocolTLS.Options
    有些棘手。您需要获得一个
    SecIdentity
    ,它需要与钥匙链交互。奎因对此进行了一些讨论

    一旦您有了
    SecIdentity
    ,您就可以这样使用它:

    func myTLSOptions()->NWProtocolTLS.Options{
    let options=NWProtocolTLS.options()
    让yourSecIdentity=//您必须在这里实现一些东西
    sec_协议(选项)设置(本地)标识(options.securityProtocolOptions),sec_标识(yourSecIdentity)
    返回选项
    }
    
    一旦你编写了代码,一切都会顺利进行



    作为一个扩展,如果您想在Linux上保护NIO服务器,您可以使用。这有单独的配置,因为密钥链API不可用,因此您可以从文件中加载更多的密钥和证书。

    我需要一个安全的websocket,而不需要使用
    SecIdentity
    NIOTransportServices
    ,所以请放心关于@Lukasa关于
    swift-nio-ssl
    的提示,我拼凑了一个似乎正确的例子

    我不知道它是否正确,但我把它放在这里,以防其他人能从中受益。为了简洁起见,省略了
    try
    失败时的错误处理和中止

    let configuration = TLSConfiguration.forServer(certificateChain: try! NIOSSLCertificate.fromPEMFile("/path/to/your/tlsCert.pem").map { .certificate($0) }, privateKey: .file("/path/to/your/tlsKey.pem"))
    let sslContext = try! NIOSSLContext(configuration: configuration)
                
    let upgradePipelineHandler: (Channel, HTTPRequestHead) -> EventLoopFuture<Void> = { channel, req in
                    
        WebSocket.server(on: channel) { ws in
    
           ws.send("You have connected to WebSocket")
    
           ws.onText { ws, string in
               print("Received text: \(string)")
           }
                    
           ws.onBinary { ws, buffer in
               // We don't accept any Binary data
           }
                    
           ws.onClose.whenSuccess { value in
               print("onClose")
           }
       }
    }
    
    self.eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 2)
    let port: Int = 5759
    let promise = self.eventLoopGroup!.next().makePromise(of: String.self)
                
    _ = try? ServerBootstrap(group: self.eventLoopGroup!)
                    
        // Specify backlog and enable SO_REUSEADDR for the server itself
        .serverChannelOption(ChannelOptions.backlog, value: 256)
        .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
                    
        .childChannelInitializer { channel in
                        
            let handler = NIOSSLServerHandler(context: sslContext)
            _ = channel.pipeline.addHandler(handler)
                  
            let webSocket = NIOWebSocketServerUpgrader(
                shouldUpgrade: { channel, req in
                    return channel.eventLoop.makeSucceededFuture([:])
                },
                upgradePipelineHandler: upgradePipelineHandler
            )
                  
            return channel.pipeline.configureHTTPServerPipeline(
                withServerUpgrade: (
                    upgraders: [webSocket],
                    completionHandler: { ctx in
                         // complete
                    })
            )
        }.bind(host: "0.0.0.0", port: port).wait()
    
    _ = try! promise.futureResult.wait()
    try! server.close(mode: .all).wait()
    
    let configuration=TLSConfiguration.forServer(certificateChain:try!NIOSSLCertificate.fromPEMFile(“/path/to/your/tlsCert.pem”).map{.certificate($0)},privateKey:.file(“/path/to/your/tlsKey.pem”))
    让sslContext=try!NIOSSLContext(配置:配置)
    让upgradePipelineHandler:(Channel,HTTPRequestHead)->EventLoopFuture={Channel,req in
    服务器(在:通道上){ws-in
    发送(“您已连接到WebSocket”)
    ws.onText{ws,字符串输入
    打印(“收到的文本:\(字符串)”)
    }
    ws.onBinary{ws,缓冲区在
    //我们不接受任何二进制数据
    }
    ws.onClose.whenSuccess{中的值
    打印(“onClose”)
    }
    }
    }
    self.eventLoopGroup=multi-threadedeventloopgroup(线程数:2)
    let端口:Int=5759
    让promise=self.eventLoopGroup!.next().makePromise(of:String.self)
    _=try?ServerBootstrap(组:self.eventLoopGroup!)
    //指定backlog并为服务器本身启用SO_REUSEADDR
    .serverChannelOption(ChannelOptions.backlog,值:256)
    .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr),值:1)
    .childChannelInitializer{channel in
    let handler=NIOSSLServerHandler(上下文:sslContext)
    _=channel.pipeline.addHandler(处理程序)
    让webSocket=NIOWebSocketServerUpgrader(
    应升级:{通道,请求在
    返回channel.eventLoop.makeSucceededFuture([:])
    },
    upgradePipelineHandler:upgradePipelineHandler
    )
    返回channel.pipeline.configureHTTPServerPipeline(
    使用服务器升级:(
    升级者:[webSocket],
    completionHandler:{ctx in
    //完整的
    })
    )
    }.bind(主机:“0.0.0.0”,端口:port).wait()
    _=尝试!承诺。未来结果。等待()
    尝试!服务器。关闭(模式:。全部)。等待()
    
    我设法让客户端和服务器按照您的建议使用NIOTransportServices运行。因此,现在我正试图让
    SecIdentity
    正常工作。因此我猜
    SecIdentity\u协议\u选项\u设置\u对等身份验证\u所需(options.securityProtocolOptions,false)
    仍然损坏?我需要获得自签名证书吗