二、架构
系统从总体上分为两部分,一部为企业的EBS及接口系统,第二部分为第三方厂商自建系统。
在企业总部系统部分,又分为两部分,一部分为WS接口系统,第二部分为原始EBS系统。
在EBS部分,又可以分为正式表和接口表两部分。
整体需求在技术上分为两类:
Ø 只读EBS
WS直接从EBS生产表或接口表中读取数据,因为不涉及到写入操作,所以只要清楚数据库结构即可得到所需要的数据;
Ø 读写EBS(需要交互)
这部分工作比较复杂,需要对EBS进行写入操作,因为EBS的复杂性,需要把内容写入到接口表中,由标准请求来处理接口表到正式表的导入。
在数据导入到正式表的过程中,有可能发生验证失败的情况,这种情况下,标准请求一般会在接口表或其它地方记录出错的信息,如果第三方需要这个信息,可以调用接口表从而得出相应的结论。总之,第三方与EBS的交互可以靠两种方式组合得出,但是交互的效率可能会相对稍慢,即中间有一定的延时。
所谓标准请求,是指EBS自带的一些功能,至于它都有哪些标准请求,需要查阅EBS的相关文档,它们有的就是有,它们没有的,谁也不能提供。
在技术架构方面,WebService接口部分采用Visual Studio 2008来开发,因为WebService与具体的程序语言无关,所以只要使用标准的接口规则,就可以被多个第三方厂商所使用。
三、WebService接口实现
WS服务器采用Windows2008+IIS来实现,由WS来实现第三方厂商与EBS的沟通及交互,保证第三方厂商的系统(无论是在总部还是在海外IDC)都可以顺利的与EBS进行通讯。在接口实现这一部分,将分多个部分进行说明:
Ø 安全通讯
在第三方与WS通讯的时候,需要考虑通讯的安全性,WS本身将采用HTTPS的方式来工作。
因为不能保证全部第三方系统都能采用域验证的方式来使用,所以在数据传输上,还需要考虑一些更通用的WS的验证方式。
在每新增加一个第三方厂商的时候,系统会分配给他们一个密码串(32字节),这个密码串是每个厂商(系统)唯一的,也不会在不同的厂商之间互相通报,每次数据发送,都会带着这个密码串一起发过来,这样可以首先确定上载数据的合法性,同理,数据下传的时候也会采用此种方式。
Ø 灵活性
WS设计的原则应该是尽量把数据库表进行封装,使得第三方无须过多的了解EBS的表结构即可以正常工作,但是同时还要考虑WS的扩展性,所以不能做太多的接口函数,应该尽量采用Schema的方式来描述,每个Schema将与具体的业务及操作相对应,Schema的扩展相当灵活,可以随着业务的发展和新的第三方厂商的介入不断的完善及发展,形成一个标准的EBS接口Schema库,并形成相应的说明,可以挑选合适的Schema来使用。
到此为止,我们只说明了实现的两个方面,安全性和灵活性,在下一期中,我们将对其它几个方面进行说明。
Ø 读取数据
读取数据使用专门的接口函数,并且只有一个函数,可以做几次重载来实现不同的需要,更多的情况是靠schema参数来区分操作的类型,返回的类型为XML文件,并且第三方会知道按何种方式来拆解此返回的XML。XML可以是单表,也可是多表的记录集的形式,具体返回格式完全由Schema来指定;在返回之前,考虑传输的效率,需要对返回的数据进行压缩,然后再二进制数组的形式来返回
² 函数原型
public byte[] GetData(string schemaName,string whereClause,string password) //取出指定条件的记录集
² 参数
schemaName
指定的模式名称,对于模式及模式的使用方式,在后面会有专门的描述
根据指定的模式,系统会找到相对应的表,返回所需要的字段
whereClause
它是根据一个查询条件来返回记录,这样可以实现很复杂的查询功能,返回的记录集遵循指定的Schema
password
由系统分配给第三方厂商(系统)的一个hash串,作为唯一的标识,服务器端接收到消息后,会检查这个密码串的合法性,如果系统中不存在这个串,则不能进行任何操作。
关于密码串的具体说明和用法,在后面有专门的描述。
² 返回值
返回值一律为字节数组,而不采用XML直接返回,这样可以在传输之前做更多的处理,比如压缩和加密,本次设计中暂不包括加密处理,压缩采用标准的压缩算法。
第三方在收到字节数组后,使用标准的压缩算法将其解开,还原成一个XML文件
在第三方客户端,会存在相应的Schema来解析这个XML,具体使用哪个Schema,由客户端自己来把握,与服务器端无关,信息拆解后如何使用,也由客户端自己把握。
如果操作失败,返回的错误也会按字节数组的形式来返回,所以客户端接收后首先要检查操作是否成功,如果确认没有失败,再去检查具体的返回内容。
Ø 写入函数
写入动作是指由客户端发起,向服务器写入相关的内容,在本系统中,写入的内容与业务无关,全部抽象为技术层面来处理。
² 函数原型
public byte[] WriteData(string schemaName,byte[] content,string password)
² 参数
schemaName
与读取函数的功能相似。
content
要写入的内容,在客户端生成,首先生成一个XML文件,与schemaName相对应,生成XML后,在客户端进行压缩和加密等操作,生成一个二进制的字节数组上传 到服务器。
password
与读取函数功能相似。
² 返回值
与读取函数类似,返回字节数组,客户端先要对其进行解压和解密方可使用,尽管很少量的内容返回压缩后反而会更大,但是为了统一的管理方式,仍采用这种方式来工作。
Ø 数据传递
数据为双向传输,即有些是从第三方系统写入EBS,有些是从EBS读取返回给第三方系统。
对于单向读取(EBS->第三方),没有数据一致性的风险,直接返回即可,完全通过Schema的添加和配置就可以实现数据安全有效的控制。
但是对于另一个方面的传输(第三方->EBS),就存在着一个比较敏感的问题,因为EBS的数据结构非常复杂,很难完全掌握它的结构,所以这个方向的传输,一定要把握一个原则,就是只能写到EBS的接口表中,不能直接写入生产表。这部分内容会在Schema部分有更详细的说明。
在下一期中,我们将来详细的介绍一下系统的安全性。
四、安全体系
在上面的章节也提到了数据的安全及一些策略,在此将详细的论述安全的数据传输。
Ø SSL体系
这是一个网络层的解决方案,具体做法是在IIS上配置相应的SSL证书,从而实现一个SSL的站点,安全证书采用VeriSign,可以从中国的代理机构购买。
SSL的方式会增高系统的安全性,但是也会对性能有一点点的影向,不过不会成为系统的性能瓶颈。
另外还需要验证是否所有的第三方厂商在写程序的时候都支持这种SSL方式,因此这个体系作为一个可选件存在,可以随时启用,不影响整体的架构。
Ø 压缩与加密
当数据在客户端与服务器通讯的时候,如果不采用SSL的方式,则信息在internet上是可以被截获并破解的,为了解决这个问题,需要对数据做一定的预处理,然后再 进行传输。
压缩是必选项,采用标准的ZIP压缩算法,客户端采用何种工具进行压缩和解密由客户端自己把握,不提供专门的处理函数。
对于加密算法,可以采用标准的加密算法,也可以采用自己定义的简单加密算法,也可以暂时不考虑加密,只用压缩来处理,本期暂不考虑加密算法。
Ø 密码串(识别码)
系统会为每个第三方厂商(系统)分配一个唯一的识别码,为了加强此识别码的强度,采用32字节长度的密码串,此密码串本身没有任何含义,只作为唯一的标识,加大它的长度,即减少了被盗用的风险。
关于密码串的分发,不考虑程序实现,只用手工处理即可,可以使用邮件的方式来发送。
为了验证密码串,需要服务器端与客户端都同时存储这个密码串,这样才可以验证。这里的服务器指的是WebService服务器,而不是EBS服务器,因为不方便在EBS中添加过多的定制化内容。
在服务器端,密码串的存储可以直接使用XML文件或平面文件都可以,这个可以在具体实现的时候再决定,在文件中仅需要简单的存储以下信息:
² 密码串
用于沟通的字符串,32字节长,手工产生,随意生成,没有规则,只要保证能正确下发到相关的第三方厂商手中即可。
² 厂商名称
用于标识,系统中不使用此标识。
² 有效起始日期
大于此日期后,该密码串才被认为是合法的,此字段不能为空,可以靠很小的日期来处理特别情况。
² 有效结束日期
小于此日期,该密码串才被认为是合法的,此字段不能为空,可以靠很大的日期来认为是无限期的,以上两个日期可以随时调整,以更改密码的可用性。
² 创建日期
此条记录添加的日期。
² 创建人(字符串描述)
是谁添加了这条记录。
² 最后修改日期
² 最后修改人
在服务器IIS启动的时候,在Instance_Startup类型的函数中,加上特别的处理,把所有的密码串全部读出来,放入Global变量中(只读取密码串一个字段,其它均不读入),在WebService的GetData/WriteData函数中,首选检查传入的密码串参数是否是合法的,如果是合法的,再继续后面的操作,如果是非法的,直接返回“非法使用”之类的错误。
验证函数如下:
private bool ValidPassword(string password)
客户端收到总部关于密码的邮件后,所有的操作均必须带着这个密码,如果因为密码填写错误,会造成一系列的错误,需要第三方自己把握。
关于密码变更:
密码变更在服务器上需要对原密码的有效结束日期进行更改,并记录更改人;
同时添加一条新的记录,并确认结束日期合法;
最后把新的密码下发给第三方厂商。
Ø 数据库表ACL
原则上客户端会按照约定的规则来读取和写入数据,但是为了防止恶意读写,在此专门设置ACL,控制哪些表可以读写,ACL文件为标准的XML文件,包括以下三个属性:
² 表名(大写)
² 是否可读(BOOL型)
² 是否可写(BOOL型)
同样,在系统启动的时候,会把这些信息读入到内存中备用。
Ø 私有信息
同一张接口表中,可能会同时有多个厂商进行操作,这时要保证不同的厂商之间的操作不会互相影响,为此需要在相应的接口表中找一个合适的字段,来存储厂商的密码串。
在后面的部分,我们将对Schema进行描述,这是数据通信的基本单位。
五、XML Schema
为了实现更通用性的交互,Schema是最重要的一部分。
这里的Schema是标准的模版xsd文档,遵循所有的标准规格。
关于XML Schema的详细内容,在此不做描述,可以从其官方网站上得到解释。
在读取数据和写入数据的时候,都会用到Schema,Schema就是用来实现对原始表的一个映射。
在服务器端(WebService服务器)和客户端都存在一份Schema列表,在服务器上存储全部的Schema,但是在客户端,只存储和自己业务相关的部分,不会存储全部Schema。
Ø 数据读取
Schema文件用于数据的描述,但是和数据库本身没有任何依赖关系,现在需要根据这个Schema来得到一个SQL语句才可以去数据库里取数据。为了简单快速的实现Schema与SQL语句的转换,可以再写一个专门的文件,文件名与Schema相同,扩展名为.select,表示是一个选择数据的SQL语句,此文件只存在于服务器上,客户端不知道此文件的存在。在Instance_Startup的函数中,将所有相关的SQL全部一次性读入到内存中,方便后期快速使用,当然如果有任何这种文件的变化,都需要IIS的重新起动。
对于where条件,可以作为一个字符串直接拼接在SQL后面,得到一个真正的SQL语句,SQL中没有参数的概念,拼接完成的SQL,在数据库中可以直接使用,为保证SQL的可用性,客户端在写where条件的时候一定要遵循一定的规则,包括and / or 之类的匹配关系,小括号/单引号的使用等,一定要正确。
对于标准的XML的生成,有两种方案:
如果Oracle10g支持XML SQL,可以直接生成符合xsd标准的XML文件;
如果不支持,只能返回一个DataSet,再参考Schema的格式,手工生成一个XML文件。
生成XML后,调用压缩工具包对其进行相关的压缩处理,生成二进制数组,直接返回。
如果使用过程中发生错误,则返回“查询错误”之类的代码,可以把相关的错误代码返回。
在读取之前,需要判断此表在ACL列表中是否可读(如果不好判断,可以跳过此步骤,因为SQL不是客户端可以更改的)。
Ø 数据写入
数据写入的函数里面有一个字节数组,首先对其进行解压及解密,生成一个XML文件,此文件与Schema配合,读入系统成为一个标准的DataSet,此时可以利用现有的技术直接把该内容写入到数据库中,在写入之前,一定要去ACL中检查一下,此表是否可以写入。
六、EBS端相关操作
所有的写入操作均写入EBS的接口表中,不会直接写入正式表,因此写入接口表中后,需要调用EBS的标准请求来把接口表写入正式表。
关于接口表,不同的模块有不同的接口表,并且有不同的操作方式,有不同的请求来实现,所以需要根据实际的接口情况,考虑EBS的接口表及标准请求,并研究标准请求返回的错误信息及含义,还有就是错误返回的存储位置,有些直接回写入接口表,有些会写入标准的错误日志表中,具体在操作的时候再确定。
七、总结
以上方式已经在我公司得到真正的应用,并已经为多个业务系统服役,使用效果良好,希望大家参考后能有所帮助。
本文转自Aicken(李鸣)博客园博客,原文链接:http://www.cnblogs.com/isline/archive/2010/04/15/1712428.html,如需转载请自行联系原作者