最近做了一个功能,是管理用户账户对接支付的一个模块,里面有一个是做提款账户的管理的功能,这个功能里面涉及到用户的银行卡号和手机号,根据需求为了保密性这里的银行卡号和手机号是不能在页面上展示的,需要后端来解决这个问题。因此我准备了两套方案来解决这个问题。
一、通过mysql的concat、left、right函数:
先看下页面效果:
所以这里只需要在MySQL中操作即可获取到加密后的数据:
account_name:卡名
account_no :卡号
account_type:卡的类型
sys_company_withdraw_account:提款账户的表名
-----------------------0-----------------------------
concat:拼接函数,concat(‘字符串1’,‘拼接参数’,‘字符串2’)
left:函数,left(‘字符串’,从左开始的截取长度)
right:函数,right(‘字符串’,从右边开始截取的长度)
select account_name,
concat(left(account_no,4),'********',right(account_no,4))as accountNo,
concat(left(mobile_no,4),'***',right(mobile_no,4)) as mobileNo,
account_type
from sys_company_withdraw_account scwa
where scwa.del_flag=0;
效果如下:
二、insert函数:
insert(a,n1,n2,str)的参数解析如下:
a:字段名.
n1:开始替换的位置.从1开始算起
n2:替换的长度.
str:替换后的字符串.
select account_name, insert(account_no,5,4,'****')as accountNo, insert(mobile_no,4,4,'***') as mobileNo, account_type from sys_company_withdraw_account scwa where scwa.del_flag=0;
三、自定义函数:
这里要用到sqlyoung:两种打开函数的方式
1、点开对象,里面的函数,创建函数
2、右击function,创建函数
3、创建一个名为fun_hideMainCode的函数
会出一个函数的模板:
DELIMITER $$
CREATE
/*[DEFINER = { user | CURRENT_USER }]*/
FUNCTION `jycloud`.`fun_hide`()
RETURNS TYPE
/*LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'*/
BEGIN
END$$
DELIMITER ;
编写函数:
DELIMITER $$
USE `jycloud`$$
DROP FUNCTION IF EXISTS `fun_hideMainCode`$$
CREATE DEFINER=`root`@`%` FUNCTION `fun_hideMainCode`(`v_type` VARCHAR(20),`v_code` VARCHAR(100)) RETURNS VARCHAR(100) CHARSET utf8
BEGIN
DECLARE result_code VARCHAR(100);
DECLARE begin_code VARCHAR(50);
DECLARE hide_code VARCHAR(50);
DECLARE end_code VARCHAR(50);
IF v_type = 'bank_card_account' THEN
SET begin_code = LEFT(v_code, 4);
SET hide_code = '*****';
SET end_code = RIGHT(v_code, 4);
SET result_code = CONCAT(begin_code, hide_code, end_code);
ELSEIF v_type = 'phone_num' THEN
SET begin_code = LEFT(v_code, 3);
SET hide_code = '****';
SET end_code = RIGHT(v_code, 4);
SET result_code = CONCAT(begin_code, hide_code, end_code);
ELSE
SET result_code = v_code;
END IF;
RETURN result_code;
END$$
DELIMITER ;
这里的
v_type = ‘bank_card_account’
v_type = ‘phone_num’
bank_card_account表示传进来的卡号字段
phone_num表示手机号字段。
4、在你的MySQL中引入此函数:
/*函数*/
select
id,
company_id,
bank_code,
bank_name,
account_name,
fun_hideMainCode('bank_card_account',account_no) AS account_no,
account_type,
fun_hideMainCode('phone_num',mobile_no) AS mobile_no,
is_default
from sys_company_withdraw_account scwa
where scwa.del_flag=0;
'bank_card_account’表示需要替换的银行卡号字段,
account_no表示传进来的银行卡号的字段。
效果如下:
在mybatis中使用直接把sql拷贝过去就可以了。
这里有个坑点,是本人亲自踩出来的坑。
在mybatis中,如果你用resulttype,这里查询的字段,as后面使用对象来接收的,必须as为数据库里面的字段。如果改成大写,可能查出来的数据里面没有这个字段。
四、后台硬编码编写工具类,更改查询的字段:
@Override
public PageInfo getCount(SysCompanyWithdrawAccount account, Integer page, Integer size) {
page = page == null ? 1 : page;
size = size == null ? 10 : size;
PageHelper.startPage(page, size);
/*获取账户结果集*/
List<SysCompanyWithdrawAccount> list=dao.getCount(account);
for (SysCompanyWithdrawAccount sysCompanyWithdrawAccount:list){
//获取卡号
String accountNo=sysCompanyWithdrawAccount.getAccountNo();
//获取手机号
String mobileNo=sysCompanyWithdrawAccount.getMobileNo();
//隐藏银行卡中间的字符串
int length = accountNo.length();
int beforeLength = 4;
int afterLength = 4;
//替换字符串,当前使用“*”
String replaceSymbol = "*";
StringBuffer sb = new StringBuffer();
for(int i=0; i<length; i++) {
if(i < beforeLength || i >= (length - afterLength)) {
sb.append(accountNo.charAt(i));
} else {
//通过追加的方式
sb.append(replaceSymbol);
}
}
//隐藏手机号中间位置字符,显示前三后三个字符
int length1 = mobileNo.length();
int beforeLength1 = 3;
int afterLength1 = 3;
//替换字符串,当前使用“*”
String replaceSymbol1 = "*";
StringBuffer sb1 = new StringBuffer();
for(int i=0; i<length; i++) {
if(i < beforeLength1 || i >= (length1 - afterLength1)) {
sb1.append(mobileNo.charAt(i));
} else {
sb1.append(replaceSymbol1);
}
}
}
return new PageInfo<>(dao.getCount(account));
}
这我将它编写成了一个工具类HideDataUtil:
import org.apache.commons.lang3.StringUtils;
public class HideDataUtil {
/**
* 隐藏银行卡号中间的字符串(使用*号),显示前四后四
* @param cardNo
* @return
*/
public static String hideCardNo(String cardNo) {
if(StringUtils.isBlank(cardNo)) {
return cardNo;
}
int length = cardNo.length();
int beforeLength = 4;
int afterLength = 4;
//替换字符串,当前使用“*”
String replaceSymbol = "*";
StringBuffer sb = new StringBuffer();
for(int i=0; i<length; i++) {
if(i < beforeLength || i >= (length - afterLength)) {
sb.append(cardNo.charAt(i));
} else {
sb.append(replaceSymbol);
}
}
return sb.toString();
}
/**
隐藏手机号中间位置字符,显示前三后三个字符
* @param phoneNo
* @return
*/
public static String hidePhoneNo(String phoneNo) {
if(StringUtils.isBlank(phoneNo)) {
return phoneNo;
}
int length = phoneNo.length();
int beforeLength = 3;
int afterLength = 3;
//替换字符串,当前使用“*”
String replaceSymbol = "*";
StringBuffer sb = new StringBuffer();
for(int i=0; i<length; i++) {
if(i < beforeLength || i >= (length - afterLength)) {
sb.append(phoneNo.charAt(i));
} else {
sb.append(replaceSymbol);
}
}
return sb.toString();
}
}
测试一下:
public static void main(String[] args) {
//$1 $2 表示正则表达式里面的第一个和第二个,也就是括号里面的内容
System.out.println(StringUtils.replacePattern("12321120687","(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
System.out.println("12321120687".replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
System.out.println("1425665665525895689".replaceAll("(\\d{4})\\d{4}(\\d{4})\\d{4}(\\d{3})", "$1****$2****$3"));
}
在这里拓展一下:MySQL优化里面,使用函数时,添加if else判断,在sql执行之后会将判断条件放在sql中,从而影响数据库的性能,因此一般不建议使用函数。