简单防恶意提交处理+session保存机制细节

最近一个活动被人搞,主要频繁提交,把这边的一个表塞了很多恶心数据。

场景为:

手机访问,输入身份证相关信息,接口1~3秒,其它活动相关信息。再提交。

处理方式:

主要加了些验证,如图形和session限制。

因为是手机访问,所以同ip是很有可能的情况,只能做一个大阀值处理,但是阀值不好控制,多了没效果,少了,真实手机用户有问题。所以异常ip需要先确认是不是一些运营商的服务器这些要查查。不是就可以直接封了。再加个简单的session校验,说实在,没啥用。不过一般人是通过电脑才来黑,如果通过运营商(就是手机热点)。同时用代理也有一定几率伪造终端ip,暂时都没有啥太好的方式感觉。

贴代码(yii版本):

<?php
/**
 * 特别注意:
 * 服务器上和本地的类是不同的。本地服务器因为链接问题,所以直接进行reture处理。
 * @author caihaibin
 *
 */
class SubmitTools {
	static function model() {
		return new SubmitTools ();
	}
	/**
	 * 防重复提交校验
	 *
	 * @param string $key
	 *        	特殊项目,自己提供当前用户唯一标志。如:活动id+用户手机号码 (必要时,活动链接也可以)
	 * @param boolean $debug_write_log
	 *        	当为true时,所有通过和不通过都写入到日志
	 * @return boolean 指定时间内的第一次提交,为true,重复提交会抛出异常
	 */
	static function record($key = '', $debug_write_log = false) {
		if (empty ( $key )) {
			$key = 'submit_' . Yii::app ()->session->getSessionID ();
		}
		$result = Yii::app ()->tmpcache->get ( $key );
		if ($result) {
			if ($debug_write_log)
				write_log ( 'mult_submit_error', $key );
			throw new Exception ( '当前用户,10秒内只能提交一次' );
		}
		Yii::app ()->tmpcache->add ( $key, '1', 10 );
		if ($debug_write_log)
			write_log ( 'mult_submit', $key );
		return true;
	}
}

上面这个版本是结合php-redis的版本

因为场景里有个情况叫身份校验延迟,这种情况下,验证码校验后更新了数据,但是在会话结束前是不会写到session的数据源里的。所以用redis,记录提交的标志。不提供的情况下就是session_id,还可以自己拼标志,比如身份证号。

多提供个yii的:

Yii::app ()->tmpcache->add ( $key, '1', 10 );

源码说明:

	/**
	 * Stores a value identified by a key into cache if the cache does not contain this key.
	 * This is the implementation of the method declared in the parent class.
	 *
	 * @param string $key the key identifying the value to be cached
	 * @param string $value the value to be cached
	 * @param integer $expire the number of seconds in which the cached value will expire. 0 means never expire.
	 * @return boolean true if the value is successfully stored into cache, false otherwise
	 */
	protected function addValue($key,$value,$expire)
	{
		if ($expire == 0)
			return (bool)$this->executeCommand('SETNX',array($key,$value));

		if($this->executeCommand('SETNX',array($key,$value)))
		{
			$this->executeCommand('EXPIRE',array($key,$expire));
			return true;
		}
		else
			return false;
	}

储存标记是原来有的,则不进行覆盖。同时yii其它cache方式如file也有相应处理。

 

 

PHP-Redis

官方原文档地址:

http://redisdoc.com/

php-redis文档

http://www.cnblogs.com/weafer/archive/2011/09/21/2184059.html

瞬时并发量上来,服务器集群后。剩下的瓶颈就是数据库,不过这边真心以目前的条件看无解中。需求修改太频繁。很多东西都是刚定就说什么什么时候要。频繁变化的东西,何来的优化呢~

解决phonegap 2.9 多次上传导致的 线程占用异常.

虽然是个很老的版本,但是优势是支持 清理缓存。同时没有什么太高的要求。

最近实现一个对话功能,需要能实现类似微信的上传录音功能。

录音好说,但是多次上传时,会报错,最终发现是线程被占用,释放做得不好啊。。

两个解决方案,修改原代码。用filereader代替。

简单解决。用filereader 读取录取后的文件,然后传到服务器。

代码如下:

获取文件内容

function getData(filepath, datacall, failcall) {
	var path = filepath;
	var level = "window.requestFileSystem";
	if (typeof failcall != 'undefined') {
		fail = failcall;
	} else {
		function fail(error) {
			// console.log(evt);
			// evt.target.
			console
					.log("gddebug file getData " + level + " fail "
							+ error.code);
		}
	}
	if (typeof datacall == 'undefined') {
		datacall = function(data) {
		};
	}
	window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
			function(fileSystem) {
				level = "fileSystem.root.getFile";
				console.log('gddebug fileSystem.root.getFile ' + path);
				fileSystem.root.getFile(path, null, function(fileEntry) {
					level = "fileEntry.file";
					fileEntry.file(function(file) {
						console.log("gddebug readAsDataURL");
						var reader = new FileReader();
						reader.onloadend = function(evt) {
							console.log("gddebug" + "Read as data URL");
							console.log("gddebug" + evt.target.result);
							datacall(evt.target.result);
						};
						reader.readAsDataURL(file);
					}, fail);
				}, fail);
			}, fail);
}

上传文件:

function uploadFile(url, filepath, wincall, failcall, calltype) {
	if (typeof calltype == 'undefined') {
		calltype = 'html';
	}
	filepath = filepath.replace(/^file:///, '');
	getData(filepath, function(data) {
		$.post(url, {
			file : data,
			filename : basename(filepath)
		}, wincall, calltype);
	}, failcall)
}

服务器解析代码:

if(isset($_POST['file'])){
	if(empty($_POST['file'])){
		sjson(false,$title,'');
	}
	$filepath='record/'.$_POST['filename'];
	$_POST['file']=preg_replace('/^data:[^;]+?;base64,/','',$_POST['file']);
	$_POST['file']=base64_decode($_POST['file']);
	file_put_contents($filepath,$_POST['file']);
}

补充amr 转 mp3版本

if(isset($_POST['file'])){
	if(empty($_POST['file'])){
		sjson(false,$title,'');
	}
	$filepath='record/'.$_POST['filename'];
	$_POST['file']=preg_replace('/^data:[^;]+?;base64,/','',$_POST['file']);
	$_POST['file']=base64_decode($_POST['file']);
	file_put_contents($filepath,$_POST['file']);
	if(preg_match('/.amr/i',$filepath)){
		$target_mp3=preg_replace('/.amr$/i','.mp3',$filepath);
		//将amr转换成mp3
		exec("java -jar amr.jar {$filepath} {$target_mp3}");
		$filepath=$target_mp3;
	}
	$urlpath='http://192.168.0.144/test/phonegap/www/upload/'.$filepath;
	sjson(true,$title,'',array('path'=>$urlpath,'html'=>$html));
}

 

编写可直接命令运行的jar文件

准备一个完整的项目.

各种类需要放在里面进行正常引用。外部引用类需要放进来。

打包工具:eclipse 需要支持导出 runnable jar file.老版本只能导出jar

操作:eclipse 右键 export -> java->runnable jar file.

然后就可以直接命令运行。也可以通过php进行调用了。

对于需要传入的参数。就是 public static void main(String[] args) 这个args 东东了。

第一个参数就是args[0]

比如写了一个amr转mp3的jar。执行代码

java -jar amrtomp3.jar “amr filepath”  “mp3 filepath”

 

 

Yii soap 一个奇怪的异常 + 一个不是方法的方法

最近对接第三方通知接口时,出现一个奇怪的问题。

soap的请求,有进入soap service 的 init 事件,确没有进入最终的动作。

暂时查不出原因,因为服务器只有上传的权限,没有拦截报文和相关其它的权限。同时只有目标发起时才发生,都是要钱的,不土豪。。测试不起。。也只能做猜想,尝试各种方法先解决了。

猜想:

1.报文有出现特殊字符,在复制的过程中会被处理,但是本身程序正常处理时,碰到会异常

2.请求不完整,可能第三方通知机制,接通后不等响应就把请求停了。这块不好验证。

3.框架或服务器bug。

经过各种尝试之后,确认了些问题,问题并不出在报文和请求头,因为将报文和请求头保存之后,在本地和在服务端模拟请求。都有正常响应。(不确认是否在各种复制的过程中,特殊字符丢失)

时间紧迫,所以按最快的方式处理。因为init能正常进行访问,所以将通知请求的解析在init中进行处理,解析出目标数据再调用原来的动作。

//获取soap报文,普通的 soap?wsdl是响应报文,不要搞混
$reqxml = file_get_contents ( 'php://input' );
//判断请求报文是否有对应的动作
if ($reqxml && preg_match ( '/xxxxxRequest/', $reqxml ))
//解析xml,得到对应数据
$reqxml = @simplexml_load_string ( $reqxml, NULL, LIBXML_NOCDATA );
//注意有些特殊标签在属性里,需要进行特殊关联。因为只有一个,这边进行了简单处理。
$request = json_decode ( json_encode ( $reqxml ), true );
//自己调用原来的函数。触发对应的通知处理
.....
//函数返回后,和原来的情况一样。没有经过目标函数,所以需要手动输出响应报文
echo '<?xml version="1.0" encoding="UTF-8"?><SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:xxxxxxControllerwsdl" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:xxxxxxResponse>xxxxxx</ns1:xxxxxResponse></SOAP-ENV:Body></SOAP-ENV:Envelope>';'
//记得关闭,
exit ();

先留位置,因为只是特殊出现。暂时只保留特殊处理。先记录,后面有时间再深入研究解决,好吧。是测试太频繁。。。。钱钱钱的问题。。。。

解决 navicat 导入大sql文件 ,单行过长问题。

前段时间维护一个项目,搞错需求。导致以为是翻新。。。把整个库拷贝了份。。(文件来源貌似是用mysql自带导出的,具体不清楚)

1g多,不算太多,主要一个问题出在sql是以:

insert into table (row…) values (value…), (value…), (value…)….

单行。。没错。。就是单行。很多sql程序,处理该机制是一直循环识别到换行符号。。导致一个问题。内存不够。在内存比较足的机器足足运行了超过半天还不到一半,没耐性的哥想原因。顺便写了写脚本解决。

$file_source = 'c:/xxxx.sql';
$file_target = 'c:/xxxx2.sql';
$rh = fopen ( $file_source, 'rb' );
$wh = fopen ( $file_target, 'wb' );
if ($rh === false || $wh === false) {
	// error reading or opening file
	return true;
}
$count = 0;
$begin = 0;
$span = 300;
$lasttable = '';
while ( ! feof ( $rh ) ) {
	$line = fgets ( $rh );
	if (preg_match ( '/INSERT INTO `(w+)`/ims', $line, $match )) {

		// if ($lasttable == $match [1])
		// continue;
		// // $line=preg_replace('/', $replacement, $subject)
		$lasttable = $match [1];
		// gddebug ( $line );
		// fputs ( $wh, $line );
		$line = preg_replace ( '/),(/ism', ");n INSERT INTO `{$lasttable}` VALUES (", $line );
		// gddebug ( $line );
		// exit ();
	}
	if (preg_match ( '/^--/ims', $line ))
		continue;
	if (preg_match ( '/^/*/ims', $line ))
		continue;
	if (preg_match ( '/LOCK TABLES/ims', $line ))
		continue;
	if (preg_match ( '/UNLOCK TABLES/ims', $line ))
		continue;
	fputs ( $wh, $line );
	// if ($count > $line) {
	// gddebug ( $line );
	// }
	$count ++;
	// if ($count > $begin + $span)
	// exit ();
	// exit;
}
fclose ( $rh );
echo ($count);

1g文件。40分钟导入~

 

PHP 压缩字符串方法

最近帮朋友采集n多数据。bluehost的最大文件数量20w 也不小心就触顶了。

采集东西的时候,因为抓取网页的时间过长,所以担心数据采集漏缺,都把网页文件缓存到虚拟机。so~
决定将不用到的东西,都打包压缩,然后删了文件。但是网页文件相当多。如果删除,后续需要补充什么东西的话相当麻烦。 所以决定放数据库里。bluehost限制的是文件数量,大小是不怎么计较的,按官方的话说,主要担心潜在文件安全,而且最大的扩展也只到30w,所以还是老实清理系统,将html缓存文件和各种采集的特殊数据,都放数据库里。回到整体,就有今天的压缩啦~

顺便符上blushost的数据库大小说明:

https://my.bluehost.com/cgi/help/429

参考:http://www.open-open.com/bbs/view/1319888000999

原文有说过一个失真的情况。具体看应用。因为我这边主要针对文本(网页源文件),所以是最好压缩的。有兴趣去了解原理,就知道为什么图片除了缩小,都不太好压缩,而文本类,轻松就压缩剩几十分之一了。

测试代码:

<?php
$filename = 'test.html';
//文件大小 3.2 M 某某变态网站,不说明了。。。
$filecontent = file_get_contents ( $filename );
// 压缩率最低(gzip压缩算法) 生成结果可以直接写到.gz文件中
$gzencode = gzencode ( $filecontent, 9 );
file_put_contents ( "gzencode.txt", $gzencode );
// 压缩率居中
$gzcompress = gzcompress ( $filecontent, 9 );
file_put_contents ( "gzcompress.txt", $gzcompress );
// 压缩率并列最高
$gzdeflate = gzdeflate ( $filecontent, 9 );
file_put_contents ( "gzdeflate.txt", $gzdeflate );

// 压缩率并列最高
$bzcompress = bzcompress ( $filecontent, 9 );
file_put_contents ( "bzcompress.txt", $bzcompress );

//压缩结果,前三种,文件都压缩到111kb ,最后一种压缩到 79kb。

 

小试 ionic

被纠结 jquery mobile 写的东西不好看,有极其轻微的闪动。然后跑来研究这个了..

起步

更新安装慢的,需要修改下nodejs镜像站

http://cnpmjs.org/

$ npm install -g cnpm --registry=https://r.cnpmjs.org

http://www.ionicframework.com/getting-started/

异常:

ionic build android error when download gradle

修复:

http://stackoverflow.com/questions/29874564/ionic-build-android-error-when-download-gradle

实例:

http://codepen.io/ionic/

文档:

http://www.ionicframework.com/docs/

小结:看似强大,但是相对问题也不少,罗列下

一、样式不是完全统一的,需要针对ios和android单独进行特殊调整。如在浏览器和ios里打开页面。tab 是在底部的,在android里,tab飘到顶部,需要进行特殊处理.

http://ionicframework.com/docs/api/provider/$ionicConfigProvider/

angular.module('ionicApp', [ 'ionic' ]).config(
		function($ionicConfigProvider) {
			//初始化函数
			//禁用缓存.
			$ionicConfigProvider.views.maxCache(0);
			//需要特殊设置安卓样式控制
			$ionicConfigProvider.platform.android.tabs.style('standard');
			$ionicConfigProvider.platform.android.tabs.position('standard');
			$ionicConfigProvider.platform.android.navBar.alignTitle('center');
			// note that you can also chain configs
			$ionicConfigProvider.backButton.text('Go Back').icon(
					'ion-chevron-left');
		})

安提示生成的demo,tab有问题,但是手动编写时。。没有问题。。。原因有待研究。

phonegap 3.0 以上版本需要通过插件进行缓存清理,不支持webview.getSettings 这种处理方式.

补充js清理神句…

location.reload(true);

执行时,会有提示

 

 

java获取基站 phonegap 插件

参考

http://code.google.com/p/dogood/source/browse/trunk/annole_android/LiveWallpaper/src/fixedPosition/CellIDInfoManager.java?r=142

代码:

package fixedPosition;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

//三大网络运营商的网络制式对应如下:
//
//移动2G 网   -->      GSM
//
//移动3G 网   -->      TD-SCDMA
//
//电信2G 网   -->      CDMA
//
//电信3G 网   -->      CDMA2000
//
//联通2G 网   -->      GSM
//
//联通3G 网   -->      WCDMA

//NETWORK_TYPE_UNKNOWN
//NETWORK_TYPE_GPRS
//NETWORK_TYPE_EDGE
//NETWORK_TYPE_UMTS
//NETWORK_TYPE_HSDPA
//NETWORK_TYPE_HSUPA
//NETWORK_TYPE_HSPA
//NETWORK_TYPE_CDMA
//NETWORK_TYPE_EVDO_0
//NETWORK_TYPE_EVDO_A
//NETWORK_TYPE_EVDO_B
//NETWORK_TYPE_1xRTT
//NETWORK_TYPE_IDEN
//NETWORK_TYPE_LTE
//NETWORK_TYPE_EHRPD

public class CellIDInfoManager {

	private final static String TAG = "CellIDInfoManager";
	private Context context;

	public CellIDInfoManager(Context context) {
		this.context=context;
	}
	/*
	 * 获取基站信息
	 */
	public ArrayList<CellIDInfo> getCellIDInfo() throws Exception{

		TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

		ArrayList<CellIDInfo> CellID = new ArrayList<CellIDInfo>();
		CellIDInfo currentCell = new CellIDInfo();

		int type = manager.getNetworkType();
		Log.d(TAG, "getCellIDInfo--> 		NetworkType = " + type);
		int phoneType = manager.getPhoneType();
		Log.d(TAG, "getCellIDInfo--> 		phoneType = " + phoneType);

		if (type == TelephonyManager.NETWORK_TYPE_GPRS				// GSM网
				|| type == TelephonyManager.NETWORK_TYPE_EDGE
				|| type == TelephonyManager.NETWORK_TYPE_HSDPA)
		{
			GsmCellLocation gsm = ((GsmCellLocation) manager.getCellLocation());
			if (gsm == null)
			{
				Log.e(TAG, "GsmCellLocation is null!!!");
				return null;
			}

			int lac = gsm.getLac();
			String mcc = manager.getNetworkOperator().substring(0, 3);
			String mnc = manager.getNetworkOperator().substring(3, 5);
			int cid = gsm.getCid();

			currentCell.cellId = gsm.getCid();
			currentCell.mobileCountryCode = mcc;
			currentCell.mobileNetworkCode = mnc;
			currentCell.locationAreaCode = lac;

			currentCell.radioType = "gsm";

			CellID.add(currentCell);

//			// 获得邻近基站信息
			List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();
			int size = list.size();
			for (int i = 0; i < size; i++) {

				CellIDInfo info = new CellIDInfo();
				info.cellId = list.get(i).getCid();
				info.mobileCountryCode = mcc;
				info.mobileNetworkCode = mnc;
				info.locationAreaCode = lac;

				CellID.add(info);
			}

		}else if (type == TelephonyManager.NETWORK_TYPE_CDMA		//// 电信cdma网
				|| type == TelephonyManager.NETWORK_TYPE_1xRTT
				|| type == TelephonyManager.NETWORK_TYPE_EVDO_0
				|| type == TelephonyManager.NETWORK_TYPE_EVDO_A)
		{

			CdmaCellLocation cdma = (CdmaCellLocation) manager.getCellLocation();	
			if (cdma == null)
			{
				Log.e(TAG, "CdmaCellLocation is null!!!");
				return null;
			}

			int lac = cdma.getNetworkId();
			String mcc = manager.getNetworkOperator().substring(0, 3);
			String mnc = String.valueOf(cdma.getSystemId());
			int cid = cdma.getBaseStationId();

			currentCell.cellId = cid;
			currentCell.mobileCountryCode = mcc;
			currentCell.mobileNetworkCode = mnc;
			currentCell.locationAreaCode = lac;

			currentCell.radioType = "cdma";

			CellID.add(currentCell);

//			// 获得邻近基站信息
			List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();
			int size = list.size();
			for (int i = 0; i < size; i++) {

				CellIDInfo info = new CellIDInfo();
				info.cellId = list.get(i).getCid();
				info.mobileCountryCode = mcc;
				info.mobileNetworkCode = mnc;
				info.locationAreaCode = lac;

				CellID.add(info);
			}
		}

		return CellID;

	}

}

phonegap插件版本(只编写了获取邻近的基站)

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.example.hello.MainActivity;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

public class UnicomGSMCell extends Plugin {

	public static final String PLUGIN_NAME = "UnicomGSMCell";
	NotificationManager notificationManager;
	Notification note;
	PendingIntent contentIntent;

	public CallbackContext callbackContext;
	private static final String STOP_ACTION = "stop";
	private static final String GET_ACTION = "LocationInfo";
	public LocationClient locationClient = null;
	public JSONObject jsonObj = new JSONObject();
	public boolean result = false;

	private static final Map<Integer, String> ERROR_MESSAGE_MAP = new HashMap<Integer, String>();

	private static final String DEFAULT_ERROR_MESSAGE = "服务端定位失败";

	public String getErrorMessage(int locationType) {
		String result = ERROR_MESSAGE_MAP.get(locationType);
		if (result == null) {
			result = DEFAULT_ERROR_MESSAGE;
		}
		return result;
	}

	@Override
	public boolean execute(String action, JSONArray args,
			final CallbackContext callbackContext) throws JSONException {
		Log.d(PLUGIN_NAME, "Plugin execute called with action: " + action);

		setCallbackContext(callbackContext);
		if (GET_ACTION.equals(action)) {
			cordova.getActivity().runOnUiThread(new Runnable() {
				@Override
				public void run() {
					TelephonyManager manager = (TelephonyManager) cordova
							.getActivity().getSystemService(
									Context.TELEPHONY_SERVICE);

					String operator = manager.getNetworkOperator();
					/** 通过operator获取 MCC 和MNC */
					int mcc = Integer.parseInt(operator.substring(0, 3));
					int mnc = Integer.parseInt(operator.substring(3));

					// GsmCellLocation location = (GsmCellLocation)
					// manager.getCellLocation();

					/** 通过GsmCellLocation获取中国移动和联通 LAC 和cellID */
					// int lac = location.getLac();
					// int cellid = location.getCid();
					/** 通过CdmaCellLocation获取中国电信 LAC 和cellID */
					// <span style="white-space:pre"> </span>
					/*
					 * CdmaCellLocation location1 = (CdmaCellLocation)
					 * mTelephonyManager.getCellLocation(); <span
					 * style="white-space:pre"> </span> lac =
					 * location1.getNetworkId(); <span style="white-space:pre">
					 * </span> cellId = location1.getBaseStationId(); <span
					 * style="white-space:pre"> </span> cellId /= 16;
					 */

					int strength = 0;
					/** 通过getNeighboringCellInfo获取BSSS */
					List<NeighboringCellInfo> infoLists = manager
							.getNeighboringCellInfo();
					System.out.println("infoLists:" + infoLists + "     size:"
							+ infoLists.size());

					// List<NeighboringCellInfo> celllist = new
					// ArrayList<NeighboringCellInfo>();

					JSONArray jsonarray = new JSONArray();
					for (NeighboringCellInfo info : infoLists) {
						JSONObject jo = new JSONObject();
						try {
							jo.put("rssi", info.getRssi());
							jo.put("cellid", info.getCid());
							jo.put("lac", info.getLac());
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						jsonarray.put(jo);
						// org.json.JSONObject jo =
						// JSONArray.toJSONObject(info);
						// celllist.add( JSONArray.fromObject(info));
						strength += (-133 + 2 * info.getRssi());// 获取邻区基站信号强度
						// info.getLac();// 取出当前邻区的LAC
						// info.getCid();// 取出当前邻区的CID
						System.out.println("rssi:" + info.getRssi()
								+ ";cellid:" + info.getCid() + ";lac:"
								+ info.getLac());
					}
					// JSONArray jsonarray = JSONArray.toJSONObject(infoLists);
					callbackContext.success(jsonarray.toString());
					result = true;
				}

			});
		} else if (STOP_ACTION.equals(action)) {
			locationClient.stop();
		}

		while (result == false) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	@Override
	public void onDestroy() {
		if (locationClient != null && locationClient.isStarted()) {
			locationClient.stop();
			locationClient = null;
		}
		super.onDestroy();
	}

	private void logMsg(String s) {
		System.out.println(s);
	}

	public CallbackContext getCallbackContext() {
		return callbackContext;
	}

	public void setCallbackContext(CallbackContext callbackContext) {
		this.callbackContext = callbackContext;
	}

	@SuppressWarnings("unused")
	@Override
	public PluginResult execute(String arg0, JSONArray arg1, String arg2) {
		// TODO Auto-generated method stub
		return null;
	}

}

index.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>lbs测试</title>
<meta name="viewport"
	content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no">
<script type="text/javascript" charset="utf-8" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova.android.js"></script>
<script type="text/javascript">
	document.addEventListener("deviceready", appReady, false);
	function appReady() {
		getgsmcell();
	}
	function getlbs(){
		$('body').append('开始获取'+'<Br>');
		function onSuccess(pos) {
			$('body').append('成功结果:' + JSON.stringify(pos)+'<Br>');
		}
		function onFail(pos) {
			$('body').append('失败结果:' + JSON.stringify(pos)+'<Br>');
		}
		setTimeout(function(){
			cordova.exec(onSuccess, onFail, 'BaiduLocation', 'getCurrentPosition', []);
		},1000)
	}
	function getgsmcell(){
		$('body').append('开始获取'+'<Br>');
		function onSuccess(pos) {
			$('body').append('成功结果:' + JSON.stringify(pos)+'<Br>');
		}
		function onFail(pos) {
			$('body').append('失败结果:' + JSON.stringify(pos)+'<Br>');
		}
		setTimeout(function(){
			cordova.exec(onSuccess, onFail, 'UnicomGSMCell', 'LocationInfo', []);
		},1000)
	}
</script>
</head>
<body>
	<br>
	<h1 onclick="getlbs()">获取定位信息</h1>
	<br>
	<br>
	<h1 onclick="getgsmcell()">获取基站信息</h1>
	<br>
	测试页面
</body>
</html>