Dirain的开源地带

思想在进步
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一次C#客户端与Java Web服务器的交互经历(求助)

Posted on 2008-11-24 21:59  Dirain  阅读(3943)  评论(14编辑  收藏  举报

   公司即将要做一套客户端系统,C#开发。在客户端中有很多涉及到money的地方,所以不得不与数据库交互一下。

   问题由此而来,所以今天在陪伴我学习.net的博客园求助。

    

   如果是公司内部使用一套客户端系统,可能常见的方式就是通过客户端直接连接内部的数据库服务器进行数据交互。由于是企业内部使用的原因,所以不需要考虑数据安全问题。可我们需要开发的是一套面向N位客户的一套软件,这样我们就无法保证用户的水平。如果从某个方面稍微发生一点失误,我们的数据库可能就直接被download掉了。毕竟连接数据库的帐号和密码可能是保存在客户端程序中的,通过反编译的方式可以直接查看到所有连接信息。即使加密,也有可能被解密掉。

   最初想到了一套模式,就是稍微复杂一点的客户端对Web Service数据操作,这样可以避免客户端直接对数据库操作,而且以后数据库的改动也不会影响到客户端,从各方面都很有优势。在实施前团队又对此方案进行了一系列讨论及研究,最终还是被暂时pass掉。因为数据量大时,先对web服务器交互得到结果就够呛了,还需要在解析xml,这也不是一件轻松的事。就这样,开始去网上求助,最终也没有得到好的结论。

   先放弃的数据交互的开发后开始的短信相关的业务,新的任务来了,通过华为的MAS系统进行短信发送。API都是华为提供好的,应该是C开发的API,难度到不是很大。可安全问题又来了,而且使用API的要求也比较bt,必须装有db2的驱动程序。因为使用需要引用华为提供的dll,并且在使用时需要连接我们的企业帐号及硬件设备。这样一些敏感的连接信息还是被暴漏在程序源代码中,反编译出源码后还是会让别人免费的发短信。不得不把短信相关业务封装到Web Service了。公司的Web服务器是已经配置好的Java环境,没必要在去配置.net的。所以Web Service的开发我选择了java中的XFire框架。没必要的东西先不说了,给大家说说我的具体操作流程,帮我看看可能会存在什么问题,毕竟我在技术方面不是很专,先谢谢各位了。

   直接让客户端与服务器的Web Service交互肯定不是一个好办法,如果用户抓取到了Web Service的连接地址,这样又让人家免费玩了。所以我在初步设计时想到了在客户端每次调用服务器时用一个帐号密码验证,并将其进行加密。写着写着,发现问题又来了。客户端去连接Web Service的最终原理肯定是http请求,这样如果用户拦截了本机的所有请求就能马上暴漏我们的Service地址和参数,然后直接自己写个程序去模拟这个请求,这样不管在客户端进行多么高级的加密,还是会被直接绕过验证。于事进化了我的想法,通过一个随机的值每次发送到Web Service,然后Web Service去验证。最初想到的是通过时间并加密的一个值去验证,因为时间时唯一的,而且还能保证客户端和服务器一致。呵呵,过了一会还是pass掉了自己的想法,因为万一客户端与服务器时间不一直,那此功能直接废掉,因为时间不同步,加密出来的值不同,在加上网络的各种延迟,肯定会导致这个验证方式不成立。

   因此,想法又进化了一步。从Web Service的初始化方法中生成一个NNID(C#中的GUID,java叫NNID)此ID被记录,N分钟后自动销毁(销毁后客户端会从新实例化类,产生新的NNID),再从服务器生成一个1-10以内的随机数(做什么后面会说)。然后从客户端得到这个值,在为Web Service提供一个登陆方法,每次登陆都传入一个从客户端加密的值。至于这个客户端加密的值,就是通过服务器产生的NNID进行加密,加密的次数由上述说到的随机数决定,假设随机数为3,就加密3次。刚刚说的是从客户端加密一个从服务器产生的唯一值,所以我们需要从服务器进行相同算法和相同次数的加密,最终比较服务器端的加密结果与客户端产生的结果,如相同,则说明验证成功!可能我这个方法比较笨,所以需要大家提供更多的意见。下面我来解释一下为什么要这么做,我考虑到了如下几点。

  1. 如按上面的方法进行交互,假设用户得到了我的Web Service地址,那么你还得去验证,可能这时大家会想到我直接抓出你所有的请求参数,模拟这个请求不就OK了吗?刚才说到NNID会被记录在某个地方,N分钟会被自动销毁。
  2. 假设用户抓到了这个地址,那么用户也无法脱离了我的客户端去直接使用我这个Web Service,因为我的NNID被加密了,他光知道还不行,而且NNID被加密的次数还是随机的,他还要即时去掌握加密了多少次才能成功验证。
  3. 可能用户会反编译我的程序,然后看看我是怎么进行加密的。那我可以把我的加密算法通过C++去实现,生成一个dll文件,并对这个dll文件进行加壳,防止反编译,这样就能保证我的加密算法不泄露。
  4. 就算用户可以脱离我的程序去使用,那么用户也只能使用N分钟而已,因为N分钟后就要销毁这个ID了,这时用户验证就无法通过了。因为NNID号称全球唯一的,出现重复的几率非常低。而且我在服务器对每次验证都进行记录,如果一旦发现某用户验证出现错误,那说明肯定存在问题,这时可以直接屏蔽掉这个用户,不允许去使用。

   这就是我想到的方式,现在已经实现了,预想的效果跟我想象的一样,就是在管理NNID时可能浪费一点内存,但我想以后应该可以进行优化,比如用户多了可以存储在数据库中,这就是我很天真想法,我技术方面还不行,我真心希望博客园的兄弟们能够给我一些指点,我可能很多细节没有考虑到,谢谢!