Web Service 接口安全与解决方案

12.7.1. 接口安全问题

来源IP控制,即黑白名单,获取IP地址需要考虑X Forward for

IP计数器,单位时间内IP访问次数达到阀值,就提示稍后连接

用户名密码认证

动态验证码

证书加密

md5/sha1 数字摘要 校验

SSL / TSL 证书加密

12.7.2. 访问接口协议

机遇http的实现方式有下面几种。
http协议传统post/get 方式
soap 简单对象访问协议
xmlrpc 机遇xml的协议
json 近年来兴起的一种数据序列化传输方法
http无状态协议,不能保证连接100%有效性。http方式受限制与浏览器,对于并发控制,超时时间,通信数据长度都有严格的限制。
例如:一般浏览器运行超时时间都是30秒或60秒,当你通过http方式访问接口时,你的程序因运行超过30秒被浏览器强行中断;另外当你提交的数据超过浏览器限制长度时也会返回错误。
结局上述问题方法是将借口独立出一台服务器,单独设置超时时间等配制
http 方式有诸多缺陷,当仍被广泛使用,他的特点是容易开发,开发人员不需要额外学习,如post/get方式
http 方式的优势是它可以携带Cookie/Session
TCP/UDP Socket 方式
TCP 这是唯能保证不间断时时传输手段,开发难度很高,目前web开发人员中能写出高效的多线程socket程序的人很少。
其中涉及很多知识,例如:进程,线程,锁,列队,进程间通信,共享内存,以及信号处理等等;没有10年功力很难写出安全,稳定,高效,可扩展的程序
UDP 能够发送大数据包

12.7.3. 接口性能问题

必须考虑接口最大会话数
处理请求后到返回数据所花费的时间
接口应该支持负载均衡,通过增加节点数量,快速扩展;同时添加与撤除节点不会影响接口的通信(包括节点硬件故障);同时接口应该具备健康状态检查功能。

第 23 章 Web Service Security

目录

23.1. 权限控制与实现23.2. 演示23.3. 增加7 Layer防火墙

<?php
/*
* =====================================
* Website: http://netkiller.github.com
* Author: neo <netkiller@msn.com>
* Email: netkiller@msn.com
* =====================================
*/

class Logging {
	protected $file;
	public function __construct($logfile = "/tmp/debug.log"){
		$this->file = fopen($logfile,"a+");
	}
	public function __destruct() {
        //fclose($this->file);
    }
	public function close() {
        fclose($this->file);
    }
	private function write($msg){
			fwrite($this->file,date('Y-m-d H:i:s').' '.$msg."\r\n");
	}
	public function info($msg){
		$this->write(__FUNCTION__.' '.$msg);
	}
	public function warning($msg){
		$this->write(__FUNCTION__.' '.$msg);
	}
	public function error($msg){
		$this->write(__FUNCTION__.' '.$msg);
	}
	public function debug($msg){
		$this->write(__FUNCTION__.' '.$msg);
	}

}

class Permission{
	protected $_PERMISSION = array();

	public function __construct($login){
		$test =
		array(
			'neo' => array(
				'News'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					),
				'RSS'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					)
				),
			'jam' => array(
				'News'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					),
				'RSS'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					)
				)
		);
		//print_r($test);
		$this->load($test[$login]);
	}
	public function load($arr){
		$this->_PERMISSION = $arr;
	}

	public function is_allowed($class, $fun){
		$class 	= trim($class);
		$fun 	= trim($fun);
		//echo $class, $fun;
		//print_r($this->_PERMISSION);
		if(array_key_exists($class,$this->_PERMISSION)){
			if(array_key_exists($fun,$this->_PERMISSION[$class])){
				if($this->_PERMISSION[$class][$fun] == 'Y') return true;
				//return in_array("Y",$this->_PERMISSION[$class][$fun]);
			}
		}
		return false;
	}
	public function is_denied($class, $fun){
		return (!$this->is_allowed($class, $fun));
	}
	public function scan(){
		return true;
	}
}

class News extends Permission{

	private $logging;
	public function __construct(){
		parent::__construct('neo');
		$this->logging = new Logging('/tmp/news.log');
	}
	public function __destruct() {
		$this->logging->debug('news->get permission denied!!!');
		$this->logging->close();
    }
	public function add(){
		if(!$this->is_allowed(__CLASS__,__FUNCTION__)) return;
		print("Allowed!!! \r\n");
		$this->logging->info('news->add ok');
	}
	public function get(){
		if( $this->is_denied(__CLASS__,__FUNCTION__)) {
			print("Denied!!! \r\n");
			$this->logging->warning('news->get permission denied!!!');
		}

	}
}

$news = new News();
$news->add();
$news->get();

23.1. 权限控制与实现

权限来自下面数组数据,这里仅仅提供一个例子,管理权限你可以单独实现一个class,实现供权限管理功能,最终后转化为下面的数据结构即可。例如你可以将权限写入数据库,最终拼装如下数字让Permission顺利load即可。

array(
			'neo' => array(
				'News'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					),
				'RSS'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					)
				),
			'jam' => array(
				'News'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					),
				'RSS'=> array(
					'add' => 'Y',
					'remove' => 'N',
					'update' => 'Y'
					)
				)
		);		

public function is_allowed($class, $fun) 用户判断权限是否合法。

23.2. 演示

这里提供了一个 News 类,用于演示怎样控制每个function的权限。

同时还提供了一个简单的 Logging 类用于记录程序运行日志。

有了上面的例子就可以将News应用于SOAP一类Web Service上,用来控制每个方法的权限

 

23.3. 增加7 Layer防火墙

上面仅仅对于方法控制权限,接下来我们为程序增加7层防火墙功能

<?php
/*
* =====================================
* Website: http://netkiller.github.com
* Author: neo <netkiller@msn.com>
* Email: netkiller@msn.com
* =====================================
*/
class Firewall{

	protected $status;
	protected $policy;
	protected $chain;
	protected $rule;
	protected $match;
	private $debug;
	//$get,$post,$cookie,$server;

	public function __construct() {
		$this->name 	= "Firewall";
	}

	public function __destruct() {
		//print "Destroying " . $this->name . "\n";
	}

	public function enable(){
		$this->status = true;
	}
	public function disable(){
		$this->status = false;
	}

	public function get(){
		if($this->status){
			$this->chain 	= $_GET;
			return($this);
		}else{
			return($this->status);
		}
	}

	public function post(){
		if($this->status){
			$this->chain 	= $_GET;
			return($this);
		}else{
			return($this->status);
		}
		$this->chain 	= $_POST;
	}

	public function cookie() {
		if($this->status){
			$this->chain = $_COOKIE;
			return($this);
		}else{
			return($this->status);
		}

	}

	public function server(){
		if($this->status){
			$this->chain = $_SERVER;
			return($this);
		}else{
			return($this->status);
		}
	}

	public function match($key, $value){
		if($this->debug) print_r($this->chain);
		$this->match = false;
		if(!array_key_exists($this->chain, $key)){
			if($this->chain[$key] == $value){
				$this->match = true;
			}
		}
		return($this);
	}
	public function policy($p){
		$this->policy = $p;
	}
	public function counter($tm, $cnt){
		return($this);
	}
	public function allow($fun = null){
		if($this->status && $this->match){
			if($fun){
				$fun();
			}
		}
		$this->destroy();
		return($this->status);
	}
	public function deny($fun = null){
		if($this->status && $this->match){
			if($fun){
				$fun();
			}
		}
		$this->destroy();
		return($this->status);
	}
	public function debug($tmp){
		$this->debug = $tmp;
	}
	public function ip($ipaddr){
		return $this->server()->match('REMOTE_ADDR', $ipaddr);
	}
	public function destroy(){
		$this->chain = array();
		$this->match = false;
	}
};

#include_once('firewall.php')
$fw = new Firewall();

$fw->debug(true);
$fw->debug(false);
$fw->enable();
//$fw->disable();
function test(){
	echo 'OK';
};
function allow(){
	echo 'allow';
};
function deny(){
	echo 'deny';
};
//$fw->policy('blacklist');

$fw->ip('192.168.3.17')->allow('allow');
$fw->ip('192.168.3.17')->deny('deny');

$fw->counter('1m',5)->match('id','1000')->deny('test');

/*
$fw->ip('172.16.0.0/24')->allow();
$fw->ip('172.16.0.0','255.255.255.0')->allow();

$fw->header(array('User-Agent' => 'MSIE5'))->deny()
*/
$fw->get()->match('id','1000')->deny('test');
$fw->get()->match('name','chen')->allow('test');
//$fw->get()->match(array('id' => '1000'))->deny();
/*
$fw->post()->data(array('action'=>'/login.php'))->allow()
$fw->cookie()->data(array('userid'=>'test'))->deny()
*/
$fw->server()->match('HTTP_REFERER', 'http://www.mydomain.com/index.html')->allow('test');
$fw->server()->match('REQUEST_METHOD', 'GET')->deny('test');

$fw->disable();
//$fw->destroy();

这里仅仅给你一个思路,我并没有写完程序。例如控制IP请求次数可以如下实现,请自行改善程序

<?php
/*
* =====================================
* Website: http://netkiller.github.com
* Author: neo <netkiller@msn.com>
* Email: netkiller@msn.com
* =====================================
*/
require 'SharedConfigurations.php';

$single_server = array(
    'host'     => '127.0.0.1',
    'port'     => 6379,
    'database' => 0
);

$multiple_servers = array(
    array(
       'host'     => '127.0.0.1',
       'port'     => 6379,
       'database' => 15,
       'alias'    => 'first',
    ),
    array(
       'host'     => '127.0.0.1',
       'port'     => 6380,
       'database' => 15,
       'alias'    => 'second',
    ),
);

$client = new Predis\Client($single_server, array('prefix' => 'fw:'));

$key=$_SERVER['REMOTE_ADDR'];

if(!$client->exists($key)){
	$client->setex($key, 20, 1);
}else{
	$client->incrby($key,1);
}

$counter = $client->get($key);

if($counter > 10){
	echo 'Deny';
}

print_r($client->get($key));

//var_dump($client->keys('*'));		
时间: 2024-09-19 02:46:45

Web Service 接口安全与解决方案的相关文章

Web Service接口大量数据传输解决方案

就管他叫"使用多线程分段获取大量数据方法"吧.假定我们的需求是,通过Web Service获取10W条订单,我的解决方案是 分成10个线程每个线程传输1W条订单分段获取,具体请看下面的流程图及其说明 1,流程图 2,流程说明: 线程1开始请求接口获取1W条数据,当数据成功获取后,接口是闲置的,这时我们开始线程 2获取数据,同时线程1继续执行获取数据的后续工作,如果转换数据,这里我用的办法是,使用预先定义的实体对象格式 反序列化XML (据说这种方式比遍历XML或是载入到DataSet中

asp.net Web Service 接口大量数据传输解决方案_实用技巧

具体请看下面的流程图及其说明 1,流程图 2,流程说明:线程1开始请求接口获取1W条数据,当数据成功获取后,接口是闲置的,这时我们开始线程2获取数据,同时线程1继续执行获取数据的后续工作,如果转换数据,这里我用的办法是,使用预先定义的实体对象格式 反序列化XML (据说这种方式比遍历XML或是载入到DataSet中循环 读取都要高效的,具体我没有测试过 ,哈哈)将数据插入到数据后停止线程1.使用这样线程循环的办法处理所有线程读取数据.

web service接口 wsdl和asmx有什么区别(实在没分了。。抱歉)

问题描述 web service接口 wsdl和asmx有什么区别(实在没分了..抱歉) http://192.168.1.210:8080/law/SearchPort?wsdl和http://localhost:2610/NewPrint/WebService/NewService.asmx 格式的接口有什么区别调用方式有区别吗(wsdl和asmx) 解决方案 没有区别,只是后缀名的区别. Web Service也叫XML Web Service WebService是一种可以接收从Inte

调用返回json的 web service接口

问题描述 调用返回json的 web service接口 公司给了一个web service接口 ,只给了一个url ,并告诉是post请求, 以前没调用过 ,求大神们给个例子什么的.接口返回是json格式 我用from表单action提交那个url 结果是让我下载一个.json的文件,下载下来打开就是我想获得的json数据,这个接口该怎么调用啊. 解决方案 直接发生http post请求.返回结果就是json数据 解决方案二: jQuery调用WebService返回JSON数据 解决方案三:

有关web service 接口 的问题

问题描述 有关web service 接口 的问题 现在要做个功能,就是点击确定把我得到的数据传给别人, 用web service ,没用过这个, 就是我该从哪里下手,需要做些什么要,配置什么吗? 解决方案 快递查询接口?http://webservice.36wu.com/ExpressService.asmx ip查询接口?http://webservice.36wu.com/ipService.asmx 天气预报接口?http://webservice.36wu.com/weatherSe

java 调用返回json的 web service接口

问题描述 java 调用返回json的 web service接口 公司给了一个web service接口 ,只给了一个url ,并告诉是post请求, 以前没调用过 ,求大神们给个例子什么的.接口返回是json格式 我用from表单action提交那个url 结果是让我下载一个.json的文件,下载下来打开就是我想获得的json数据,这个接口该怎么调用啊. 解决方案 很简单,这个你就写一个后台模拟post请求的代码就可以了,在页面是因为浏览器将json数据识别为一个文件,所以才会下载 解决方案

web service接口问题

问题描述 目前2个项目要进行项目登录状态的同步(登录前 以确定2个项目中都有一样的用户数据)在A项目中登录了.B项目也要登录反则一样.web service接口我知道,但是webservice接口只是一个方法 并不能在里面取得其当前项目中的session. 我想问下能不能用struts2 action直接做为接口来调用?如:http://www.xxx.com/user/webserivce!login.action?user=xxx这样做的和webservice 传统的方式有什么区别?为什么?

365Key的Web Service接口

web 365Key是一个可以在您浏览任意页面的时候轻松点击右键来收藏网页,并在网上与朋友分享.日前,365Key公布Web Service接口以方便开发者更好地使用365Key,目前提供以下接口如下: Web Services地址:http://services.365key.com/exportService.asmx getUserID 获取用户在365Key的ID(数字) 参数:string username -- 用户名,比如keso返回:int 用户ID getTagList 获取指

在代理里怎么同时调用2个WEB SERVICE接口

问题描述 同时引入2个接口提示以下错误,请教高手?先说声谢谢DuplicatePUBLICnameAPISUCCESSinUSEmoduleaa 解决方案 解决方案二:没人知道吗???解决方案三:LS里使用MSSoap进行调用应该可行吧.解决方案四:直接调用DOMINO使用的WEBSERVICE这样不行吗?解决方案五:既然调用的是WEBSERVICE接口.websevice代码是你写的吗?如果是你就把函数或方法写道一个websevice里就可以了吗?解决方案六:service服务是用别人的,在一