Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-use
rname-token-profile-1.0#PasswordDigest">GuYUMn8WZVIkrYhxUWP4xVuzR
/Xwji3kRxiBn4Xy2vRpWn+JngZvQ+oMn3sdv5vNaaOhOQze/M8iZgIjPZMAyhwOU+
xVwLcEtQUJcIHUNB8Hqq0z5mzUhwnqNNlcXTLJ
rJYdxJDVfEdn4Ngm94Sd
PhPzu4Y=
2013-02-20T07:35:38Z
加密算法说明:
a) 首先双方拥有明文的账号名和密码(通过电话等交流方式获取):
Username: MD5(schoolID), Password: somepassword
b) wsse:Username 的值为:学校代码 MD5 的 HEX 小写字符串
c) wsu:Created 的值为创建时间(UTC):2013-02-19T13:31:47Z
d) wsse:Nonce 的值为随机串:如 base64(SHA1(createdTimestamp + Math.random()))
e) wsse:Password 的值为:
使用 AES-128-CBC,PKCS5Padding
生成 KEY 和 IV 的方法:
str = MD5(wsse.Nonce + “somepassword”)的 HEX 小写字符串(32 字节)
AES 算法的密钥:key = str 的前 16 字节
AES 算法的初始化向量:iv = str 的后 16 字节
原文 = wsse.Nonce + wsu.Created + str
最终密文 = base64(CipherAES128CBC(原文, key, iv))
过期时间:1 分钟
平南小学学校代码:(测试,需要提供)
平南小学账号:
UserName: 9110776(MD5 为 b285171fd0a21885d4be1240e522516d)
“somepassword”: &919aalZ]q/`*&Sl2L:}!(*#=+2klj&&^@ls7_Z
3. 数据包结构
学校服务器发送的数据:
JSON Object:
名称
dataType
类型、格式
uint
data
JSON Object
说明
数据包业务类型
1:刷卡事件
相关数据
对于刷卡事件,data 对象里的数据定义:
eventID
String
schoolID
stdMainNO
stdNO
cardNO
eventTime
eventType
String
String
String
String
String
2013-01-01 18:17:16
uint
如:1
stdName
className
UTF8 String
String
如:1108
学 校 刷 卡 服 务 器 数 据 库 里 面 存 储 的
EVENT_ID,唯一
学校代码
学籍主号
学籍副号
硬件卡号
刷卡时间(UTC)
事件类型,数字
0 代表入校
1 代表离校
2 代表请假(离校)
学生姓名
所在班级
内容为四位数字
第一个数字代表学校:
1 小学
2 初中
3 高中
第二个数字代表年级
后两个数字代表班级
例如:
2118 表示“初一(18)班”
示例:
{
dataType: 1,
data: {
eventID: ”1220001”,
schoolID: “9110776”,
stdMainNO: “4112321024023491041”,
stdNO: “3100200202010910100”,
cardNO: “3230202928288410010”,
eventTime: “2013-01-01 18:17:16”,
eventType: 1,
stdName: “王小虎”,
className: “(一)五班”
}
}
4. 数据加密方式
假设原始数据为 JSON Object:
{
dataType: 1,
data: {
eventID=” 1220001”
„„
}
}
将原始数据转换 JSON 字符串(UTF8 编码),然后进行 AES-128-CBC PKCS5Padding 加密,
并转换为 BASE64 编码:
公钥为:
(J1'mnw^o291KA[:_w]`LA7w.Q/~sb%2&V6K=j#Hr+wu^>x-
2013-02-20T07:35:38Z
2013-02-20T07:45:38Z
b285171fd0a21885d4be1240e522516d
GuYUMn8WZVIkrYhxUWP4xVuzR
/Xwji3kRxiBn4Xy2vRpWn+JngZvQ+oMn3sdv5vNaaOhOQze/M8iZgIjPZMAyhwOU+
xVwLcEtQUJcIHUNB8Hqq0z5mzUhwnqNNlcXTLJ
rJYdxJDVfEdn4Ngm94Sd
PhPzu4Y=
2013-02-20T07:35:38Z
tprSS5lUQiBc1Mmnry5oHKdlcs4iLXuWF0sGhELE7L6fa3BpqQm0kkEGIu
nZIsAgLNeENju1DlpgnmBfsjCwvpNOAfXfAYZksrOKx7y+5FUTH6D/+bVg6UdLQml
xOiVj++v5HtYJJK20wKyaLhDCLPdysLxGkx5WcfFv/2EMB/UjFp6r7n2QU//l9DJW
vM4RMTh6cwqV/O+YWWpEm+0pn9OHsEUETwvuHbkv8qMDZ/D8f5Y6B9g9esFUWlysi
WZlLZrwHMuYEhREYaRzwWJcH/p703tZMo9aMAiKTrq3lQ/ZMPRGEWnLbVm2F2VpdR
wR
[RECEIVE]
tprSS5lUQiBc1Mmnry5oHKdlcs4iLXuWF0sGhELE7L7UR7zV2ez7IlTBYlbIrPTp
6. 关于 AES-128-CBC 加密
上文中提到的所有的 AES-128-CBC 加解密,首先需要将初始密钥转换为 MD5 的小写 hex
字符串(共 32 字节),前 16 字节作为 KEY,后 16 字节作为 IV
例如:
原文为 123,密钥为 abc,
则 MD5hex(“abc”) = ” 900150983cd24fb0d6963f7d28e17f72”
key = ” 900150983cd24fb0”
iv =” d6963f7d28e17f72”
密文为:
base64(CipherAES128CBC(“123”, key, iv)) = “z1n9Ur0O0fWs0eeIq6fkJg==”
三、环境搭建
选择的技术为 node.js,要在 node.js 平台上实现 webservice,首先要安装 node.js,
然后提供一套完整的服务端/客户端 webservice 模块,这个模块可以使用第三方的
模块,根据项目的需求,在 www.npmjs.org 中找到了 node-soap 这个模块,初略看
了一下它的文档说明,提供了完整的 webservice 通信框架,以及项目需要的加密
方式。创建一个项目工程,并在项目中使用 npm 命令安装 soap 即可,也可直接下
载最新的压缩包。参照官方的文档,既可以开始编写项目代码了。
四、代码编写
1. 编写 WSDL 文件 要确定 webservice 提供的服务以及相应的接口数据结构等,
需要使用 WSDL 对 webservice 进行描述。有关 Webservice 的的知识可以在
www.w3chool.com 中的 webservice 中进行学习和了解。根据项目的要求,生成
WSDL 文件,如下:
Client 示例:
var soap = require('soap');
var url = 'http://example.com/wsdl?wsdl';
var args = {name: 'value'};
soap.createClient(url, function(err, client) {
client.MyFunction(args, function(err, result) {
console.log(result);
});
});
这是 node-soap 模块的示例,根据实际情况,将其修改为:
var soap = require(‘soap’);
var url = ‘http://127.0.0.1:8000/ CardEventListener?wsdl’;
var args ={
dataType: 1,
data: {
}
eventID: ”1220001”,
schoolID: “9110776”,
stdMainNO: “4112321024023491041”,
stdNO: “3100200202010910100”,
cardNO: “3230202928288410010”,
eventTime: “2013-01-01 18:17:16”,
eventType: 1,
stdName: “王小虎”,
className: “(一)五班”
};
Soap.createClient(url,function(err,client){
Client.newEvent(args,function(err,result){
Console.log(result);
});
});
这样一个最基本的客户端就搭建起来了,按照文档的描述,还需要增加对用户
身份的加密,对数据的加密。
为客户端增加身份验证。