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");
}
}
}
}
相关推荐
《Openfire与XMPP协议在Android即时通讯中的应用解析》 Openfire是一款开源的服务器软件,它基于XMPP(Extensible Messaging and Presence Protocol)协议,为实时通信提供了一个强大而灵活的平台。XMPP,原名为...
【基于openfire XMPP的即时通讯客服端】是一款专为学校设计的即时通讯软件,它采用了XMPP(Extensible Messaging and Presence Protocol)协议,通过openfire服务器实现强大的在线通信功能。XMPP是一种开放标准,...
android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音。添加删除好友,消息提醒,群聊,邀请好友进入房间,聊天记录保存等等。界面美观。最后说明:此demo是在网上一个叫EIM企信通的demo基础...
android openfire xmpp smack即时通讯,包括:聊天发生文字,表情,图片,语音。添加删除好友,消息提醒,群聊,邀请好友进入房间,聊天记录保存等等。界面美观。最后说明:此demo是在网上一个叫EIM企信通的demo基础...
Openfire基于XMPP(Extensible Messaging and Presence Protocol)协议,这是一种开放标准,被广泛用于构建即时通讯系统。 1. **Openfire**: Openfire是一款开源的服务器软件,它实现了XMPP协议,提供了一个高效...
Dockerized Openfire XMPP服务器 基于Ubuntu GNU / Linux官方映像。 准备 拉图像 docker pull unixs/openfire 创建本地数据持久性目录 mkdir ~ /openfire 准备本地数据 只运行一次。 注意: ~/openfire本地数据...
先说一下为什么要写这篇博客,是因为本人在周末在研究XMPP和OpenFire,从网上下载了个Demo,但跑不起来,花了很长时间,经改造后,跑起来了,写个篇博文也是希望后边学习XMPP和OpenFire的同学下载后直接运行,少走...
开火Openfire XMPP 代码。 开发一个插件来执行中国墙政策。
《Spark与Openfire结合XMPP实现即时通讯技术详解》 在现代互联网应用中,即时通讯(Instant Messaging,简称IM)已经成为不可或缺的一部分。本资料主要探讨如何利用Apache Spark、Smack库以及Openfire服务器来构建...
【标题】:基于Openfire的XMPP即时通讯服务器实践 【描述】:Openfire是一款流行的开源XMPP服务器,它提供了强大的即时通讯功能。通过使用Openfire,开发者可以构建自己的即时通讯系统,实现用户间的文本、语音甚至...
【标题】:“基于openfire为服务器的xmpp即时通信 Android客户端” 在当今信息化时代,即时通信(Instant Messaging,简称IM)已经成为人们日常生活中不可或缺的一部分。本文将深入探讨如何使用openfire作为服务器...
在本项目中,我们关注的是基于asmack和openfire的XMPP(Extensible Messaging and Presence Protocol)实现。XMPP是一种开放的标准协议,用于构建实时通讯系统,它以其强大的扩展性和灵活性被广泛应用于各种即时通讯...
在了解如何在Mac下搭建XMPP服务器之前,首先要知道XMPP和Openfire是什么。XMPP(Extensible Messaging and Presence Protocol,可扩展消息和出席协议)是一种开放标准的即时通信协议,适用于即时消息(IM)、在线...
本项目“Android启动Service登陆Openfire实现基于XMPP Smack的消息推送功能”就是一个很好的示例,展示了如何利用Service和XMPP协议在Android设备上实现实时消息传递。 首先,Openfire是一款开源的XMPP服务器,它...
**XMPP与Openfire搭建详解** XMPP(Extensible Messaging and Presence Protocol)是一种基于XML的实时通讯协议,常用于构建即时通讯系统。它允许用户进行一对一、一对多的消息传输,同时还支持状态呈现、群组聊天...
Openfire是XMPP服务器的一个实现,用Java编写,提供了实时、双向的通信能力。在这个场景中,我们主要探讨如何在Android应用中集成XMPP并使用Openfire作为后台服务器。 首先,让我们了解XMPP。XMPP是一种基于XML的...
XMPP即时聊天源码是一套基于android asmack openfire xmpp的安卓即时聊天服务端,项目直连google talk服务器,可以使用谷歌帐号登录客户端,测试需要至少两个谷歌帐号。在程序里添加好友即可聊天。聊天核心功能使用...