首页 > 代码库 > 使用spring+html5实现安全传输随机数字密码键盘

使用spring+html5实现安全传输随机数字密码键盘

随着互联网的飞跃式发展,移动支付已越来越受欢迎并且已成为常态,很多三方支付公司推出了很多支付方式如快捷支付、认证支付、

扫码支付等等。快捷支付和认证支付可分为移动app控件和移动HTML5网页。用户第一次使用快捷支付或认证支付进行支付的时候,需先绑定

银行卡。在绑定银行卡的过程中,需要验证银行卡信息。不同银行、不同银行卡验证的要素不一样,有些需要验证四要素,有的需要验证八要

素。对于需要验证银行卡的交易密码的情况,怎样保证交易密码的安全不被别人所窃取呢?为了保证交易密码不在传输过程中被窃取,出现了

安全传输随机数字密码键盘。

安全传输随机数字密码键盘怎么实现呢?今天给大家详细的介绍安全传输随机数字密码键盘的原理和代码实现。下图是实现的数字键

盘效果:

技术分享


一、实现原理


用户点击“交易密码”输入框,页面异步向后台发送“获取密码键盘”的请求,后台接收到请求之后随机生成“1234567890与随机密文的对应

关系”和“随机密文”和“1234567890图片“的对应关系,然后把它们关系放入dto实例中并放入redis中,最后把随机密文以集合的方式返回到页面,

页面js获取到密文集合后以循环的方式向后台请求对应的数字图片流,并展示在页面。


当用户点击数字键盘中的数字图片,就会把图片对应的密文放入到pkey隐藏输入框中,多个数字以逗号隔开,当点击支付的时候,就会

把peykey隐藏输入框的值传入到后台,后台从redis中取出“密文”与“1234567890数字“的对应关系,就取出了对应交易密码。


二、具体实现


1).HTML5页面


页面主要展示密码输入框和支付按钮,需要导入JQuery、bootstrap及pwdkey.js等。下面是具体代码:

<%@ page language="java" import="java.util.*"
	contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ page pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
%>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
<html>
<head>
<meta name="viewport"
	content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0" />
<meta http-equiv="Cache-Control" CONTENT="private,must-revalidate">
<link rel="stylesheet"
	href=http://www.mamicode.com/‘‘>>

2).密码键盘js代码


用户点击“交易密码”输入框,页面异步向后台发送“获取密码键盘”的请求,后台接收到请求之后把随机密文以集合的方式返回到页面,

页面js获取到密文集合后以循环的方式向后台请求对应的数字图片流并展示在页面。具体代码如下:

$(document).ready(
		function() {
			$("#pay").removeAttr("disabled");
			$("input").click(function() {
				hideKey();
			});
			$("button").click(function() {
				hideKey();
			});
			$(".pass-label").click(function() {
				
				var rangdom = $(this).attr("random");
				var path = $(this).attr("path");
				pwdkey(this, rangdom, path);
			});
			window.addEventListener(
					"onorientationchange" in window ? "orientationchange"
							: "resize", hengshuping, false);
		});
function hengshuping() {

	if (window.orientation == 180 || window.orientation == 0) {
		$("div#keyboard td").each(function() {
			$(this).css("padding", "15px");
		});
	}
	if (window.orientation == 90 || window.orientation == -90) {
		$("div#keyboard td").each(function() {
			$(this).css("padding", "8px");
		});

	}
	window.scrollTo(0, $(".pass-label").offset().top);
}
function pwdkey(obj, rangdom, path) {
	$(‘.keyboard‘).addClass("navbar-fixed-bottom");
	$(‘.keyboard‘).css({
		"z-index" : "9999"
	});
	if (rangdom == null || rangdom == "") {
		alert("无法加载密码键盘,请刷新后重试!");
		return false;
	}
	if ($("#pkey").val() == null || $("#pkey").val() == "undefined") {
		$(obj)
				.html(
						$(obj).html()
								+ ‘<input type="hidden" name="pkey" id="pkey" />‘);
	}
	$("#pin").html("交易密码");
	setCssNomal();
	$("#pkey").val("");
	$
			.ajax({
				type : ‘post‘,
				url : path + "/common/pkey.do",
				cache : false,
				async : false,
				data : {
					rangdom : rangdom
				},
				success : function(data) {
					if (data =http://www.mamicode.com/= null || data == "" || data == "undefined">

3).获取密码键盘后台方法


该方法将随机生成“1234567890与随机密文的对应关系”和“随机密文”和“1234567890图片“的对应关系,然后把它们关系放入dto实例中

并放入redis中,最后把随机密文以集合的方式返回到页面。具体代码如下:

获取密码键盘

/**
	 * 
	 * @Description: 获取密码键盘
	 * @param request
	 * @param rangdom 随机字符串
	 * @return
	 * 
	 */
	@SuppressWarnings("unchecked")
	@ResponseBody
	@RequestMapping(value = http://www.mamicode.com/"common/pkey.do", method = RequestMethod.POST)>
生成键盘的PwdKeyUtils工具类:

/**
 * 
 * @ClassName: PwdKeyUtils
 * @Description: 密码处理工具类
 * @author yangbo yangbo@zlinepay.com
 * @date 2015年6月25日 上午11:03:24
 * 
 */
public class PwdKeyUtils {
	private final static Map<String, String> imagesValueMap;

	/**
	 * 
	 * @Description: 获取密码键盘映射关系
	 * @param imagesValueMap
	 * @return
	 * 
	 */
	static {
		imagesValueMap = new HashMap<String, String>();
		imagesValueMap.put("0",
				"images/keys/0.png");
		imagesValueMap.put("1",
				"images/keys/1.png");
		imagesValueMap.put("2",
				"images/keys/2.png");
		imagesValueMap.put("3",
				"images/keys/3.png");
		imagesValueMap.put("4",
				"images/keys/4.png");
		imagesValueMap.put("5",
				"images/keys/5.png");
		imagesValueMap.put("6",
				"images/keys/6.png");
		imagesValueMap.put("7",
				"images/keys/7.png");
		imagesValueMap.put("8",
				"images/keys/8.png");
		imagesValueMap.put("9",
				"images/keys/9.png");
	}

	public static PwdKeyDto digitkeyboard() {
		List<String> rundomKeys = new ArrayList<String>();// 随机key映射
		Map<String, String> valueKeys = new HashMap<String, String>();// 密文和明文映射
		Map<String, String> imgKeyMaps = new HashMap<String, String>();// 密文和图片映射
		List<String> keys = new ArrayList<String>();
		for (int i = 0; i < 10; i++) {
			keys.add(i + "");
		}
		for (int i = 0; i < 10; i++) {
			Random r = new Random();
			int index = r.nextInt(keys.size());
			String key = keys.get(index);
			keys.remove(index);
			String randomkey = randomKey(24);
			rundomKeys.add(randomkey);
			valueKeys.put(randomkey, key);
			imgKeyMaps.put(randomkey, imagesValueMap.get(key));
		}
		PwdKeyDto dto = new PwdKeyDto(rundomKeys, valueKeys, imgKeyMaps);
		return dto;
	}

	/**
	 * 
	 * @Description:获取动态key
	 * @param num
	 *            key位数
	 * @return
	 * 
	 */
	public static String randomKey(int num) {
		StringBuffer sb = new StringBuffer("");
		char[] chars = { ‘0‘, ‘1‘, ‘2‘, ‘3‘, ‘4‘, ‘5‘, ‘6‘, ‘7‘, ‘8‘, ‘9‘, ‘A‘,
				‘B‘, ‘C‘, ‘D‘, ‘E‘, ‘F‘, ‘G‘, ‘H‘, ‘I‘, ‘J‘, ‘K‘, ‘L‘, ‘M‘,
				‘N‘, ‘O‘, ‘P‘, ‘Q‘, ‘R‘, ‘S‘, ‘T‘, ‘U‘, ‘V‘, ‘W‘, ‘X‘, ‘Y‘,
				‘Z‘, ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘, ‘h‘, ‘i‘, ‘j‘, ‘k‘,
				‘l‘, ‘m‘, ‘n‘, ‘o‘, ‘p‘, ‘q‘, ‘r‘, ‘s‘, ‘t‘, ‘u‘, ‘v‘, ‘w‘,
				‘x‘, ‘y‘, ‘z‘ };
		for (int i = 0; i < num; i++) {
			int id = (int) Math.ceil(Math.random() * 60);
			sb.append(chars[id]);
		}
		return sb.toString();
	}

	/**
	 * 
	 * @Description:解密pin
	 * @param request
	 * @param pin
	 * @return
	 * 
	 */
	public static String decryptPinData(HttpServletRequest request,
			String ciphertextpin) throws Exception {
		if (StringUtils.isNotBlank(ciphertextpin)) {
			Map<String, String> valuekeys = (Map<String, String>) request
					.getSession().getAttribute("valuekeys");
			if (valuekeys == null || valuekeys.size() != 10) {
				throw new Exception();
			}
			String[] ciphertextpins = ciphertextpin.split(",");
			StringBuffer sb = new StringBuffer("");
			for (String ctpin : ciphertextpins) {
				sb.append(valuekeys.get(ctpin));
			}
		}
		return null;
	}
}


4).获取图片流后台方法

用户页面获取到随机密文集合后以循环的方式向后台请求该方法获取对应的数字图片流。具体代码如下:

/**
	 * 获取key图片
	 * 
	 * @throws Exception
	 */
	@RequestMapping(value = http://www.mamicode.com/"/common/getKey.do", method = RequestMethod.GET)>

5).用户支付


当用户点击数字键盘中的数字图片,就会把图片对应的密文放入到pkey隐藏输入框中,多个数字以逗号隔开,当点击支付的时候,就

会把peykey隐藏输入框的值传入到后台,后台从redis中取出“密文”与“1234567890数字“的对应关系,就取出了对应交易密码。具体代码如下:

页面提交支付js:

function check()
{
	hideKey();
	var pin="";
	
		
		pin=$("#pkey").val();
		if(pin==""||pin==undefined)
		{
			bool=false;
			alert("请输入交易密码");
			
			return false;
		}else
		{
			var keys=pin.split(",");
			if(keys.length!=6)
			{
				alert("请输入6位交易密码");
				
				return false;
			}
		}
		$.ajax({
			type : ‘post‘,
			url : "test/pay.do",
			data : {
				random:"2321321321",
				pin:pin
			},
			cache : false,
			success : function(data) { 
				if(data.success)
					{
					  alert(data.message);
					}else{
						
					}
				
			},
			error : function(){
				
				alert("系统异常,请重试!");
			}
		});
}


后台解析密文方法:

/**
	 * 
	 * @Description: 支付
	 * @param pin 交易密码密文
	 * @param random 随机码
	 * @return
	 * 
	 */
	@ResponseBody
	@RequestMapping(value = http://www.mamicode.com/"/test/pay.do", method = RequestMethod.POST)>

以上就是对使用spring+html5实现安全传输随机数字密码键盘的介绍和代码实现,大家有什么疑问或设计的不合理的地方可以一起讨论,需要源码请联系我。

使用spring+html5实现安全传输随机数字密码键盘