1

asmack(Android Gingerbread)でグーグルトークに接続しようとしています。私は設定connectionConfig.setTruststoreType("BKS")しました-それで私は証明書の問題を乗り越えます。これで失敗はXMPPConnection.proceedTLSReceived()関数にあります。これは、サーバーが「starttls」要求に対して「proceed」を送信した後に呼び出されます。

この関数は、TSLソケットを初期化することになっています。例外「java.net.SocketException:ソケットが閉じられました」で失敗します。

// Verify certificate presented by the server
context.init(kms,
    new javax.net.ssl.TrustManager[]{new ServerTrustManager(getServiceName(), config)},
    //new javax.net.ssl.TrustManager[]{new OpenTrustManager()},
    new java.security.SecureRandom());
Socket plain = socket;
// Secure the plain connection
socket = context.getSocketFactory().createSocket(plain, plain.getInetAddress().getHostName(), plain.getPort(), false);
socket.setSoTimeout(0); ////// THIS LINE THROWS THE EXCEPTION

手がかりはありますか?

ソケットは次のように記述されます:SSLソケットオーバーソケット[addr = talk.google.com / 173.194.70.125、port = 5222、localport = 34840]

エミュレーターとGalaxySI9000で失敗します。

4

1 に答える 1

1

結局のところ、SSL 接続にタイムアウトの問題がありました。私のアプリケーションでは、SSL ソケットを生成するのに (プレーン ソケットを介して) 非常に時間がかかり、反対側は単純にあきらめました... これ、またはキーの問題がありました (ただし、認証エラーは発生しませんでした)。

次の方法で問題を解決しました。

  1. API レベル 15 への移行 - BKS (API 10 で使用した) ではなく、AndroidCSStore を使用します。
  2. getAuthTokenを使用してパスワードを取得します。これは実際にはトークンですが、後で接続時にパスワードとして使用されます。
  3. 問題の真相を突き止めるための時間はありません。今は機能しています。それがすべてです。

以下にコードを投稿しました。SASLXOAuth2Mechanism が完成しました。しかし、Main のコードは整然としたものであり、完全ではありません。このサイトの他の回答からコードを抜粋しました。盗作について事前に謝罪します。

Main.java - asmack を開始する

// Init asmack, and register new mechanisms.
asmack = SmackAndroid.init(ctx);

SASLAuthentication.registerSASLMechanism("X-OAUTH2", SASLXOAuth2Mechanism.class);
SASLAuthentication.supportSASLMechanism("X-OAUTH2", 0);

ConnectionConfiguration connectionConfig = 
    new ConnectionConfiguration (getHost(), getPort(), getService());
connectionConfig.setSASLAuthenticationEnabled(true);
connectionConfig.setSecurityMode(true);
connectionConfig.setRosterLoadedAtLogin(true);
connectionConfig.setReconnectionAllowed(true);
connectionConfig.setSendPresence(false);
//connectionConfig.setCompressionEnabled(true);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        connectionConfig.setTruststoreType("AndroidCAStore");
        connectionConfig.setTruststorePassword(null);
        connectionConfig.setTruststorePath(null);
} /*else {
        connectionConfig.setTruststoreType("BKS");
        String path = System.getProperty("javax.net.ssl.trustStore");
        if (path == null)
            path = System.getProperty("java.home") + File.separator + "etc"
                + File.separator + "security" + File.separator
                + "cacerts.bks";
        connectionConfig.setTruststorePath(path);
        connectionConfig.setTruststorePassword("changeit");
 //} */

 XMPPConnection con = new XMPPConnection(connectionConfig);

SASLXOAuth2Mechanism.java - XOAuth2 メカニズム

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import org.jivesoftware.smack.SASLAuthentication;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.sasl.SASLMechanism;
import org.jivesoftware.smack.util.Base64;

import de.measite.smack.Sasl;

public class SASLXOAuth2Mechanism extends SASLMechanism
{
    static final String AUTHENTICATOR_URL = "http://www.google.com/talk/protocol/auth";
    protected String authenticationText = null;
    static final String TAG = "SASLXOAuth2Mechanism";

    public SASLXOAuth2Mechanism(SASLAuthentication saslAuthentication) {
        super(saslAuthentication);
    }

    @Override
    protected String getName()
    {
        return "X-OAUTH2";
    }

    @Override
    public void authenticate(String username, String host, String password) throws IOException, XMPPException {
        this.password = password;
        this.authenticationId = username;

        StringBuilder credentials = new StringBuilder();
        credentials.append("\0");
        credentials.append(username);
        credentials.append("\0");
        credentials.append(password);
        authenticationText = Base64.encodeBytes(credentials.toString().getBytes("UTF-8"), Base64.DONT_BREAK_LINES);

        String[] mechanisms = { "PLAIN" };
        Map<String,String> props = new HashMap<String,String>();
        sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, this);
        authenticate();
    }

    protected void authenticate() throws IOException, XMPPException {
        // Send the authentication to the server
        getSASLAuthentication().send(new XOAuth2AuthMechanism(getName(), authenticationText));
    }

    /**
     * Initiating SASL authentication by select a mechanism.
     */
    public class XOAuth2AuthMechanism extends Packet {
        final private String name;
        final private String authenticationText;

        public XOAuth2AuthMechanism(String name, String authenticationText) {
            super();
            this.name = name;
            this.authenticationText = authenticationText;
        }

        public String toXML() {
            StringBuilder stanza = new StringBuilder();
            stanza.append("<auth mechanism=\"").append(name);
            stanza.append("\" xmlns=\"urn:ietf:params:xml:ns:xmpp-sasl\" auth:service=\"oauth2\" xmlns:auth=\"").append(AUTHENTICATOR_URL);
            stanza.append("\">");
            if (authenticationText != null) {
                stanza.append(authenticationText);
            }
            stanza.append("</auth>");
            return stanza.toString();
        }
    }
}
于 2013-02-18T11:31:33.617 に答える