安卓xmpp简单介绍(登录)以及自签名证书的使用
2016-12-05 18:03
309 查看
安卓xmpp简单介绍(登录)以及自签名证书的使用
概念
OSI七层模型
开放系统互连参考模型 (Open System Interconnect 简称OSI)是国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)联合制定的开放系统互连参考模型,为开放式互连信息系统提供了一种功能结构的框架。它从低到高分别是:物理层、数据链路层、网络层、传输层、会话层、表示层和应用层,具体参考[百度百科]。
七层模型的介绍网络上很多,这里不浪费篇幅,主要给初学者举几个例子,可能印象更深,初级java开发常接触到的协议以及所属的层分别为:
IP(Internet Protocol)-网络层
TCP(Transmission Control Protocol)-传输层
UDP(User Datagram Protocol)-传输层
SSL(Secure Sockets Layer)-传输层和应用层之间
TLS(Transport Layer Security)-传输层和应用层之间
HTTP(HyperText Transfer Protocol)-应用层
HTTPS(Hyper Text Transfer Protocol over Secure Socket Layer)-应用层
FTP(File Transfer Protocol)-应用层
SFTP(Secure File Transfer Protocol)-应用层
TELNET-应用层
DNS(Domain Name System)-应用层
XMPP
Extensible Messaging and Presence Protocol,(可扩展消息处理现场协议)是基于可扩展标记语言(XML)的协议,它用于即时消息(IM)以及在线现场探测。它在促进服务器之间的准即时操作。这个协议可能最终允许因特网用户向因特网上的其他任何人发送即时消息,即使其操作系统和浏览器不同。属于应用层范畴,在TCP或TLS之上进行数据的封装。
安卓应用支持xmpp
asmack(客户端)
asmack是一个开源软件,支持在安卓应用上封装实现xmpp协议的交互功能。近期由于smack在4之后支持了安卓,因此smack自2015年2月后不再更新,asmack只有一个jar包,因此集成比较方便,本文示例代码仍旧以asmack为例(与smack大同小异)。
jar和源码:http://asmack.freakempire.de/4.0.7/
openfire(服务端)
openfire是开源的、基于可拓展通讯和表示协议(XMPP)、采用Java编程语言开发的实时协作服务器。 Openfire安装和使用都非常简单,并利用Web进行管理。单台服务器可支持上万并发用户。下载地址:https://www.igniterealtime.org/projects/openfire/
协议的介绍
网络上很多,本文不再赘述,贴几个随手能搜到的帖子:XMPP-百度百科
XMPP协议实现原理介绍
示例代码
初始化
config = new ConnectionConfiguration(host, port, serviceName); config.setDebuggerEnabled(true); config.setCompressionEnabled(false); config.setReconnectionAllowed(true); config.setSecurityMode(SecurityMode.disabled); // 是否开启TLS SASLAuthentication.registerSASLMechanism("MyMechanism", MyMechanism.class);// 新增自定义的登录校验机制 SASLAuthentication.supportSASLMechanism("MyMechanism", 0); // 设置登录校验器的序号,序号小的会优先选择
serviceName即openfire的domain,可以在openfire管理台上查到,一般为计算机名。
asmack默认集成了”DIGEST-MD5”、”PLAIN”、”ANONYMOUS”等几种校验器,具体参考源码:SASLAuthentication.java
登录
connection = new XMPPTCPConnection(config); connection.addPacketListener(new PacketListener() { @Override public void processPacket(Packet packet) { processReceivedMessage(packet);// 接收消息后的处理,可以根据消息类型做业务逻辑 } }, new PacketFilter() { @Override public boolean accept(Packet packet) { return true; } }); connection.connect(); connection.login(userName, password, resource);//resource为资源名,可以为空。
连接相关操作不能在主线程中进行。
userName为”JID”,假如我们在openfire上创建一个用户名为abc,那么JID为abc@domain。
实际测试登录方式为DIGEST-MD5时,userName带上@domain,”PLAIN”时可以只传abc。
DIGEST-MD5登录过程交互
客户端打开stream流<stream:stream to="mypcname-f" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
服务端打开stream流
<?xml version='1.0' encoding='UTF-8'?> <stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="mypcname-f" id="akgn03i374" xml:lang="en" version="1.0">
服务端返回特性列表
<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>SCRAM-SHA-1</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>
客户端选择鉴权机制
<auth mechanism="DIGEST-MD5" xmlns="urn:ietf:params:xml:ns:xmpp-sasl"> </auth>
服务端返回挑战码
<challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09ImYwMDE5NDYwMy1m...2Vzcw== </challenge>
客户端回应挑战
<response xmlns="urn:ietf:params:xml:ns:xmpp-sasl">dXNlcm5hbWU9ImZzdEBmMD......dlNKQVJKRzhTdWci </response>
服务端返回鉴权结果
<success xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cnNwYXV0aD0...U5NTc2MDIxMA== </success>
客户端重新打开stream流
<stream:stream to="mypcname-f" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
服务器端重新打开stream流
<?xml version='1.0' encoding='UTF-8'?> <stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="mypcname-f" id="akgn03i374" 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"> <optional/> </session> <sm xmlns='urn:xmpp:sm:2'/> <sm xmlns='urn:xmpp:sm:3'/> </stream:features>
客户端发送资源绑定请求
<iq id='uhNnW-13' type='set'> <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'> <resource>xxxResource</resource> </bind> </iq
服务器返回资源绑定响应
<iq type="result" id="uhNnW-13" to="mypcname-f/akgn03i374"> <bind xmlns="urn:ietf:params:xml:ns:xmpp-bind"> <jid>fst@mypcname-f/xxxResource</jid> </bind> </iq
客户端发送创建会话
<iq id='uhNnW-14' type='set'> <session xmlns="urn:ietf:params:xml:ns:xmpp-session"/> </iq>
服务端响应会话创建成功
<iq type="result" id="uhNnW-14" to="fst@mypcname-f/xxxResource"/>
客户端发送初始化presence
<presence id='uhNnW-15'></presence>
支持SSL协议的登录
制作服务端和客户端证书
openfire默认会生成服务端的证书以及keysotre,但这个证书是颁给域名(默认是计算机名)的,我们在拿手机测试过程中很可能需要直接通过IP地址访问,这时候默认生成的证书在SSL/TLS握手过程中会被认为不合法,无法建立SSL/TLS连接。本文借解决该问题,简单描述如何使用自签名证书在TLS下进行XMPP登录。证书不合法一般原因不外乎以下几种:签发机构不合法(自签名证书)、有效期过期、颁发的域名与访问域名不同等等,我们使用keytool命令制作合法的自签名证书,然后让客户端信任该证书公钥,解决本问题。
生成自签名证书及keystore(服务器端使用),其中CN字段填写openfire所在的ip地址
keytool -genkey -alias mycert -keyalg RSA -keysize 1024 -keystore server.keystore -validity 365
修改openfire设置,指向该keystore文件。
菜单:服务器-TLS/SSL Certificates,修改其中的Identity Store的File字段,改为我们刚生成的server.keystore
从keystore中导出证书公钥
keytool -export -alias mycert -keystore server.keystore -file mycert.crt
将公钥证书导入另外一个keystore(可以不存在,会直接创建),供客户端使用
keytool -import -alias mycert -keystore client.keystore -storetype bks-v1 -file mycert.crt -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath C:/Users/mypcname/Desktop/tvms/bksprovider/bcprov-jdk15on-155.jar
默认keystore的类型为JKS,安卓要求使用BKS,这里需要额外下载一个jar包,并指定keystore类型为BKS
客户端代码打开TLS,并且加载这个证书
config.setSecurityMode(SecurityMode.enabled); InputStream ins = null; >文件均以放在src/main/assets下为例
方式一:加载keysotre文件,需要指定keystore密码
ins = OTTSDK.getApplicationContext().getAssets().open("client.keystore"); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(ins, "changeit".toCharArray());
方式二:加载证书文件,可以为X.509的crt或者pem格式。
ins = OTTSDK.getApplicationContext().getAssets().open("mycert.crt"); CertificateFactory cf = CertificateFactory.getInstance("X.509"); X509Certificate x509Certificate = (X509Certificate) cf.generateCertificate(ins); KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); ks.load(null); ks.setCertificateEntry("xmppCert", x509Certificate);
设置SSLContext
// set TrustManager and SSLContext. TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(ks); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, tmf.getTrustManagers(), new SecureRandom()); config.setCustomSSLContext(sslContext);
引用
csdn指导文档,涉及客户端和服务端软件,以及客户端样例代码:http://blog.csdn.net/h7870181/article/details/8653865
openfire使用和配置:
http://www.cnblogs.com/hoojo/archive/2012/05/17/2506769.html
Connecting to a server that uses a self signed certificate:
https://community.igniterealtime.org/thread/56000
Extensible Messaging and Presence Protocol (XMPP):
https://xmpp.org/rfcs/rfc3921.html
相关文章推荐
- XMPP使用简单介绍--登录
- Log4j 的使用以及简单介绍
- Core Animation基础介绍、简单使用CALayer以及多种动画效果
- libevent简单介绍以及使用(带有服务器和客户端)
- 字符理论--hzk16的介绍以及简单的使用方法 (转)
- Core Animation基础介绍、简单使用CALayer以及多种动画效果
- 原来win+apache实现ssl的证书认证如此简单 +使用openssl来生成CA证书、申请证书、颁发证书以及撤销证书的过程
- mongodb简单介绍以及使用整理2
- 玩转web之servlet(六)---session介绍及简单使用(登录验证中保存信息)
- xmpp学习使用简单介绍(二)
- hzk16的介绍以及简单的使用方法
- Core Animation基础介绍、简单使用CALayer以及多种动画效果
- Core Animation基础介绍、简单使用CALayer以及多种动画效果
- 玩转web之servlet(六)---session介绍及简单使用(登录验证中保存信息)
- C#关于log4net(Log For Net)的使用 简单说明以及介绍
- Core Animation基础介绍、简单使用CALayer以及多种动画效果
- iOS开发证书和Profile文件 介绍以及使用
- 安卓多线程#1--ANR异常以及Handler类使用方法介绍
- Linux登录界面以及简单使用入门
- 玩转web之servlet(六)---session介绍及简单使用(登录验证中保存信息)