无法使用 android 的 asmack 库登录 google talk
Posted
技术标签:
【中文标题】无法使用 android 的 asmack 库登录 google talk【英文标题】:Unable to login to google talk using asmack library for android 【发布时间】:2014-09-15 11:15:22 【问题描述】:我一直在尝试使用 asmack 库登录 google talk,但没有成功。我真的不知道幕后发生了什么,只是从这里和那里收集了一些代码 sn-ps。这是我目前的 android 活动:
public class MainActivity extends Activity
public static final String HOST = "talk.google.com";
public static final int PORT = 5222;
public static final String SERVICE = "gmail.com";
public static final String USER = "user@gmail.com";
public static final String PASSWORD = "password";
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Context context = getApplicationContext();
SmackAndroid asmk = SmackAndroid.init(context);
SASLAuthentication.registerSASLMechanism("X-OAUTH2", SASLGoogleOAuth2Mechanism.class);
SASLAuthentication.supportSASLMechanism("X-OAUTH2", 0);
ConnectionConfiguration connConfig = new ConnectionConfiguration(HOST, PORT, SERVICE);
connConfig.setSecurityMode(SecurityMode.enabled);
connConfig.setReconnectionAllowed(true);
XMPPTCPConnection connection = new XMPPTCPConnection(connConfig);
try
connection.connect();
try
connection.login(USER, PASSWORD);
catch (XMPPException ex)
Log.w("XMPPChatDemoActivity", "Failed to log in");
Log.w("XMPPChatDemoActivity", ex.getMessage());
catch (...)
...
这就是 SASL 机制:
public class SASLGoogleOAuth2Mechanism extends SASLMechanism
private static final Logger log = Logger.getLogger("XMPPChatDemoActivity");
public static final String NAME = "X-OAUTH2";
public SASLGoogleOAuth2Mechanism(SASLAuthentication saslAuthentication)
super(saslAuthentication);
log.info("Creating SASL mechanism for GTalk (X-OAUTH2)");
@Override
public void authenticate(String username, String host, String serviceName, String password) throws IOException, SaslException, NotConnectedException
this.authenticationId = username;
this.hostname = host;
this.password = password;
String[] mechanisms = "PLAIN" ;
Map<String, String> props = new HashMap<String, String>();
this.sc = Sasl.createSaslClient(mechanisms, username, "xmpp", host, props, this);
log.info("sc " + sc);
authenticate();
@Override
public void authenticate(String host, CallbackHandler cbh) throws IOException, SaslException, NotConnectedException
String[] mechanisms = "PLAIN" ;
Map<String, String> props = new HashMap<String, String>();
sc = Sasl.createSaslClient(mechanisms, null, "xmpp", host, props, cbh);
authenticate();
@Override
protected void authenticate() throws IOException, SaslException, NotConnectedException
String authenticationText = null;
try
if (sc.hasInitialResponse())
byte[] response = sc.evaluateChallenge(new byte[0]);
authenticationText = Base64.encodeBytes(response, Base64.DONT_BREAK_LINES);
catch (SaslException e)
throw new SaslException("SASL authentication failed", e);
// Send the authentication to the server
getSASLAuthentication().send(new GoogleOAuthMechanism(authenticationText));
@Override
protected String getName()
return NAME;
/**
* Initiating SASL authentication by select a mechanism.
*/
public static class GoogleOAuthMechanism extends Packet
private final String authenticationText;
/**
* Create a GoogleOAuthMechanism.
*
* @param authenticationText the authentification token
*
*/
public GoogleOAuthMechanism(final String authenticationText)
this.authenticationText = authenticationText;
@Override
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=\"http://www.google.com/talk/protocol/auth\">");
if (authenticationText != null
&& authenticationText.trim().length() > 0)
stanza.append(authenticationText);
stanza.append("</auth>");
return stanza.toString();
代码没问题,我没有收到任何异常,但我收到了<not-authorized>
响应。用户名和密码正确。我找不到该库的任何参考代码。任何帮助将不胜感激。
【问题讨论】:
【参考方案1】:经过几天的努力并尝试了我在互联网上找到的所有可以想象到的 sn-ps 组合,我发现了一个我很高兴与社区分享的解决方案。
看来,我们应该使用 来自 google 的身份验证令牌,而不是将密码传递给 XMPPTCPConnection.login()
方法。我发现a post 解释了一种生成此类令牌的方法。我的similar question 存在,但它也使用X-GOOGLE-TOKEN 机制进行身份验证,这是我使用X-OAUTH2 机制进行身份验证的另一种方法。此外,我能找到的与使用 OAUTH2 对 google talk 进行身份验证问题相关的所有其他帖子都是旧的。我正在使用 smack 4.0.4 的 asmack 版本。
所以问题中显示的代码工作所需的唯一修改是:
AccountManager am = AccountManager.get(this);
Account accounts[] = am.getAccountsByType("com.google");
conn.login(USER, amf.blockingGetAuthToken(accounts[0], GOOGLE_TOKEN_TYPE, true));
如您所见,我使用存储在设备上的帐户来证明解决方案,但您可以通过其他方式生成令牌,正如我上面评论的那样。
最后,当我通过反复试验找到解决方案时,如果有人解释实际发生的事情或我可能提供的任何错误信息,我将不胜感激,因此可以进一步改进此答案。
【讨论】:
以上是关于无法使用 android 的 asmack 库登录 google talk的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Android 设备上使用 asmack 15 登录 Google Talk
Android Asmack xmpp 登录仅适用于我自己的 Facebook 帐户