X-FACEBOOK-PLATFORM身份验证错误

时间:2013-09-26 12:36:55

标签: xmpp x-facebook-platform

我正在尝试使用以下代码通过Facebook chat apiSMACK建立联系,但我始终会收到X-FACEBOOK-PLATFORM failed: not-authorized。我有一个有xmpp权限的有效令牌,但我想我错过了一些东西......它正在使用user / pass,但没有使用accessToken。

感谢你的帮助,这件事让我发疯了。

public class FacebookChatSample {

public static void main(   )
{

    String accessToken = //internet example "AAACjg0Eh1N8BAFuhUFZAN0EteV6pjZAsZAI46i8oV3iVmyLdaKiwaBcM5DPFjbEZAq9LZAZAA0qXsvaXkKB7SqnhubzlUAK7tmr3UYLaeQgaXSJ6EZCKn2G";
    String consumerKey = //internet example "179784128779487";

    long targetFacebookId = 550121201669650L;

    String toID = "1002221765";

    String message = "HELLOOOOO FROM MY JAVA PROGRAM!!";

    XMPPConnection connection = createXMPPConnection();
    try
    {
        connection.connect();
        connection.login( consumerKey, accessToken );

        String to = String.format( "-%d@chat.facebook.com", Long.valueOf( targetFacebookId ) );
        Chat chat = connection.getChatManager().createChat( to, null );
        chat.sendMessage( message );
    }
    catch( XMPPException e )
    {
       e.printStackTrace();
    }
    finally
    {
        connection.disconnect();
    }
}

private static synchronized XMPPConnection createXMPPConnection()
{
    SASLAuthentication.registerSASLMechanism(
            SASLXFacebookPlatformMechanism.NAME,
            SASLXFacebookPlatformMechanism.class );
    SASLAuthentication.supportSASLMechanism(
            SASLXFacebookPlatformMechanism.NAME, 0 );

    ConnectionConfiguration configuration = new ConnectionConfiguration(
            "chat.facebook.com", 5222 );
    configuration.setSASLAuthenticationEnabled( true );

    return new XMPPConnection( configuration );
}

public static class SASLXFacebookPlatformMechanism extends SASLMechanism
{
    public static final String NAME = "X-FACEBOOK-PLATFORM";

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

    private String apiKey = "";

    private String accessToken = "";

    @Override
    protected void authenticate() throws IOException, XMPPException
    {
        AuthMechanism stanza = new AuthMechanism( getName(), null );
        getSASLAuthentication().send( stanza );
    }

    @SuppressWarnings( "hiding" )
    @Override
    public void authenticate( String apiKey, String host, String accessToken )
            throws IOException, XMPPException
    {
        if( apiKey == null || accessToken == null )
        {
            throw new IllegalStateException( "Invalid parameters!" );
        }

        this.apiKey = apiKey;
        this.accessToken = accessToken;
        this.hostname = host;

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

    @Override
    public void authenticate( String username, String host,
            CallbackHandler cbh ) throws IOException, XMPPException
    {
        String[] mechanisms = { "DIGEST-MD5" };
        Map<String, String> props = new HashMap<String, String>();
        this.sc = Sasl.createSaslClient( mechanisms, null, "xmpp", host,
                props, cbh );
        authenticate();
    }

    @Override
    protected String getName()
    {
        return NAME;
    }

    @Override
    public void challengeReceived( String challenge ) throws IOException
    {
        byte response[] = null;
        if( challenge != null )
        {
            String decodedResponse = new String(
                    org.jivesoftware.smack.util.Base64.decode( challenge ) );
            Map<String, String> parameters = getQueryMap( decodedResponse );

            String version = "1.0";
            String nonce = parameters.get( "nonce" );
            String method = parameters.get( "method" );

            Long callId = Long.valueOf( System.currentTimeMillis() );

            String composedResponse = String
                    .format(
                            "method=%s&nonce=%s&access_token=%s&api_key=%s&call_id=%s&v=%s",
                            URLEncoder.encode( method, "UTF-8" ),
                            URLEncoder.encode( nonce, "UTF-8" ),
                            URLEncoder.encode( this.accessToken, "UTF-8" ),
                            URLEncoder.encode( this.apiKey, "UTF-8" ),
                            callId, URLEncoder.encode( version, "UTF-8" ) );
            response = composedResponse.getBytes();
        }

        String authenticationText = "";

        if( response != null )
        {
            authenticationText = org.jivesoftware.smack.util.Base64
                    .encodeBytes(
                            response,
                            org.jivesoftware.smack.util.Base64.DONT_BREAK_LINES );
        }

        Response stanza = new Response( authenticationText );

        getSASLAuthentication().send( stanza );
    }

    private Map<String, String> getQueryMap( String query )
    {
        String[] params = query.split( "&" );
        Map<String, String> map = new HashMap<String, String>();
        for( String param : params )
        {
            String name = param.split( "=" )[0];
            String value = param.split( "=" )[1];
            map.put( name, value );
        }
        return map;
    }
}
}

1 个答案:

答案 0 :(得分:1)

我的上帝,我也一直在为此奋斗。我只想出来了!一旦我得到它,它似乎很容易,但令人困惑的是,似乎来自XMPP的问题实际上是Facebook的一个问题。我认为您的问题(我的问题是)Facebook要求您请求与XMPP协议无关的特定于应用程序的登录权限。如果您查看聊天API规范,它表示如果您使用的是X-FACEBOOK-PLATFORM,则需要为您的应用程序请求xmpp_login扩展权限。您必须通过用于获取session_token的Facebook SDK中的会话对象执行此操作。

以下是我使用的代码:

session.requestNewReadPermissions(new NewPermissionsRequest(getActivity(), Arrays.asList("xmpp_login")));

一旦我这样做,它就像一个魅力。最后需要注意的是,您需要确保弹出对话框要求用户授予您的应用程序此扩展权限,并在您继续操作并尝试xmpp.login之前获得所需的权限。否则,您将遇到与您的应用请求权限但实际上获取权限相同的问题。

我希望这适合你。