现在网购支付超方便,但是你们担心过安全性吗?只需要学会这招,网上支付就能更安心!今天我就来分享下怎么通过手机使用随机密码键盘付费,保证你们一眼就能看懂,一学就会
移动支付的安全挑战
现在大家都喜欢用手机付款了,因为方便又快,就像我们平常玩手机或者上网那样。但是,第一次用得先绑张银行卡,查对一下号码,别告诉别人交易密码,要不然钱可能会被偷走哟。那怎么保护好我们的交易密码不被人偷看?这个问题可大了。
交易密码的验证过程
保护交易密码?得看它的验证难易度。你们肯定也遇到过这种情况,绑银行卡总是输个交易密码,这跟咱的钱袋子直接挂钩!要是泄露了,那就是中大奖了!所以,验证交易密码这事儿得既简便,又安全才行。
随机数字密码键盘的重要性
想护住你的购物密码吗?试下这款随机数键盘!每次输入数字都会变,不怕被人看或者记下来,用起来超安心的。有了它,付款变得更加放心,用得更舒服!
随机数字密码键盘的实现原理
这破passwordrandomizer真的让人头大!当你打开”交易密码”那部分,你的需求立马被后台知道了。然后后台就开始组装一堆乱七八糟的数字和密文对应关系,存在Redis里等着用。最后,界面上会出现那些密文对应的数字图片,你只需要轻轻一点,输入密码,系统就能根据后台的对应关系,帮你找到真实的交易密码。
<link rel="stylesheet"
href=''>
<script src="">
<script src="">
<script type="text/javascript" src="">
xxx付款
.input-out {
padding-top: 20px;
}
.btn-out {
margin:30px 10px;
}
.btn-out button {
width: 100%;
background: #5CACEE;
border: #5CACEE;
color: #fff;
height: 50px;
border-radius: 3px;
font-size: 18px;
font-family: "Microsoft Yahei", "??????", SimHei, Tahoma, Arial, Helvetica, STHeiti;
}
.keyboard {
background: #fff;
}
.keyboard table {
width:100%;
text-align:center;
}
.keyboard table td {
padding: 15px;
}
.keyboard table a,
.keyboard table a:hover,
.keyboard table a:focus {
color: #333;
text-decoration: none;
}
.input-out label {
color:#D2D1D1;
font-weight: normal;
font-size: 16px;
}
.bottom {
color:#888888;
margin-bottom: 15px;
text-align:center;
margin-top:100px;
}
.bottom a {
color:#888888;
}
.bottom img {
vertical-align: middle;
width: 18px;
}
<form action="/pay" method="post" id="from">
<div class="input-out pass-label" style="border-bottom: 1px solid #ddd;padding-left: 12px;" random="2321321321" path="" >
<img src='" />
客服电话:4000-xxx-xxx
安全传输随机数字密码键盘的代码实现
这个所谓的随机数字密码键盘,其实就是由后面那堆程序搞出来的。它负责生成和保管密文与数字的对应关系,接着安然无恙地送过来给我们看。在我们这边,就是用JavaScript代码接收后台发来的数据,然后根据这个数据动态生成密码键盘,还得处理用户的输入。
$(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()
+ '');
}
$("#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 == null || data == "" || data == "undefined"
|| data.length != 10) {
alert("无法加载密码键盘,请刷新后重试!");
return false;
} else {
var key_table = $("#key_table");
key_table.html("");
var content = '';
for (var i = 0; i < 12; i++) {
if ((i + 1) % 3 == 0 && i != 0 && i <= 5) {
content = content
+ ' |
';
} else if (i <= 7) {
content = content
+ ' | ';
} else if (i == 8) {
content = content
+ ' | '
+ '
';
} else if (i < 11) {
content = content
+ ' | ';
} else {
content = content
+ ' | '
+ '
';
}
}
key_table.html(content);
setTimeout(function() {
$("#keyboard").show();
}, 600);
hengshuping();
}
},
error : function() {
alert("无法加载键盘,请刷新后重试!");
}
});
}
function ontouch(obj) {
var pkey = $("#pkey").val();
var key = $(obj).attr("key");
if (pkey == "") {
$("#pin").html("");
}
var content = $("#pin").html();
if (content != "" && content.length >= 6) {
return false;
}
if (pkey != "") {
key = "," + key;
}
pkey = pkey + key;
$("#pkey").val(pkey);
$("#pin").append("*");
setCssKey();
}
function deleteOne() {
var pkey = $("#pkey").val() + "";
if (pkey == "") {
return false;
}
var local = pkey.lastIndexOf(",");
if (local == -1) {
$("#pkey").val("");
$("#pin").html("交易密码");
setCssNomal();
} else {
pkey = pkey.substring(0, local - 1);
var content = $("#pin").html();
content = content.substring(0, content.length - 1);
$("#pkey").val(pkey);
$("#pin").html(content);
}
}
function _ok() {
$("#key_table").html("");
$("#keyboard").hide();
}
function showkey() {
$("#keyboard").show();
}
function hideKey() {
$("#key_table").html("");
$("#keyboard").hide();
}
function setCssKey() {
$("#pin").css({
"font-size" : "18px",
"color" : "#030303",
"font-weight" : "normal",
"letter-spacing" : "1px"
});
}
function setCssNomal() {
$("#pin").css({
"font-size" : "16px",
"color" : "#D2D1D1",
"font-weight" : "normal"
});
}
用户界面与交互设计
搞定密码键盘要注意界面,简单易用、明了清晰最好!而且,交互设计还得考虑大众喜好,让操作感舒适愉悦。
技术挑战与未来发展
/**
*
* @Description: 获取密码键盘
* @param request
* @param rangdom 随机字符串
* @return
*
*/
@SuppressWarnings("unchecked")
@ResponseBody
@RequestMapping(value = "common/pkey.do", method = RequestMethod.POST)
public Object digitkeyboard(HttpServletRequest request, String rangdom) {
LOG.info("[获取密码键盘digitkeyboard][parames:outOrderId=" + rangdom + "]");
try {
if (StringUtils.isBlank(rangdom)) {
return "";
}
PwdKeyDto pwdkey = PwdKeyUtils.digitkeyboard();
redisUtil.set("pwdkey_" + rangdom, pwdkey,
redisUtil.getDigitkeyimeOut());
return pwdkey.getRundomKeys();
} catch (Exception e) {
LOG.error("[获取密码键盘digitkeyboard][error:{}",e);
}
return "";
}
密码PwdKeyDto:
/**
*
* @ClassName: PwdKeyDto
* @Description: 密码映射Dto
* @author xxxx xxxx@xxx.com
* @date 2015年6月25日 上午11:01:20
*
*/
public class PwdKeyDto implements Serializable{
/**
描述*/
private static final long serialVersionUID = 1L;
private List rundomKeys;// 随机Keys
private Map valueKeyMaps;// 密文和明文映射
private Map imgKeyMaps;// 密文和明文映射
public PwdKeyDto() {
super();
// TODO Auto-generated constructor stub
}
public List getRundomKeys() {
return rundomKeys;
}
public void setRundomKeys(List rundomKeys) {
this.rundomKeys = rundomKeys;
}
public PwdKeyDto(List rundomKeys, Map valueKeyMaps,
Map imgKeyMaps) {
super();
this.rundomKeys = rundomKeys;
this.valueKeyMaps = valueKeyMaps;
this.imgKeyMaps = imgKeyMaps;
}
public Map getValueKeyMaps() {
return valueKeyMaps;
}
public void setValueKeyMaps(Map valueKeyMaps) {
this.valueKeyMaps = valueKeyMaps;
}
public Map getImgKeyMaps() {
return imgKeyMaps;
}
public void setImgKeyMaps(Map imgKeyMaps) {
this.imgKeyMaps = imgKeyMaps;
}
}
,虽然数字键盘可以增加支付的安全性,但是它有些小毛病。那么,怎么才能让这些键盘上的数字是随机显示的?还有就是在同时有很多人用的时候,该怎么办?不过别担心,科技总是在进步,我觉得以后肯定会有更棒的办法来提高我们手机支付的安全性!
总结与展望
/**
*
* @ClassName: PwdKeyUtils
* @Description: 密码处理工具类
* @author xxxx xxxx@xxxx.com
* @date 2015年6月25日 上午11:03:24
*
*/
public class PwdKeyUtils {
private final static Map imagesValueMap;
/**
*
* @Description: 获取密码键盘映射关系
* @param imagesValueMap
* @return
*
*/
static {
imagesValueMap = new HashMap();
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 rundomKeys = new ArrayList();// 随机key映射
Map valueKeys = new HashMap();// 密文和明文映射
Map imgKeyMaps = new HashMap();// 密文和图片映射
List keys = new ArrayList();
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 valuekeys = (Map) 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;
}
}
说实话,搞这个挺费劲的,就跟设个密码锁似的,得好用还不能让人烦心,简直太难了。其实,就是靠那些数学方法搞定的。以后这趋势,手机支付肯定越做越好,肯定会有更好用、更安全的付钱方式出来,让咱们过得舒坦点。
大伙儿好!咱来聊聊,用手机付钱的时候,你最在乎啥子?是安全性还是便利性呀?快去下面回复告诉我!别忘了给我点个赞,分享给其他人,让他们也学学怎么保护手机支付安全!
/**
* 获取key图片
*
* @throws Exception
*/
@RequestMapping(value = "/common/getKey.do", method = RequestMethod.GET)
public void getKey(String key, String rangdom, HttpServletRequest request,
HttpServletResponse response) throws Exception {
LOG.info("[获取密码键盘key(getKey)][parms:key=" + key + "]");
PwdKeyDto pwdkey = (PwdKeyDto) redisUtil.get("pwdkey_" + rangdom);
if (pwdkey == null || pwdkey.getImgKeyMaps() == null) {
LOG.error("获取图片[getKey]:未获取到对应的键盘的映射关系");
throw new Exception();
}
Map imagekeys = pwdkey.getImgKeyMaps();
String path = imagekeys.get(key);
String rootPath = request.getSession().getServletContext()
.getRealPath("/");
path = rootPath + path;
LOG.info("[获取密码键盘key(getKey)][path=" + path + "]");
if (StringUtils.isNotEmpty(path)) {
try {
InputStream fis = new FileInputStream(new File(path));
BufferedInputStream bis = new BufferedInputStream(fis);
OutputStream fos = response.getOutputStream();
BufferedOutputStream bos = new BufferedOutputStream(fos);
String fileName = "image.";
String[] strs = path.split("\.");
fileName = fileName + strs[strs.length - 1];
setFileDownloadHeader(request, response, fileName);
int byteRead = 0;
byte[] buffer = new byte[8192];
while ((byteRead = bis.read(buffer, 0, 8192)) != -1) {
bos.write(buffer, 0, byteRead);
}
bos.flush();
fis.close();
bis.close();
fos.close();
bos.close();
} catch (Exception e) {
LOG.error("获取图片[path:" + path + "])失败:" + e.toString(), e);
}
}
}
评论0