当前位置: 首页 > 知识库问答 >
问题:

我可以用OkHttp将本地IP地址绑定到SSLSocketFactory吗?

殷浩慨
2023-03-14

我正在努力让Android上的OkHttpClient使用自定义证书发出HTTPS请求,同时绑定到特定网络接口的本地地址。我当前的尝试使用以下OkHttpClient

val client = OkHttpClient.Builder()
        .readTimeout(2, TimeUnit.SECONDS)
        .connectTimeout(2, TimeUnit.SECONDS)
        .sslSocketFactory(
            MySocketFactory(
                getSslContext().socketFactory,
                localAddress
            ),
            MyTrustManager()
        )
        .build()

MySocketFactory类实现为:

class MySocketFactory(
    private val delegate: SSLSocketFactory, 
    private val localAddress: InetAddress
) : SSLSocketFactory() {
    override fun createSocket(): Socket {
        Timber.i("createSocket has been called!")
        val socket = delegate.createSocket()
        socket.bind(InetSocketAddress(localAddress, 0))
        return socket
    }

[other overrides of the various abstract createSocket methods, each of which throws an UnsupportedOperationException]

    override fun getDefaultCipherSuites() = delegate.defaultCipherSuites

    override fun getSupportedCipherSuites() = delegate.supportedCipherSuites
}

这主要是基于OkHttp GitHub站点的留档,它描述了如何将值传递给Builder.socketFactory()允许我们通过覆盖无参数的createSocket方法将每个套接字绑定到特定地址。但是,sslSocketFactory的文档没有提到任何关于能够绑定套接字的内容。当我使用上述代码运行我的应用程序时,永远不会生成createSocket日志条目,这表明工厂被完全忽略。因此,永远不会到达HTTPendpoint。

如果我在没有包装器< code>MySocketFactory类的情况下尝试相同的设置,而只是传递< code>getSslContext()。socketFactory直接放入< code > builder . sslsocketfactory -然后我就可以很好地联系endpoint了,假设当时我的机器上只有一个本地地址。

所以我的问题是:这可以用自定义的< code>SSLSocketFactory来实现吗?

共有2个答案

袁华清
2023-03-14

https://github.com/yschimke/okurl/blob/0abaa8510dd5466d5e9a08ebe33a009c491749bf/src/main/kotlin/com/baulsupp/okurl/network/InterfaceSocketFactory.kt

请使用< code > builder . socket factory(getsocket factory())。此示例代码应该基于IP或名称进行选择。

class InterfaceSocketFactory(private val localAddress: InetAddress) : SocketFactory() {
  private val systemFactory = getDefault()

  override fun createSocket(): Socket {
    val s = systemFactory.createSocket()
    s.bind(InetSocketAddress(localAddress, 0))
    return s
  }

  override fun createSocket(host: String, port: Int): Socket {
    return systemFactory.createSocket(host, port, localAddress, 0)
  }

  override fun createSocket(address: InetAddress, port: Int): Socket {
    return systemFactory.createSocket(address, port, localAddress, 0)
  }

  override fun createSocket(
    host: String,
    port: Int,
    localAddr: InetAddress,
    localPort: Int
  ): Socket {
    return systemFactory.createSocket(host, port, localAddr, localPort)
  }

  override fun createSocket(
    address: InetAddress,
    port: Int,
    localAddr: InetAddress,
    localPort: Int
  ): Socket {
    return systemFactory.createSocket(address, port, localAddr, localPort)
  }

  companion object {

    fun byName(ipOrInterface: String): SocketFactory? {
      val localAddress = try {
        // example 192.168.0.51
        InetAddress.getByName(ipOrInterface)
      } catch (uhe: UnknownHostException) {
        // example en0
        val networkInterface = NetworkInterface.getByName(ipOrInterface) ?: return null

        networkInterface.inetAddresses.nextElement()
      }

      return InterfaceSocketFactory(localAddress)
    }
  }
}
西门安宁
2023-03-14

对但不是定制SSLSocketFactory,而是定制常规的SocketFactory。当OkHttp创建任何套接字时,它总是首先使用常规的SocketFactory,然后可能用SSL包装它。这对于TLS隧道是必要的,但在任何地方都可以使用。

 类似资料:
  • 问题内容: 我如何将expressjs服务器绑定到特定IP 就像是 等效于nodejs: 问题答案: 在调用listen时,ExpressJS 会将参数向下传递给模块,因此您的示例应该可以正常工作。 不是吗?

  • 我正在尝试将jboss绑定到一个外部ip地址,而不是默认的127.0.0.1,但是我得到了错误并且无法。 我要绑定到的IP地址是有效和可访问的,并且我已经使用ping进行了测试。我试过修改standalone.conf或修改standalone.xml,也试过-b xxx.xxx.236.237逼近,但每次都得到相同的错误。 请帮忙。多谢了。

  • 假设我有一个名为“mynet”的网络,我想启动一个IP地址绑定到192.168.23.2的容器。 我开始使用的代码是: 我从这里做什么?我正在有效地从中寻找与选项等效的选项。

  • 就是用户打开页面后端,可以直接获取本机的ip地址吗?

  • 问题内容: 我知道对此问题的最初反应是“否”和“无法完成”,并且“您不需要它,您做错了什么”。我正在尝试获取用户的LAN IP地址,并将其显示在网页上。为什么?因为这就是我正在处理的页面的全部内容,因此会显示有关您的尽可能多的信息 因此,除了向用户展示以供参考之外,我实际上并没有对IP做任何事情。我曾经通过使用一个小的Java小程序来做到这一点。效果很好。但是这些天来,浏览器让您多次达成共识和信任

  • 问题内容: 我有一台具有多个NIC的客户端计算机,如何将Go中的http.Client绑定到某个NIC或某个SRC IP地址? 假设您有一些非常基本的http客户端代码,如下所示: 有没有办法绑定到特定的NIC或IP? 问题答案: 与此问题类似,您需要设置字段。将其设置为的实例可以让您指定要使用的对象。然后允许您指定进行连接的本地地址。 例: