Smack: SSL / TLS требуется для сервера, но отключен в клиенте - PullRequest
0 голосов
/ 29 апреля 2019

Я разрабатываю чат один на один, но сталкиваюсь с проблемой SSL / TLS, требуемой сервером, но отключенной в клиенте, не знаю, что я делаю неправильно, пожалуйста, помогите мне разобраться в ошибке

Мой класс обслуживания:

class ChatService:Service() {

    var text = ""

    var  chat:Chat?=null
    companion object {
        private val DOMAIN = "localhost"
        private val USERNAME = "admin@localhost"
        private val PASSWORD = "localhost"

        var cm: ConnectivityManager? = null
        var xmpp: MyXMPP? = null
        var ServerchatCreated = false

        fun isNetworkConnected(): Boolean {
            return cm!!.getActiveNetworkInfo() != null
        }
    }

    override fun onCreate() {
        super.onCreate()
        cm= getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager?
        xmpp = MyXMPP.getInstance(this, DOMAIN, USERNAME, PASSWORD);
        xmpp!!.connect("onCreate");
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return START_NOT_STICKY
    }

    override fun onBind(intent: Intent?): IBinder? {
        return LocalBinder<ChatService>(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        xmpp!!.disconnect();
    }
}

Мой класс XMPP Для соединения:

companion object {
        fun getInstance(context: ChatService, server: String, user: String, pass: String): MyXMPP {

        if (instance == null) {
            instance = MyXMPP(context, server, user, pass)
            instanceCreated = true
        }
        return instance!!

    }
}


constructor(context: ChatService, serverAdress: String, logiUser: String, passwordser: String) {
    this.serverAddress = serverAdress
    this.loginUser = logiUser
    this.passwordUser = passwordser
    this.context = context
    initialiseConnection()
}

private fun initialiseConnection() {
            val serviceName = JidCreate.domainBareFrom("localhost")
            val config = XMPPTCPConnectionConfiguration.builder()
            config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
            config.setServiceName(serviceName)
            config.setHostAddress(InetAddress.getByName("192.168.0.101"))//my ip address
            config.setPort(5222)
            config.setXmppDomain(serviceName)
            config.setDebuggerEnabled(true)
            //System.setProperty("smack.debugEnabled", "true")
            XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true)
            XMPPTCPConnection.setUseStreamManagementDefault(true)
            connection = XMPPTCPConnection(config.build())
            val connectionListener = XMPPConnectionListener()
            connection!!.addConnectionListener(connectionListener)
        }

Внутренний класс к классу MyXMPP:

inner class XMPPConnectionListener : ConnectionListener {
            override fun connected(connection: XMPPConnection) {

                Log.d("xmpp", "Connected!")
                connected = true
                if (!connection.isAuthenticated) {
                    login()
                }
            }

            override fun connectionClosed() {
                if (isToasted)

                    Handler(Looper.getMainLooper()).post(Runnable {
                        // TODO Auto-generated method stub

                        Toast.makeText(
                            context, "ConnectionCLosed!",
                            Toast.LENGTH_SHORT
                        ).show()
                    })
                Log.d("xmpp", "ConnectionCLosed!")
                connected = false
                chat_created = false
                loggedin = false
            }

            override fun connectionClosedOnError(arg0: Exception) {
                if (isToasted)

                    Handler(Looper.getMainLooper()).post(Runnable {
                        Toast.makeText(
                            context, "ConnectionClosedOn Error!!",
                            Toast.LENGTH_SHORT
                        ).show()
                    })
                Log.d("xmpp", "ConnectionClosedOn Error!")
                connected = false

                chat_created = false
                loggedin = false
            }

Вход в ejabberсервер:

fun login() {

            try {
                connection?.login(loginUser, passwordUser)
                Log.i("LOGIN", "Yey! We're connected to the Xmpp server!")

            } catch (e: XMPPException) {
                e.printStackTrace()
            } catch (e: SmackException) {
                e.printStackTrace()
            } catch (e: IOException) {
                e.printStackTrace()
            } catch (e: Exception) {
            }

        }

Logcat:

D/SMACK: RECV (0): <?xml version='1.0'?><stream:stream id='1777473137180053616' version='1.0' xml:lang='en' xmlns:stream='http://etherx.jabber.org/streams' from='localhost' xmlns='jabber:client'>
2019-04-29 13:25:40.247 30893-30976/shop.com.letsshop D/SMACK: RECV (0): <stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'><required/></starttls></stream:features>
2019-04-29 13:25:40.249 30893-30974/shop.com.letsshop E/(onCreate): SMACKException: SSL/TLS required by server but disabled in client
2019-04-29 13:25:40.251 30893-30976/shop.com.letsshop W/AbstractXMPPConnection: Connection XMPPTCPConnection[not-authenticated] (0) closed with error
    org.jivesoftware.smack.SmackException$SecurityRequiredByServerException: SSL/TLS required by server but disabled in client
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.afterFeaturesReceived(XMPPTCPConnection.java:928)
        at org.jivesoftware.smack.AbstractXMPPConnection.parseFeatures(AbstractXMPPConnection.java:1446)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$1100(XMPPTCPConnection.java:149)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1048)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:980)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:996)
        at java.lang.Thread.run(Thread.java:764)
2019-04-29 13:25:40.252 30893-30976/shop.com.letsshop D/xmpp: ConnectionClosedOn Error!

1 Ответ

0 голосов
/ 01 мая 2019

После много борьбы я нашел решение:)

MyXmpp Class:

        val serviceName = JidCreate.domainBareFrom("localhost")// if user is register as admin@localhost ,you should have to take only string after "@" i.e localhost
        val config = XMPPTCPConnectionConfiguration.builder()
        config.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
        config.setXmppDomain(serviceName);
        config.setHostAddress( InetAddress.getByName("192.168.0.101"))// your server ip address or for local host ,pc ip address
        config.setPort(5222)
        config.setDebuggerEnabled(true)
        val sslContext = getSSLContext()// setting ssl
        config.setCustomSSLContext(sslContext)
        SASLAuthentication.blacklistSASLMechanism("SCRAM-SHA-1")
        SASLAuthentication.blacklistSASLMechanism("DIGEST-MD5")
        SASLAuthentication.unBlacklistSASLMechanism("PLAIN")
        XMPPTCPConnection.setUseStreamManagementResumptiodDefault(true)
        XMPPTCPConnection.setUseStreamManagementDefault(true)
        connection = XMPPTCPConnection(config.build())
        connection?.login("admin", "localhost")//ejabber server login id .if you have admin@localhost then take only admin as a username . password i am having as localhost.

Включение SSL:

@Throws(IOException::class,
    CertificateException::class, NoSuchAlgorithmException::class, KeyStoreException::class, KeyManagementException::class)
       private fun getSSLContext():SSLContext{
        var cf: CertificateFactory? =null


        try {
            cf = CertificateFactory.getInstance("X.509");
        } catch (e:CertificateException) {
            Log.d("ca", "ca=" + e.message);
        }

        var input = context.getResources().openRawResource(R.raw.my_keystore); // R.raw.chain is CA Root Certificate added in RAW resources folder

        var caInput =  BufferedInputStream(input);
        var ca:Certificate?=null
        try {
            ca = cf!!.generateCertificate(caInput)
           // Log.d("ca", "ca=" + ((X509Certificate) ca).getSubjectDN())

        }
        catch (e:Exception){
            Log.e("ca", e.message);
        }
        finally {
            caInput.close();
        }

        // Create a KeyStore containing our trusted CAs
        var keyStoreType = KeyStore.getDefaultType();
        var keyStore = KeyStore.getInstance(keyStoreType);
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        // Create a TrustManager that trusts the CAs in our KeyStore
        var tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        var tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
        tmf.init(keyStore);

        // Create an SSLContext that uses our TrustManager
        var sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        return sslContext;
    }

Здесь я застрял: как найти my_keystore. Затем я нашел в файле server.pem в ejabbered, там вы найдете закрытый ключ, ключ, который я должен вставить на стороне клиента (Android Studio-> res-> raw (папка) -> my_keystore (создайте пустой файл, как этот)), т.е. в файле my_keystore. Здесь указан полный путь к server.pem. /opt/ejabberd/conf

...