前提:已获得 APNS 证书 ,已完毕 MDM 配置描写叙述文件的制作。请參考《 MDM 证书申请流程 》一文和《配置MDM Provisioning Profile》。

环境:OSX 10.9.2,JDK 1.6。Eclipse JavaEE Helois,Tomcat 7.0

一、前言

《THE IOS MDMPROTOCOL》(即Inside Apple MDM)一文中描写叙述了一个简单 MDM Server Python 实现(server.py)。

笔者也曾參照此文配置,但在安装M2Crypto 一步时遇到一个 cc 參数没有定义错误。实在无法进行下去,因此不得不放弃。在參照《基于IOS上MDM技术相关资料整理及汇总》一文时,发现其使用了商业SSL证书(StartSSL)。而笔者使用的自签名SSL证书,有些步骤不太一样 ,另外在一些关键点也须要读者自己摸索,因此有了本文的诞生。

二、准备

无论 APNS 还是 MDM,都须要server实现 https。如果我们使用 Eclipse 调试 Tomcat,则须要改动 Servers 项目以下的Tomcat 配置文件 server.xml。详细过程请參考《开启 Tomcat https 服务》。

三、 实现 checkin URL

MDM 须要实现完整 APNS 服务,对此我们採用的是第三方的 java apns 实现。

主要是 notnoop 的 Java apns(不是google 的 JavaPNS),此外,还有 xmlwise ,用于解析苹果的 plist 文档。

java apns有两个包:apns-0.1.5.jar 和 apns-0.1.5-jar-with-dependencies.jar包。

前者是 API,后者是依赖包。

xmlwise 就一个包:xmlwise-1_2.jar。

数据库採用 mysql。因此也须要 mysql-connector-java-5.1.2-bin.jar包。

此外java apns 使用了slf4j。即 slf4j-simple-1.7.7.jar。

将 MDM push 证书 mdm_push.p12 和 provisioning 配置描写叙述文件 client.mobileconfig 放到WebContent 文件夹下。

用 MySQLWorkbench 连上 mysql 数据库,创建两张表。用于设备注冊:

CREATE TABLE `Authenticate` (

`UDID` varchar(40) NOT NULL,

`Topic` varchar(200) DEFAULTNULL,

`timestamp` timestamp NULLDEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (`UDID`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE `TokenUpdate` (

`UDID` varchar(40) NOT NULL,

`Topic` varchar(200) DEFAULTNULL,

`PushMagic` varchar(200)DEFAULT NULL,

`Token` varchar(200) DEFAULTNULL,

`UnlockToken` blob,

`timestamp` timestamp NULLDEFAULT CURRENT_TIMESTAMP,

PRIMARY KEY (`UDID`)

) ENGINE=InnoDB DEFAULT CHARSET=latin1;

首先看注冊服务。设备注冊由Servlet checkin 实现。其 doPut 方法例如以下:

System.out.println("*********ReceivedMessage:***********\n"+plistStr);

try{

Map<String,Object>plist=Plist.fromXml(plistStr);

if(plist!=null){

StringMessageType=plist.get("MessageType").toString();

if(MessageType.equals("Authenticate")){

Authenticate au=newAuthenticate(plist.get("UDID").toString(),plist.get("Topic").toString());

au.save();

}elseif(MessageType.equals("TokenUpdate")){

Stringregex="Token</key>\\s*<data>\\s*([^\\s]*)\\s*</data>";

String tokenStr=Utils.regxCatch(plistStr,regex);

System.out.println("catches tokens:"+tokenStr);

TokenUpdate tu=new TokenUpdate(plist);

tu.Token=tokenStr;

tu.save();

}

response.getWriter().println(Utils.emptyPlist());

}

}catch(Exceptione){

e.printStackTrace();

}

checkin 主要处理与注冊相关的两种消息:Authenticate 和 TokenUpdate。

在设备注冊中,server首先收到Authenticate 消息,checkin 将之计入 Authenticate 表,然后返回一个空的 plist 文件。设备随后会发来TokenUpdate 消息。checkin 也会将之存到 TokenUpdate 表并返回空 plist 文件。在 TokenUpdate 消息的处理中,checkin获取的是 UDID、device token、push magic和 unlock 等 MDM push中将要用到的重要字段。

当中,token(即 APNS 中的 device token)须要特别注意。

由于在苹果的文档中说,这是一个32位长度的字符串。

实际上我们都知道APNS 中,device token 是一个 byte 数组。

在 TokenUpdate 消息中,iOS 将 device token 的 byte 数组进行了base64 编码,结果变成了一个 44 字节长度的 string。也就是说在 TokenUpdate 消息中。<token>字段的值类型应该是<string>,而不应该是消息中定义的<data>。

一个典型的 TokenUpdate 消息,其 token 描写叙述例如以下:

<key>Token</key>

<data> [ 32 byte string, base64 encoded,redacted ]</data>

显然,这里的<data>必须换成<string>。xmlwise 包中的 Plist 类才干正确解析。

由于在 Plist 类中,对于 plist 文件里的数据类型<data>会被解析为 byte 数组而不是字符串。

因此 checkin 在处理 TokenUpdate 消息时。採取了额外的手段来获取 token 字段,即正则捕获。

执行 Tomcat server,将 iPad 接入server统一 wifi 网络,然后在浏览器中訪问描写叙述文件地址:

https://192.168.2.1:8443/mdmtest/client.mobileconfig

此时 safari 将调用设置程序,在客户端安装 mdm 配置描写叙述文件。当你点击“安装”button,iPad 会请求 checkin URL地址,并发送Authenticate 消息和 TokenUpdate 消息。你能够在数据库中查看到这两条消息。

创建一个简单的 MDM server(1)的更多相关文章

  1. 使用Python创建一个简易的Web Server

    Python 2.x中自带了SimpleHTTPServer模块,到Python3.x中,该模块被合并到了http.server模块中.使用该模块,可以快速创建一个简易的Web服务器. 我们在C:\U ...

  2. spring cloud 创建一个简单Eureka Server

    在Spring Cloud实现一个Eureka Server是一件非常简单的事情.下面我们来写一个Eureka Server DEMO. 编码 父项目pom.xml <?xml version= ...

  3. 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型

    第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...

  4. 编写一个简单的Web Server

    编写一个简单的Web Server其实是轻而易举的.如果我们只是想托管一些HTML页面,我们可以这么实现: 在VS2013中创建一个C# 控制台程序 编写一个字符串扩展方法类,主要用于在URL中截取文 ...

  5. [WCF学习笔记] 我的WCF之旅(1):创建一个简单的WCF程序

    近日学习WCF,找了很多资料,终于找到了Artech这个不错的系列.希望能从中有所收获. 本文用于记录在学习和实践WCF过程中遇到的各种基础问题以及解决方法,以供日后回顾翻阅.可能这些问题都很基础,可 ...

  6. node创建一个简单的web服务

    本文将如何用node创建一个简单的web服务,过程也很简单呢~ 开始之前要先安装node.js 1.创建一个最简单的服务 // server.js const http = require('http ...

  7. 用go和zk实现一个简单的分布式server

    golang的zk客户端 最近打算写个简单的配置中心,考虑到实现便捷性,语言选择了go,由于其中计划用到zk,就调研了下golang的zk客户端,并实现了个简单的分布式server.最终找到了两个,地 ...

  8. 创建一个简单的 http 服务器

    创建一个简单的 http 服务器 直接在 目录下运行 当前的目录即可是root 目录 默认端口8000 应该可以加参数修改端口号 Python2 python -m SimpleHTTPServer ...

  9. 如何创建一个简单 APT 仓库

    0. 无废话版本 需求: 有一堆 .deb 包,想把它们做成一个 APT 仓库,这样就可以用apk install pkgname进行安装了,这样一方面自己可以规避 dpkg -i xxx.deb 时 ...

随机推荐

  1. Android中的Service使用

    Service的生命周期 (适用于2.1及以上) 1. 被startService的无论是否有任何活动绑定到该Service,都在后台运行.onCreate(若需要) -> onStart(in ...

  2. Redis的Docker镜像

    原文地址:https://hub.docker.com/_/redis/ Pull Command docker pull redis Short Description Redis is an op ...

  3. java容器详细解析(转)

    :在java开发中我们肯定会大量的使用集合,在这里我将总结常见的集合类,每个集合类的优点和缺点,以便我们能更好的使用集合.下面我用一幅图来表示 其中淡绿色的表示接口,红色的表示我们经常使用的类. 1: ...

  4. nginx实战五

    nginx用户认证 https://coding.net/u/aminglinux/p/nginx/git/blob/master/access/auth.md 当访问一些私密资源时,最好配置用户认证 ...

  5. chromedriver 下载地址

    重要的事情说三遍 chromedriver 下载地址 chromedriver 下载地址 chromedriver 下载地址 http://chromedriver.storage.googleapi ...

  6. 从jar包中读取资源

    package myspider; import java.io.UnsupportedEncodingException; /** * * @author mark */ public class ...

  7. Zookeeper命令操作

    Zookeeper支持某些特定的四字命令字母与其的交互.他们大多数是查询命令,用来获取Zookeeper服务的当前状态及相关信息.用户在客户端可以通过telnet或nc向Zookeeper提交相应的命 ...

  8. 记一次Animator状态快速切换问题的解决

    事情是这样的,我尝试在一帧内多次切换一些状态(当前状态为Idle的情况下): public Animator animator; void OnEnable() { animator.CrossFad ...

  9. tomcat 源码分析

    Tomcat源码分析——Session管理分析(下)    Tomcat源码分析——Session管理分析(上)     Tomcat源码分析——请求原理分析(下)     Tomcat源码分析——请 ...

  10. vim 学习日志(6):分屏 sp,vsp,分屏移动

    Vim的分屏功能 本篇文章主要教你如何使用 Vim 分屏功能. 分屏启动Vim 使用大写的O参数来垂直分屏. vim -On file1 file2 ... 使用小写的o参数来水平分屏. vim -o ...