Commit e38f1a14 by WeiCong

修改密码安全策略

parent d2a9f666
......@@ -10,8 +10,11 @@ import org.sss.common.model.IFilter;
import org.sss.common.model.IMenuItem;
import org.sss.presentation.noui.api.response.ErrorCode;
import org.sss.presentation.noui.util.NoUiUtils;
import org.sss.presentation.noui.util.StringUtil;
import org.sss.util.ContainerUtils;
import sun.misc.BASE64Decoder;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.time.Duration;
import java.time.LocalDateTime;
......@@ -25,8 +28,8 @@ import java.util.*;
* $
*/
public class DatabaseLoginContextForELCS extends AbstractLoginContext {
public static final String ERROR = "error";
final static Log log = LogFactory.getLog(DatabaseLoginContextForELCS.class);
final static String ERROR_USERNAME_PASSWORD = "error.username.password";
final static String ERROR_USER_LOCKED = "error.user.locked";
final static String ERROR_USER_EXPRIED = "error.user.expired";
......@@ -41,7 +44,6 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
final static String FLAG_INDIRECT = "1";
final static String FLAG_SKIP = "2";
final static String MENU_FREQUENT_ITEM = "menu.frequent";
final static int INDEX_INR = 1;
final static int INDEX_PNTINR = 2;
final static int INDEX_FRM = 3;
......@@ -51,7 +53,7 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
final static int INDEX_IMG = 7;
final static int INDEX_STL = 8;
final static int INDEX_CLS = 9;
private static final String loginCheck = "loginCheck.properties";
public static int defaultSessionTimeout = 3600;
public static String defaultHomePageName = "/layout.zul";
public static String defaultHomeTransaction = "office";
......@@ -59,6 +61,15 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
public static boolean loginOnlyOnce = true;
public static String imageNull = null;
public static String imageFrequent = null;
static int ERROR_MAX_COUNT = 5;
//用户距离上次修改密码间隔
private static Duration pwdAmeInterval = Duration.ofDays(30);
//连续多次输入密码重置
private static int maxfltcnt = 5;
static {
init();
}
protected final MenuItem menu = new MenuItem();
private String userId;
......@@ -70,20 +81,6 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
private String homeTransaction = "office";
private int sessionTimeout = 3600;
private static final String loginCheck="loginCheck.properties";
public static final String ERROR="error";
//用户距离上次修改密码间隔
private static Duration pwdAmeInterval=Duration.ofDays(30);
//连续多次输入密码重置
private static int maxfltcnt=5;
static int ERROR_MAX_COUNT = 5;
static {
init();
}
private static void init() {
try {
Properties props = new Properties();
......@@ -93,10 +90,77 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
maxfltcnt = Integer.parseInt(props.getProperty("maxfltcnt"));
} catch (Exception e) {
//load失败启用默认值
log.error("load loginCheck.properties failed",e);
log.error("load loginCheck.properties failed", e);
}
}
/**
* 用户原文密码解密,先传统base64解密,然后对解密后的字符串的首位字符串进行偏移【头4 尾7】
*
* @param pwd 待解签串
* @return 解签后的字符串
*/
public static String pwdDecode(String pwd) {
if (StringUtil.isEmpty(pwd)) {
return "";
}
BASE64Decoder decoder = new BASE64Decoder();
try {
pwd = new String(decoder.decodeBuffer(pwd), StandardCharsets.UTF_8);
pwd = convert(pwd);
} catch (Exception e) {
log.warn("密码解密失败,使用原密码");
}
return pwd;
}
//偏移 头4 尾7
private static String convert(String str) {
if(str.length()==1){
return change(str.charAt(0), 4);
}else if(str.length()==2){
return change(str.charAt(0), 4)+change(str.charAt(1), 7);
}else{
String btw_str = str.substring(1, str.length() - 1);
String head = change(str.charAt(0), 4);
String tail = change(str.charAt(str.length() - 1), 7);
return head + btw_str + tail;
}
}
//根据偏移量转换字符
private static String change(char ch, int offset) {
int before = ch;
int after;
//a-z
if (ch >= 97 && ch <= 122) {
if (before + offset <= 122) {
after = before + offset;
} else {
after = (before + offset) % 122 + 96;
}
return String.valueOf((char) after);
}
//A-Z
else if (ch >= 65 && ch <= 90) {
if (before + offset <= 90) {
after = before + offset;
} else {
after = (before + offset) % 90 + 64;
}
return String.valueOf((char) after);
}
//0-9
else if (ch >= 48 && ch <= 57) {
if (before + offset <= 57) {
after = before + offset;
} else {
after = (before + offset) % 57 + 47;
}
return String.valueOf((char) after);
}
return String.valueOf(ch);
}
protected boolean isVersion2() {
return false;
......@@ -153,11 +217,12 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
}
public String checkPassword(String userName, String dbPassword, String password) {
password=pwdDecode(password);
IFilter passwordFilter = NoUiUtils.passwordFilter;
if(NoUiUtils.passwordFilter == null){
if (NoUiUtils.passwordFilter == null) {
log.info("请在eibs.xml为NoUiUtils配置passwordFilter项");
}
if (dbPassword != null){
if (dbPassword != null) {
dbPassword = dbPassword.trim();
}
String encodedPassword = ContainerUtils.encodeWithSalt ? passwordFilter.encode(password, userName).trim() : passwordFilter.encode(password).trim();
......@@ -175,7 +240,7 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
String sendcode = getParameter(parameterMap, "j_sendcode");
String verifycode = getParameter(parameterMap, "j_verifycode");
// String dncode = getParameter(parameterMap, "j_dncode");
if (userName == null || password == null /*|| dncode==null*/ ){
if (userName == null || password == null /*|| dncode==null*/) {
parameterMap.put(ERROR, ErrorCode.LOGIN_PARAMETER_CHECK);
return setLogon(false, userName, ERROR_USERNAME_PASSWORD, "用户名或密码为空.", null, null);
}
......@@ -188,7 +253,7 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
stmt.setString(1, userName);
rs = stmt.executeQuery();
if (!rs.next()) {
if (!guestAccountUsed){
if (!guestAccountUsed) {
parameterMap.put(ERROR, ErrorCode.LOGIN_NON_USR);
return setLogon(false, userName, ERROR_USERNAME_PASSWORD, "系统无此用户.", stmt, rs);
}
......@@ -198,8 +263,8 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
sessionTimeout = -1;
return setLogon(true, userName, null, "游客成功登录.", stmt, rs);
}
if(sendcode==null || verifycode==null || !sendcode.equalsIgnoreCase(verifycode)){
log.info("验证码验证失败,待校验:"+sendcode+",原始:"+verifycode);
if (sendcode == null || verifycode == null || !sendcode.equalsIgnoreCase(verifycode)) {
log.info("验证码验证失败,待校验:" + sendcode + ",原始:" + verifycode);
parameterMap.put(ERROR, ErrorCode.LOGIN_VERIFYCODE_ERROR);
return setLogon(false, userName, ErrorCode.LOGIN_VERIFYCODE_ERROR.getCode(), ErrorCode.LOGIN_VERIFYCODE_ERROR.getMessage(), stmt, rs);
}
......@@ -214,15 +279,14 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
ukey = rs.getString(8);
DbUtils.closeQuietly(stmt);
DbUtils.closeQuietly(rs);
String errorStr=checkPassword(userName, dbPassword, password);
if (STATUS_LOCKED.equals(userState)){
String errorStr = checkPassword(userName, dbPassword, password);
if (STATUS_LOCKED.equals(userState)) {
parameterMap.put(ERROR, ErrorCode.LOGIN_LOCK_USR);
return setLogon(false, userName, ERROR_USER_LOCKED, "用户已被锁定.", stmt, rs);
}
else if (STATUS_EXPIRED.equals(userState)){
} else if (STATUS_EXPIRED.equals(userState)) {
parameterMap.put(ERROR, ErrorCode.LOGIN_EXPRIED_USR);
return setLogon(false, userName, ERROR_USER_EXPRIED, "用户已被注销.", stmt, rs);
} else if (!STATUS_NORMAL.equals(userState)){//非0:正常;1:注销;2:锁定,不可登录,
} else if (!STATUS_NORMAL.equals(userState)) {//非0:正常;1:注销;2:锁定,不可登录,
parameterMap.put(ERROR, ErrorCode.LOGIN_STATE_ABNORMAL_ERROR);
return setLogon(false, userName, ErrorCode.LOGIN_STATE_ABNORMAL_ERROR.getCode(), ErrorCode.LOGIN_STATE_ABNORMAL_ERROR.getMessage(), stmt, rs);
} /*else if (!Objects.equals(ukey,dncode)) {//dn码错误
......@@ -400,45 +464,6 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
}
}
class Menu implements Comparable<Menu> {
String id;
String parentId;
String transactionName;
String image;
String style;
String styleClass;
String descriptionKey;
String flag;
public Menu(String id, String parentId, String transactionName, String image, String style, String styleClass,
String descriptionKey, String flag) {
this.id = id;
this.parentId = parentId;
this.transactionName = transactionName;
this.image = image;
this.style = style;
this.styleClass = styleClass;
this.descriptionKey = descriptionKey;
this.flag = flag;
}
@Override
public int compareTo(Menu menu) {
if (parentId == null && menu.parentId != null)
return -1;
else if (parentId != null && menu.parentId == null)
return 1;
return id.compareTo(menu.id);
}
@Override
public String toString() {
if (parentId == null)
return "<NULL>" + id + transactionName;
return parentId + id + transactionName;
}
}
private void calculateMenu(ResultSet rs, Map<String, Menu> menuList, Map<String, Menu> frequentList,
List<String> removeMenuList, List<String> removeFrequentList, boolean flag) throws Exception { // 如果为用户信息或第一条角色信息时,直接操作待删除菜单和待删除常用菜单
// 注:多角色叠加菜单时以最大可显示的方式进行处理:可见/常用直接增加,不可见或不常用待全部角色都不可见或不常用时才处理(多角色在所有角色处理结束后再处理)
......@@ -484,6 +509,56 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
}
}
private boolean addMenu(MenuItem item, Menu parentMenu, Menu menu) {
if (parentMenu == null || parentMenu.id.equals(item.id)) {
item.add(new MenuItem(menu.id, getI18nValue(menu.descriptionKey), menu.transactionName, menu.image));
return true;
}
for (IMenuItem subItem : item)
if (addMenu((MenuItem) subItem, parentMenu, menu))
return true;
return false;
}
class Menu implements Comparable<Menu> {
String id;
String parentId;
String transactionName;
String image;
String style;
String styleClass;
String descriptionKey;
String flag;
public Menu(String id, String parentId, String transactionName, String image, String style, String styleClass,
String descriptionKey, String flag) {
this.id = id;
this.parentId = parentId;
this.transactionName = transactionName;
this.image = image;
this.style = style;
this.styleClass = styleClass;
this.descriptionKey = descriptionKey;
this.flag = flag;
}
@Override
public int compareTo(Menu menu) {
if (parentId == null && menu.parentId != null)
return -1;
else if (parentId != null && menu.parentId == null)
return 1;
return id.compareTo(menu.id);
}
@Override
public String toString() {
if (parentId == null)
return "<NULL>" + id + transactionName;
return parentId + id + transactionName;
}
}
class MenuItem extends MenuItemImpl {
String id;
......@@ -502,16 +577,4 @@ public class DatabaseLoginContextForELCS extends AbstractLoginContext {
return String.format("Id = %s,Label = %s,Value = %s", id, label, value);
}
}
private boolean addMenu(MenuItem item, Menu parentMenu, Menu menu) {
if (parentMenu == null || parentMenu.id.equals(item.id)) {
item.add(new MenuItem(menu.id, getI18nValue(menu.descriptionKey), menu.transactionName, menu.image));
return true;
}
for (IMenuItem subItem : item)
if (addMenu((MenuItem) subItem, parentMenu, menu))
return true;
return false;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment