数据库通常需要对密码进行加密处理,如果已经使用了明文,则需要进行加密迁移。
1. 明文数据库
CREATE DATABASE `test` ;
USE `test`;
insert into `t_a`(`id`,`name`,`password`) values
(1,'123','qw1r1re'),
(2,'12','qw1r12re'),
(3,'3','qw12r12re'),
(4,'4','q12r1we'),
(5,'2','qw12r12re'),
(6,'423','qw12r12re'),
(7,'2341','qw12r312re'),
(8,'12','qw123r1e'),
(9,'431','qw123re'),
(10,'123','qwr312re');
2. 目标数据库
CREATE DATABASE `test_b` ;
USE `test_b`;
DROP TABLE IF EXISTS `t_a`;
CREATE TABLE `t_a` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(16) DEFAULT NULL,
`password` blob,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=63 DEFAULT CHARSET=utf8;
3.对密码使用md5加密后迁移到目标库
INSERT INTO test_b.t_a (name,password)
SELECT name,MD5(password) FROM test.t_a;
加密迁移后的效果:
4. java实现的md5加密工具
public class MD5Utils {
public final static String MD5(String s) {
char hexDigits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
try {
byte[] btInput = s.getBytes();
// 获得MD5摘要算法的 MessageDigest 对象
MessageDigest mdInst = MessageDigest.getInstance("MD5");
// 使用指定的字节更新摘要
mdInst.update(btInput);
// 获得密文
byte[] md = mdInst.digest();
// 把密文转换成十六进制的字符串形式
int j = md.length;
char str[] = new char[j * 2];
int k = 0;
for (int i = 0; i < j; i++) {
byte byte0 = md[i];
str[k++] = hexDigits[byte0 >>> 4 & 0xf];
str[k++] = hexDigits[byte0 & 0xf];
}
return new String(str).toLowerCase();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
System.out.println("数据库加密和java加密结果对比:");
System.out.println("202cb962ac59075b964b07152d234b70".equals(MD5Utils.MD5("123")));
}
}
5. 密码复杂度校验
5.1 前台校验
function checkPasswordFormat() {
var password=document.getElementsByName("user.password").value;
var strongRegex = new RegExp(
"^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$", "g");
if (strongRegex.test(password)) {
return true;
} else {
alert("密码格式必须同时有大写字母,小写字母,数字,除了字母数字下划线以外的字符,且至少8位!");
return false;
}
}
5.2 后台校验
5.2.1 检查密码字符串是否连续。KeywordUtil.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
public class KeywordUtils {
private static Map<String, String> keyMap;
/**
* 检查字符串是否连续
* @param password 密码字符串
* @return 不连续返回false 完全连续返回true
*/
public static boolean checkPassword(String password) {
return checkPassword(password, 0);
}
/**
* 检查字符串是否连续
*
* @param password
* 密码字符串
* @param diff
* 字符串连续数相差diff个算连续 例:字符串长度为15,
* 理论最大连续个数为14,diff为2时,连续13个时为连续字符串,连续12个为非连续字符串
* @return 不连续返回false 连续返回true
*
*/
public static boolean checkPassword(String password, int diff) {
if (password.length() <= 1) {
return false;
}
int length = password.length() - 1;
int count = checkContinue(password);
if (count < length - diff) {
return false;
}
return true;
}
private static int checkContinue(String password) {
if (keyMap == null) {
initKeyMap();
}
int count = 0;
for (int i = 0; i < password.length() - 1; i++) {
char c = password.charAt(i);
char nextChar = password.charAt(i + 1);
String s = keyMap.get(c + "");
if (StringUtils.isNotBlank(s) && s.indexOf(nextChar) >= 0) {
count++;
}
}
return count;
}
private static void initKeyMap() {
keyMap = new HashMap<String, String>();
keyMap.put("`", "1!");
keyMap.put("~", keyMap.get("`"));
keyMap.put("1", "`q2~Q@");
keyMap.put("!", keyMap.get("1"));
keyMap.put("2", "1qw3!QW#");
keyMap.put("@", keyMap.get("2"));
keyMap.put("3", "2we4@WE$");
keyMap.put("#", keyMap.get("3"));
keyMap.put("4", "3er5#ER%");
keyMap.put("$", keyMap.get("4"));
keyMap.put("5", "4rt6$RT^");
keyMap.put("%", keyMap.get("5"));
keyMap.put("6", "5ty7%TY&");
keyMap.put("^", keyMap.get("6"));
keyMap.put("7", "6yu8^YU*");
keyMap.put("&", keyMap.get("7"));
keyMap.put("8", "7ui9&UI(");
keyMap.put("*", keyMap.get("8"));
keyMap.put("9", "8io0*IO)");
keyMap.put("(", keyMap.get("9"));
keyMap.put("0", "9op-(OP_");
keyMap.put(")", keyMap.get("0"));
keyMap.put("-", "0p[=)P{+");
keyMap.put("_", keyMap.get("-"));
keyMap.put("=", "-[]_{}");
keyMap.put("+", keyMap.get("="));
keyMap.put("q", "12wa!@WA");
keyMap.put("Q", keyMap.get("q"));
keyMap.put("w", "2qase3@QASE#");
keyMap.put("W", keyMap.get("w"));
keyMap.put("e", "3wsdr4#WSDR$");
keyMap.put("E", keyMap.get("e"));
keyMap.put("r", "4edft5$EDFT%");
keyMap.put("R", keyMap.get("r"));
keyMap.put("t", "5rfgy6%RFGY^");
keyMap.put("T", keyMap.get("t"));
keyMap.put("y", "6tghu7^TGHU&");
keyMap.put("Y", keyMap.get("y"));
keyMap.put("u", "7yhji8&YHJI*");
keyMap.put("U", keyMap.get("u"));
keyMap.put("i", "8ujko9*UJKO(");
keyMap.put("I", keyMap.get("i"));
keyMap.put("o", "9iklp0(IKLP)");
keyMap.put("O", keyMap.get("o"));
keyMap.put("p", "0ol;[-)OL:{_");
keyMap.put("P", keyMap.get("p"));
keyMap.put("[", "-p;']=_P:\"}+");
keyMap.put("{", keyMap.get("["));
keyMap.put("]", "=['\\+{\"|");
keyMap.put("}", keyMap.get("]"));
keyMap.put("\\", "]}");
keyMap.put("|", keyMap.get("\\"));
keyMap.put("a", "qwszQWSZ");
keyMap.put("A", keyMap.get("a"));
keyMap.put("s", "wazxdeWAZXDE");
keyMap.put("S", keyMap.get("s"));
keyMap.put("d", "esxcfrESXCFR");
keyMap.put("D", keyMap.get("d"));
keyMap.put("f", "rdcvgtRDCVGT");
keyMap.put("F", keyMap.get("f"));
keyMap.put("g", "tfvbhyTFVBHY");
keyMap.put("G", keyMap.get("g"));
keyMap.put("h", "ygbnjuYGBNJU");
keyMap.put("H", keyMap.get("h"));
keyMap.put("j", "uhnmkiUHNMKI");
keyMap.put("J", keyMap.get("j"));
keyMap.put("k", "ijm,loIJM<LO");
keyMap.put("K", keyMap.get("k"));
keyMap.put("l", "ok,.;pOK<>:P");
keyMap.put("L", keyMap.get("l"));
keyMap.put(";", "pl./'[PL>?\"{");
keyMap.put(":", keyMap.get(";"));
keyMap.put("'", "][;/}{:?");
keyMap.put("\"", keyMap.get("'"));
keyMap.put("z", "asxASX");
keyMap.put("Z", keyMap.get("z"));
keyMap.put("x", "zsdcZSDC");
keyMap.put("X", keyMap.get("x"));
keyMap.put("c", "xdfvXDFV");
keyMap.put("C", keyMap.get("c"));
keyMap.put("v", "cfgbCFGB");
keyMap.put("V", keyMap.get("v"));
keyMap.put("b", "vghnVGHN");
keyMap.put("B", keyMap.get("b"));
keyMap.put("n", "bhjmBHJM");
keyMap.put("N", keyMap.get("n"));
keyMap.put("m", "njk,NJK<");
keyMap.put("M", keyMap.get("m"));
keyMap.put(",", "mkl.MKL>");
keyMap.put("<", keyMap.get(","));
keyMap.put(".", ",l;/<L:?");
keyMap.put(">", keyMap.get("."));
keyMap.put("/", ".;'>:\"");
keyMap.put("?", keyMap.get("/"));
}
}
5.2.2 密码不包含用户名等。PasswordUtil.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
public class PasswordUtils {
private static Map<String, String> likeMap;
private static final int LONIN_NAME_LENGTH = 4;
public static boolean checkPasswordFormat(String password) {
String pattern = "^(?=.{8,})(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*\\W).*$*";
boolean flag = Pattern.matches(pattern, password);
return !flag;
}
/**
* 检查密码是否包含完整用户名、大小写、形似
*
* @param password密码
* @param loginName 用户名
* @return 不包含 返回false 包含及形似返回true
*/
public static boolean checkPasswordLoginName(String password,
String loginName) {
if (password.toLowerCase().indexOf(loginName.toLowerCase()) >= 0) {
// 大小写全匹配
return true;
}
if (likeMap == null) {
initLikeMap();
}
if (loginName.length() > LONIN_NAME_LENGTH) {
return checkLike(password.toLowerCase(), loginName.toLowerCase());
}
return false;
}
private static boolean checkLike(String password, String loginName) {
Integer[][] allData = new Integer[loginName.length()][];
int length = loginName.length();
for (int i = 0; i < loginName.length(); i++) {
char c = loginName.charAt(i);
String s = String.valueOf(c);
List<Integer> list = statCharInString(s, s, password);
Integer[] tmp = new Integer[list.size()];
allData[i] = list.toArray(tmp);
}
List<List<Integer>> returnData = new ArrayList<List<Integer>>();
getData(allData, 0, new ArrayList<Integer>(), returnData);
for (int i = 0; i < returnData.size(); i++) {
List<Integer> data = returnData.get(i);
int totalLength = length - 1;
int value = 0;
int thisLength = totalLength;
int lastValue = -2;
int diffValue = 0;
for (int j = 0; j < data.size(); j++) {
if (data.get(j) == -1) {
thisLength--;
continue;
}
if (lastValue == -2) {
lastValue = data.get(j);
continue;
}
if (data.get(j) - lastValue == 1) {
diffValue++;
}
if (data.get(j) > lastValue) {
value += data.get(j) - lastValue;
} else {
value += lastValue - data.get(j);
}
lastValue = data.get(j);
}
if (totalLength - thisLength > totalLength / 3) {
// 缺少超过3分之一 为不相似
continue;
}
if (diffValue > totalLength * 4 / 5) {
// 连续个数超过 5分之4 为相似
return true;
}
if (value > thisLength - 2 && value < thisLength + 2) {
// 所有数位置差 在范围+-2内 为相似
return true;
}
}
return false;
}
private static void getData(Integer[][] data, int count,
List<Integer> dataList, List<List<Integer>> allData) {
if (data[count].length == 0) {
List<Integer> tmp = new ArrayList<Integer>();
for (int j = 0; j < dataList.size(); j++) {
tmp.add(dataList.get(j));
}
tmp.add(-1);
if (count < data.length - 1) {
getData(data, count + 1, tmp, allData);
} else {
allData.add(tmp);
}
} else {
for (int i = 0; i < data[count].length; i++) {
List<Integer> tmp = new ArrayList<Integer>();
for (int j = 0; j < dataList.size(); j++) {
tmp.add(dataList.get(j));
}
tmp.add(data[count][i]);
if (count < data.length - 1) {
getData(data, count + 1, tmp, allData);
} else {
allData.add(tmp);
}
}
}
}
private static List<Integer> statCharInString(String oldstr, String s,
String pwd) {
List<Integer> list = new ArrayList<Integer>();
String tmp = new String(pwd);
int length = 0;
while (tmp.indexOf(s) >= 0) {
int index = tmp.indexOf(s);
int l = length + index;
list.add(l);
tmp = tmp.substring(tmp.indexOf(s) + 1);
length += index + 1;
}
if (oldstr.equals(s)) {
String value = likeMap.get(s);
if (value != null) {
list.addAll(statCharInString(oldstr, value, pwd));
}
}
return list;
}
private static void initLikeMap() {
likeMap = new HashMap<String, String>();
likeMap.put("a", "@");
likeMap.put("o", "0");
likeMap.put("1", "l");
likeMap.put("0", "o");
likeMap.put("l", "1");
}
}