如何实现web项目单机部署

  • 实现目标
实现项目部署包仅能在指定服务器部署,不可更改。更换位置,无法正常启动和访问。目前还没有完美的解决方案,有些思路还待验证。

  • 实现方案
校验规则

校验当前服务器mac地址是否匹配

启动报错提示

方案1:自定义servlet,load-on-startup设置为0,在init方法中校验
方案2:定义ServletContextListener,在contextInitialized方法中校验
可考虑在校验失败的情况下删除项目文件。该方案通过修改配置文件,从而屏蔽掉校验,安全级别不高

禁止非指定server部署访问

为了禁止非指定server部署访问,可在action层、service层进行校验,校验失败返回状态信息。

Action层校验:AOP实现,cglib动态代理,@before中进行校验,校验失败抛出自定义异常,配置自定义异常友好提示页面。但是像启动报错提示一样,也可通过修改配置文件屏蔽校验,且不影响使用,安全级别不高。

Service层校验:代理实现(静态代理、JDK代理、cglib代理),静态代理需要很多代理类,后两者需要使用spring集成,因为如果项目已使用代理(例如事务、日志),自定义代理类实际代理的是spring已代理后的类,无法代理成功(不知道是否特殊处理后可以,但明显不是一个好的方案)。和Action层校验一样,也存在修改配置文件屏蔽校验的问题。

最小硬编码非配置文件实现

在Action层取消依赖注入机制,通过自定义FactoryBean间接获取Service层对象,校验失败捕获异常。代码如下:
public static Object getBean(Class cl) throws NoAssessException{
		Object bean=null;
		if(AssessUtils.isAssess()){
			bean=SpringContextUtils.getBean(cl);//从spring容器里获取bean对象
			bean=context.getBean(cl);
		}else{
			throw new NoAssessException("This server cannot run this 					service.");
		}
		return bean;
}

service调用:
HelloWorldService helloWorldService=(HelloWorldService)FactoryBean
.getBean(HelloWorldService.class);
helloWorldService.helloWorld();

因为使用了自定义异常,无法在action层作为私有属性初始化service,只能在具体方法中初始化并捕获异常,增加了类代码量。好处在于明确问题原因,并给予友好提示。

改进方案:校验时不抛出异常,使其可作为变量定义,减少action层具体方法中重复获取service对象。缺点在于异常状态为空指针异常,无法给予友好提示。

缺点:1、改变了常用的依赖注入的对象调用方式;2、service层校验需要过action层;3、反编译源码后,也很容易全局屏蔽掉校验

待验证方案

以上方案安全级别都不高,以mac地址等对类文件进行加密,自定义类加载器以当前server的mac进行解密,这样是否会好一些。
需要解决的问题:1、如何自动进行类加密(工具类手动可以,希望有更好的方案);2、如何全局引入自定义类加载器,最好可以集成在spring中。

接下来有空研究,以下两篇Classloader的文章可以参考:
http://www.inter12.org/archives/702
http://bingobird.iteye.com/blog/606116

已验证:未完美解决
http://sheungxin.iteye.com/blog/2352833

猜你喜欢

转载自sheungxin.iteye.com/blog/2346332