`
youzifei
  • 浏览: 66668 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

openfire xmpp sasl 浅析

阅读更多

SASL全称Simple Authentication and Security Layer,是一种用来扩充C/S模式验证能力的机制。在Postfix可以利用SASL来判断用户是否有权使用转发服务,或是辨认谁在使用你的服务器。
SASL提供了一个通用的方法为基于连接的协议增加验证支持,而XMPP使用了一个普通的XML名字空间来满足SASL的需要。

在xmpp协议下客户端和服务器端的交换报文如下:
1.客户端发送xmpp流
[client]:<stream:stream to="192.168.0.104" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
2.服务端响应
[server]:<?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="192.168.1.212" id="8e73bf6e" xml:lang="en" version="1.0">
3.服务端发送支持链接的特性
[server]:<stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>DIGEST-MD5</mechanism><mechanism>JIVE-SHAREDSECRET</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism><mechanism>CRAM-MD5</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><auth xmlns="http://jabber.org/features/iq-auth"/><register xmlns="http://jabber.org/features/iq-register"/></stream:features>
4.客户端选择 tls (Transport Layer Security 传输层安全)协议
[client]:<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
5.服务器端开始处理 tls
[server]:<proceed xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
6.客户端重新发送开始流
[client]:<stream:stream to="192.168.1.212" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
7.服务端响应
[server]:<?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="192.168.1.212" id="8e73bf6e" xml:lang="en" version="1.0"><stream:features><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>DIGEST-MD5</mechanism><mechanism>JIVE-SHAREDSECRET</mechanism><mechanism>PLAIN</mechanism><mechanism>ANONYMOUS</mechanism><mechanism>CRAM-MD5</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><auth xmlns="http://jabber.org/features/iq-auth"/><register xmlns="http://jabber.org/features/iq-register"/></stream:features>
8.客户端发送 sasl认证请求
[client]:<auth mechanism="DIGEST-MD5" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"></auth>
9.服务端发送 询问 询问内容使用base64进行编码
[server]:<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09IjE5Mi4xNjguMS4yMTIiLG5vbmNlPSJNODU5ZE9PT3R6b21CVHA3S25zSlg2YTJIS0ZEcGdSZ0FWQ3hHY2twIixxb3A9ImF1dGgiLGNoYXJzZXQ9dXRmLTgsYWxnb3JpdGhtPW1kNS1zZXNz</challenge>
realm="192.168.1.212",nonce="M859dOOOtzomBTp7KnsJX6a2HKFDpgRgAVCxGckp",qop="auth",charset=utf-8,algorithm=md5-sess
10.客户端应答询问,应答内容使用base64进行编码
[client]:<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">Y2hhcnNldD11dGYtOCx1c2VybmFtZT0iamltbXkiLHJlYWxtPSIxOTIuMTY4LjEuMjEyIixub25jZT0iTTg1OWRPT090em9tQlRwN0tuc0pYNmEySEtGRHBnUmdBVkN4R2NrcCIsbmM9MDAwMDAwMDEsY25vbmNlPSJDRU9ienFnMTVJV1JSNkcrOFBLS2ZtbG81MUI2UzZaU040WXBHNXFxIixkaWdlc3QtdXJpPSJ4bXBwLzE5Mi4xNjguMS4yMTIiLG1heGJ1Zj02NTUzNixyZXNwb25zZT1iYjFkOWEwMWQ5NTBkYTFhOTIxNTI2ODMzYmUyZjE3Mixxb3A9YXV0aCxhdXRoemlkPSJqaW1teSI=</response>
charset=utf-8,username="jimmy",realm="192.168.1.212",nonce="M859dOOOtzomBTp7KnsJX6a2HKFDpgRgAVCxGckp",nc=00000001,cnonce="CEObzqg15IWRR6G+8PKKfmlo51B6S6ZSN4YpG5qq",digest-uri="xmpp/192.168.1.212",maxbuf=65536,response=bb1d9a01d950da1a921526833be2f172,qop=auth,authzid="jimmy"
11.服务端验证成功
[server]:<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD1kZGZiZmVmYmRiZjZlYmZjOTQ4M2U0MWMyMDM4MTA5YQ==</success>
rspauth=ddfbfefbdbf6ebfc9483e41c2038109a
12.客户端第三次重新建立流
[client]:<stream:stream to="192.168.1.212" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
13.服务端响应
[server]:<?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="192.168.1.212" id="8e73bf6e" xml:lang="en" version="1.0"><stream:features><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"/><session xmlns="urn:ietf:params:xml:ns:xmpp-session"/></stream:features>
下面就是一些流程性的东西了

在sasl 是怎样进行challenge、response、success的呢?
在服务端
先生成saslserver,由server生成challenge,发送给client。
    Map<String, String> props=new TreeMap<String, String>();
    props.put(Sasl.QOP, "auth");
    SaslServer ss=Sasl.createSaslServer("DIGEST-MD5", "xmpp", "java.com", props, new ServerCallbackHandler());
    byte[] token=new byte[0];
    byte[] challenge=ss.evaluateResponse(token);

在客户端收到 challenge后生, 生成saslclient 处理challenge 生成response 在发给server
    SaslClient sc=Sasl.createSaslClient(new String[]{"DIGEST-MD5"}, "x", "xmpp", "java.com", null, new ClientCallbackHandler());
    byte response[];
    response=sc.evaluateChallenge(challenge);
server收到 应答后进行验证,验证通过后给客户端一个响应。
    ss.evaluateResponse(response);
    if(ss.isComplete()) {
        System.out.println("auth success");
    }

下面是sasl 的一个小例子,希望有助于理解sasl协议

package test.com.jimmy.tls;

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

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.RealmCallback;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;

public class AuthMain {

    /**
     * @param args
     * @throws SaslException
     */

    public static void main(String[] args) throws SaslException {

        Map<String, String> props=new TreeMap<String, String>();

        props.put(Sasl.QOP, "auth");
        /**
         * 为指定机制创建一个 SaslServer。 Sasl.createSaslServer(String mechanism, String protocol, String serverName, Map<String,?> props,
         * CallbackHandler cbh)
         *  参数 mechanism - 非 null 的机制名。它必须是 SASL 机制的 IANA 注册名。(例如 "GSSAPI"、"CRAM-MD5")。
         *  protocol - 非 null 的协议(例如 "ldap")字符串名,将为它执行身份验证。
         *  serverName - 服务器的非 null 完全限定主机名。
         *   props - 可能为 null 的属性集,用于选择 SASL 机制并配置所选机制的身份验证交换。例如,如果 props 包含
         * Sasl.POLICY_NOPLAINTEXT 属性,且属性值为 "true",则所选的 SASL 机制必须不易受到简单被动式攻击的危害。除了在此类中所声明的标准属性外,也可以包括其他的可能特定于机制的属性。忽略与所选机制无关的属性。 cbh
         * - SASL 机制使用的回调处理程序(可能为 null),以便为完成身份验证而从应用程序/库获得更多的信息。例如,SASL 机制可能需要从调用方获得身份验证 ID、密码和域。使用 NameCallback 来请求身份验证 ID。使用
         * PasswordCallback 来请求密码。如果要从域列表中选择,则使用 RealmChoiceCallback 来请求域,如果必须输入域,则使用 RealmCallback 来请求域。
         */
        SaslServer ss=Sasl.createSaslServer("DIGEST-MD5", "xmpp", "java.com", props, new ServerCallbackHandler());

        byte[] token=new byte[0];

        byte[] challenge=ss.evaluateResponse(token);

        SaslClient sc=
            Sasl.createSaslClient(new String[]{"DIGEST-MD5"}, "x", "xmpp", "java.com", null, new ClientCallbackHandler());

        byte response[];

        if(challenge != null) {

            response=sc.evaluateChallenge(challenge);

        } else {

            response=sc.evaluateChallenge(null);

        }

        ss.evaluateResponse(response);

        if(ss.isComplete()) {

            System.out.println("auth success");

        }

    }

}

class ClientCallbackHandler implements CallbackHandler {

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {

        for(int i=0; i < callbacks.length; i++) {
            if(callbacks[i] instanceof NameCallback) {
                NameCallback ncb=(NameCallback)callbacks[i];
                ncb.setName("tony1");
            } else if(callbacks[i] instanceof PasswordCallback) {
                PasswordCallback pcb=(PasswordCallback)callbacks[i];
                pcb.setPassword("admin1s".toCharArray());
            } else if(callbacks[i] instanceof RealmCallback) {
                RealmCallback rcb=(RealmCallback)callbacks[i];
                rcb.setText("java.com");
            } else {
                throw new UnsupportedCallbackException(callbacks[i]);
            }

        }

    }

}

class ServerCallbackHandler implements CallbackHandler {

    public ServerCallbackHandler() {

    }

    public void handle(final Callback[] callbacks) throws IOException,

    UnsupportedCallbackException {

        for(Callback callback: callbacks) {

            if(callback instanceof RealmCallback) {
                System.out.println("RealmCallback" + ((RealmCallback)callback).getDefaultText());
            } else if(callback instanceof NameCallback) {
                System.out.println("NameCallback" + ((NameCallback)callback).getDefaultName());
            } else if(callback instanceof PasswordCallback) {
                ((PasswordCallback)callback).setPassword("admin1s".toCharArray());
            } else if(callback instanceof AuthorizeCallback) {
                AuthorizeCallback authCallback=((AuthorizeCallback)callback);
                authCallback.setAuthorized(true);
            } else {
                System.out.println(callback.getClass().getName());
                throw new UnsupportedCallbackException(callback, "Unrecognized Callback");

            }

        }

    }

}

分享到:
评论
1 楼 可以扯扯 2015-08-14  
好文要顶!看了之后茅塞顿开

相关推荐

    openfire xmpp协议源码

    《Openfire与XMPP协议在Android即时通讯中的应用解析》 Openfire是一款开源的服务器软件,它基于XMPP(Extensible Messaging and Presence Protocol)协议,为实时通信提供了一个强大而灵活的平台。XMPP,原名为...

    基于openfire XMPP的即时通讯客服端

    【基于openfire XMPP的即时通讯客服端】是一款专为学校设计的即时通讯软件,它采用了XMPP(Extensible Messaging and Presence Protocol)协议,通过openfire服务器实现强大的在线通信功能。XMPP是一种开放标准,...

    android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音等

    android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音。添加删除好友,消息提醒,群聊,邀请好友进入房间,聊天记录保存等等。界面美观。最后说明:此demo是在网上一个叫EIM企信通的demo基础...

    android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音等直接导入eclipse不报错

    android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音。添加删除好友,消息提醒,群聊,邀请好友进入房间,聊天记录保存等等。界面美观。最后说明:此demo是在网上一个叫EIM企信通的demo基础...

    android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音等.zip

    Openfire基于XMPP(Extensible Messaging and Presence Protocol)协议,这是一种开放标准,被广泛用于构建即时通讯系统。 1. **Openfire**: Openfire是一款开源的服务器软件,它实现了XMPP协议,提供了一个高效...

    docker-openfire:Dockerized Openfire XMPP服务器

    Dockerized Openfire XMPP服务器 基于Ubuntu GNU / Linux官方映像。 准备 拉图像 docker pull unixs/openfire 创建本地数据持久性目录 mkdir ~ /openfire 准备本地数据 只运行一次。 注意: ~/openfire本地数据...

    Xmpp和OpenFire实例

    先说一下为什么要写这篇博客,是因为本人在周末在研究XMPP和OpenFire,从网上下载了个Demo,但跑不起来,花了很长时间,经改造后,跑起来了,写个篇博文也是希望后边学习XMPP和OpenFire的同学下载后直接运行,少走...

    openfire:Openfire XMPP 代码。 开发一个插件来执行中国墙政策

    开火Openfire XMPP 代码。 开发一个插件来执行中国墙政策。

    spark_smack_openfire.zip_openfire spark_spark xmpp_xmpp _xmpp op

    《Spark与Openfire结合XMPP实现即时通讯技术详解》 在现代互联网应用中,即时通讯(Instant Messaging,简称IM)已经成为不可或缺的一部分。本资料主要探讨如何利用Apache Spark、Smack库以及Openfire服务器来构建...

    openfire为服务器的XMPP的即时通信样例

    【标题】:基于Openfire的XMPP即时通讯服务器实践 【描述】:Openfire是一款流行的开源XMPP服务器,它提供了强大的即时通讯功能。通过使用Openfire,开发者可以构建自己的即时通讯系统,实现用户间的文本、语音甚至...

    基于openfire为服务器的xmpp即时通信 Android客户端

    【标题】:“基于openfire为服务器的xmpp即时通信 Android客户端” 在当今信息化时代,即时通信(Instant Messaging,简称IM)已经成为人们日常生活中不可或缺的一部分。本文将深入探讨如何使用openfire作为服务器...

    及时通讯基于asmack和openfire,xmpp完整项目

    在本项目中,我们关注的是基于asmack和openfire的XMPP(Extensible Messaging and Presence Protocol)实现。XMPP是一种开放的标准协议,用于构建实时通讯系统,它以其强大的扩展性和灵活性被广泛应用于各种即时通讯...

    Mac 下搭建XMPP服务器之openfire

    在了解如何在Mac下搭建XMPP服务器之前,首先要知道XMPP和Openfire是什么。XMPP(Extensible Messaging and Presence Protocol,可扩展消息和出席协议)是一种开放标准的即时通信协议,适用于即时消息(IM)、在线...

    Android启动Service登陆Openfire实现基于XMPP Smack的消息推送功能

    本项目“Android启动Service登陆Openfire实现基于XMPP Smack的消息推送功能”就是一个很好的示例,展示了如何利用Service和XMPP协议在Android设备上实现实时消息传递。 首先,Openfire是一款开源的XMPP服务器,它...

    xmpp,openfire搭建ppt

    **XMPP与Openfire搭建详解** XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通讯协议,常用于构建即时通讯系统。它允许用户进行一对一、一对多的消息传输,同时还支持状态呈现、群组聊天...

    android XMPP openfire

    Openfire是XMPP服务器的一个实现,用Java编写,提供了实时、双向的通信能力。在这个场景中,我们主要探讨如何在Android应用中集成XMPP并使用Openfire作为后台服务器。 首先,让我们了解XMPP。XMPP是一种基于XML的...

    XMPP即时聊天源码.zip

    XMPP即时聊天源码是一套基于android asmack openfire xmpp的安卓即时聊天服务端,项目直连google talk服务器,可以使用谷歌帐号登录客户端,测试需要至少两个谷歌帐号。在程序里添加好友即可聊天。聊天核心功能使用...

Global site tag (gtag.js) - Google Analytics