前提:已获得 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. 主流ETL(Extract-Transform-Load)工具选型,Kettle Spoon、Datastage、Powercenter介绍

    参考:三大主流ETL工具选型 ETL工具 Kettle Spoon 开源ETL工具,所以免费,用java开发的. Ascential公司的Datastage(在2005年被IBM收购现在是 IBM 的 ...

  2. SELECT控件add方法 ie 类型不匹配

    s = document.createElement('select'); try{ //for ie8 or earlier s.add(new Option('text','value'),s.o ...

  3. jmeter ---常用字符串相关函数

    主要的函数如下: 1.将字符串转为大写或小写: ${__lowercase(Hello,)}  ${__uppercase(Hello,)}2.生成字符串:  __RandomString函数 3.取 ...

  4. selenium 并发执行测试用例

    转帖: 要想多线程并发的运行WebDriver,必须同时满足2个条件,首先你的测试程序是多线程,其次需要用到Selenium Server(selenium-server-standalone-XXX ...

  5. OAF_OAF控件系列8 - SubTab的实现(案例)

    2014-06-02 Created By BaoXinjian

  6. starUML破解方法(Windows10 & MAC)

    安装好,打开安装目录,依次找到[www\license\node],找到名为[LicenseManagerDomain]的js文件,打开它,在第25行位置插入以下几句代码: return { name ...

  7. Mark 装修建材 清单

    装修攻略 介绍 装修公司:东易.龙发.金螳螂.乐豪斯乳胶漆:多乐士,立邦.三棵树.晨阳水漆.华润.都芳瓷砖:马可波罗.东鹏瓷砖.蒙娜丽莎.诺贝尔.简一瓷砖.欧神诺瓷砖.金舵瓷砖.卓远瓷砖.鹰牌.兴辉瓷 ...

  8. java线程高并发编程

    java线程具体解释及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了.看看百度百科对他的评价,一点也不为过: 假设IT的历史 ...

  9. Is "UNION ALL" Always Better Than "UNION"? Watch Out!

    无论是教科书还是平常的实践都告诉我们 - “尽量避免用UNION,尽可能用UNION ALL替代”. 原因很简单,UNION会对结果集进行排序去重操作,这是一个很消耗资源的操作. 但是,今天碰到了一个 ...

  10. nginx中配置404错误页面的教程

    什么是404页面如果网站出了问题,或者用户试图访问一个并不存在的页面时,此时服务器会返回代码为404的错误信息,此时对应页面就是404页面.404页面的默认内容和具体的服务器有关.如果后台用的是NGI ...