Commit 78145c41 by 胡文明

loginCheck.properties配置文件归属于 classpath路径

DatabaseLoginContextForELCS属于人行独有
parent d2e57ae3
package cn.com.brilliance.eibs.auth;
import log.Log;
import log.LogFactory;
import org.apache.commons.dbutils.DbUtils;
import org.sss.common.impl.AbstractLoginContext;
import org.sss.common.impl.MenuItemImpl;
import org.sss.common.impl.PasswordFilter;
import org.sss.common.model.IContext.DataType;
import org.sss.common.model.IMenuItem;
import org.sss.presentation.noui.api.response.ErrorCode;
import org.sss.util.ContainerUtils;
import java.sql.*;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
/**
* LoginModule实现示例
*
* @author Jason.Hoo (latest modification by $Author: hujianxin $)
* @version $Revision: 922 $ $Date: 2014-11-19 16:05:38 +0800 (Wed, 19 Nov 2014)
* $
*/
public class DatabaseLoginContextForELCS extends AbstractLoginContext {
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";
final static String ERROR_SYSTEM_FAULT = "error.system.fault";
final static String STATUS_NORMAL = "0";
final static String STATUS_EXPIRED = "1";
final static String STATUS_LOCKED = "2";
final static String TYPE_VISIBLE = "0";
final static String TYPE_INVISIBLE = "1";
final static String TYPE_FREQUENT = "2";
final static String FLAG_NORMAL = "0";
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;
final static int INDEX_DSP = 4;
final static int INDEX_TYP = 5;
final static int INDEX_FLG = 6;
final static int INDEX_IMG = 7;
final static int INDEX_STL = 8;
final static int INDEX_CLS = 9;
public static int defaultSessionTimeout = 3600;
public static String defaultHomePageName = "/layout.zul";
public static String defaultHomeTransaction = "office";
public static boolean guestAccountUsed = false;
public static boolean loginOnlyOnce = true;
public static String imageNull = null;
public static String imageFrequent = null;
protected final MenuItem menu = new MenuItem();
private String userId;
private String userRol;
private String userEty;
private Timestamp pwdamedat;
private String ukey;
private String homePageName = "/layout.zul";
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();
// 加载配置文件
props.load(DatabaseLoginContextForELCS.class.getClassLoader().getResourceAsStream(loginCheck));
pwdAmeInterval = Duration.ofDays(Integer.parseInt(props.getProperty("pwdAmeInterval")));
maxfltcnt = Integer.parseInt(props.getProperty("maxfltcnt"));
} catch (Exception e) {
//load失败启用默认值
log.error("load loginCheck.properties failed",e);
}
}
protected boolean isVersion2() {
return false;
}
private String getVersion2Sql() {
return isVersion2() ? ",m.img,m.stl,m.stlcls" : "";
}
private String getVersion2String(ResultSet rs, int index) throws SQLException {
return isVersion2() ? rs.getString(index) : null;
}
private String getI18nValue(String key) {
return ctx.getGui().getI18nValue("eibs", key);
}
private boolean setLogon(boolean flag, String userName, String type, String logText, Statement stmt, ResultSet rs) {
DbUtils.closeQuietly(rs);
DbUtils.closeQuietly(stmt);
if (flag) {
if (loginOnlyOnce)
ctx.logout(DataType.USER_NAME, userName);
this._userName = userName;
}
log.warn(String.format("%s,userName=[%s]", logText, userName));
errorText = flag ? "" : getI18nValue(type);
this.flag = flag;
return flag;
}
private boolean setAuth(boolean flag, Statement stmt1, ResultSet rs1, Statement stmt2, ResultSet rs2) {
DbUtils.closeQuietly(rs1);
DbUtils.closeQuietly(stmt1);
DbUtils.closeQuietly(rs2);
DbUtils.closeQuietly(stmt2);
this.authed = flag;
return flag;
}
@Override
public String getHomePageName() {
return homePageName;
}
@Override
public String getHomeTransaction() {
return homeTransaction;
}
@Override
public int getSessionTimeout() {
return sessionTimeout;
}
public String checkPassword(String userName, String dbPassword, String password) {
PasswordFilter passwordFilter = new PasswordFilter();
if (dbPassword != null)
dbPassword = dbPassword.trim();
String encodedPassword = passwordFilter.encode(password).trim();
log.debug("password(input/db)" + dbPassword + "\t" + encodedPassword);
if (!encodedPassword.equals(dbPassword))
return "[Database: NOT Match.]";
return null;
}
@Override
public boolean login(Connection conn, Map parameterMap) {
this._userName = null;
String userName = getParameter(parameterMap, "j_username");
String password = getParameter(parameterMap, "j_password");
String dncode = getParameter(parameterMap, "j_dncode");
if (userName == null || password == null || dncode==null ){
parameterMap.put(ERROR, ErrorCode.LOGIN_PARAMETER_CHECK);
return setLogon(false, userName, ERROR_USERNAME_PASSWORD, "用户名或密码为空.", null, null);
}
ResultSet rs = null;
PreparedStatement stmt = null;
try {
String sql = "SELECT inr,pwd,fltcnt,sta,etyextkey,usg,pwdamedat,ukey FROM usr WHERE nam=?";
stmt = conn.prepareStatement(sql);
stmt.setString(1, userName);
rs = stmt.executeQuery();
if (!rs.next()) {
if (!guestAccountUsed){
parameterMap.put(ERROR, ErrorCode.LOGIN_NON_USR);
return setLogon(false, userName, ERROR_USERNAME_PASSWORD, "系统无此用户.", stmt, rs);
}
userName = "guest";
homePageName = "/register.zul";
homeTransaction = "usrreg";
sessionTimeout = -1;
return setLogon(true, userName, null, "游客成功登录.", stmt, rs);
}
userId = rs.getString(1);
log.debug("userId=" + userId);
String dbPassword = rs.getString(2);
int faultCount = rs.getInt(3);
String userState = rs.getString(4);// 0:正常;1:注销;2:锁定
userEty = rs.getString(5);
userRol = rs.getString(6);
pwdamedat = rs.getTimestamp(7);
ukey = rs.getString(8);
DbUtils.closeQuietly(stmt);
DbUtils.closeQuietly(rs);
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)){
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:锁定,不可登录,
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码错误
parameterMap.put(ERROR, ErrorCode.LOGIN_DN_ERROR);
return setLogon(false, userName, ErrorCode.LOGIN_DN_ERROR.getCode(), ErrorCode.LOGIN_DN_ERROR.getMessage(), stmt, rs);
} else if (Objects.nonNull(errorStr)) {
// 校验密码
sql = "UPDATE usr SET fltcnt=?,sta=?,lstfltdattim=? WHERE inr=?";
stmt = conn.prepareStatement(sql);
faultCount++;
stmt.setInt(1, faultCount);
stmt.setString(2, faultCount >= maxfltcnt ? STATUS_LOCKED : userState);
stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
stmt.setString(4, userId);
stmt.execute();
conn.commit();
if (faultCount >= maxfltcnt) {
parameterMap.put(ERROR, ErrorCode.LOGIN_PWD_CHECK);
} else {
parameterMap.put(ERROR, ErrorCode.LOGIN_PWD_ERROR);
}
return setLogon(false, userName, ERROR_USERNAME_PASSWORD, String.format("密码验证失败.%s.", errorStr), stmt,
rs);
} else if (Objects.isNull(pwdamedat)) {//初次登陆
parameterMap.put(ERROR, ErrorCode.LOGIN_FIRST_LOGIN);
return setLogon(true, userName, ErrorCode.LOGIN_FIRST_LOGIN.getCode(), ErrorCode.LOGIN_FIRST_LOGIN.getMessage(), stmt, rs);
} else if (pwdamedat.toLocalDateTime().plus(pwdAmeInterval).isBefore(LocalDateTime.now())) {//超过指定时间仍为修改密码
parameterMap.put(ERROR, ErrorCode.LOGIN_PWD_AME_INTERVAL);
return setLogon(true, userName, ErrorCode.LOGIN_PWD_AME_INTERVAL.getCode(), ErrorCode.LOGIN_PWD_AME_INTERVAL.getMessage(), stmt, rs);
}
log.debug("faultCount=" + faultCount);
sql = "UPDATE usr SET fltcnt=?,sta=?,lstdattim=? WHERE inr=?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, 0);
stmt.setString(2, STATUS_NORMAL);
stmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
stmt.setString(4, userId);
stmt.execute();
conn.commit();
// 监控用户返回监控页面
if ("monitor".equals(userName)) {
homePageName = "/monitor.zul";
homeTransaction = "monitor";
sessionTimeout = -1;
return setLogon(true, userName, null, "监控用户成功登录.", stmt, rs);
}
homePageName = defaultHomePageName;
homeTransaction = defaultHomeTransaction;
sessionTimeout = defaultSessionTimeout;
} catch (Exception e) {
log.error("系统登录内部错误", e);
parameterMap.put(ERROR, ErrorCode.SYSTEM_ERROR);
return setLogon(false, userName, ERROR_SYSTEM_FAULT, "系统内部错误.", stmt, rs);
}
return setLogon(true, userName, null, "成功登录.", stmt, rs);
}
@Override
public boolean auth(Connection conn, Map parameterMap) {
log.debug("正在加载当前用户菜单.");
String sql = "";
ResultSet rs = null;
PreparedStatement stmt = null;
ResultSet subRs = null;
PreparedStatement subStmt = null;
try {
// 进行菜单处理
Map<String, Menu> menuMap = new HashMap(); // 全部菜单
Map<String, Menu> frequentMap = new HashMap(); // 常用菜单
// 加载所有默认可访问的交易
// sql = "SELECT inr,pntinr,frm,dsp,typ,flg" + getVersion2Sql() + " FROM frm m
// WHERE typ=? OR typ=?"
sql = "select frm.inr,frm.pntinr,frm.frm,frm.dsp,frm.typ,frm.flg from frm,frr where frr.rol=? and frr.etyextkey=? and frr.frm=substr(frm.dsp,6)";
stmt = conn.prepareStatement(sql);
stmt.setString(1, userRol);
stmt.setString(2, userEty);
rs = stmt.executeQuery();
while (rs.next()) {
String id = rs.getString(INDEX_INR);
Menu menu = new Menu(id, rs.getString(INDEX_PNTINR), rs.getString(INDEX_FRM),
getVersion2String(rs, INDEX_IMG), getVersion2String(rs, INDEX_STL),
getVersion2String(rs, INDEX_CLS), rs.getString(INDEX_DSP), rs.getString(INDEX_FLG));
if (!menuMap.containsKey(id))
menuMap.put(id, menu);
if (TYPE_FREQUENT.equals(rs.getString(INDEX_TYP)))
if (!frequentMap.containsKey(id))
frequentMap.put(id, menu);
}
DbUtils.closeQuietly(stmt);
DbUtils.closeQuietly(rs);
// 进行排序
List<Menu> menus = new ArrayList(menuMap.values());
Collections.sort(menus);
List<Menu> frequents = new ArrayList(frequentMap.values());
Collections.sort(frequents);
// 通过addMenu查询并增加菜单(若未添加成功直接添加为根菜单),同时添加可访问交易
for (Menu menu : menus) {
if (!ContainerUtils.isEmpty(menu.transactionName))
this.trans.put(menu.transactionName, getI18nValue(menu.descriptionKey));
if (!FLAG_INDIRECT.equals(menu.flag) && !addMenu(this.menu, menuMap.get(menu.parentId), menu))
this.menu.add(
new MenuItem(menu.id, getI18nValue(menu.descriptionKey), menu.transactionName, menu.image));
}
// 删除菜单中为空的父项
checkMenu(this.menu);
// 添加常用菜单
MenuItem frequentItem = new MenuItem(null, getI18nValue(MENU_FREQUENT_ITEM), null, imageFrequent);
for (Menu frequent : frequents)
if (!FLAG_INDIRECT.equals(frequent.flag))
frequentItem.add(new MenuItem(frequent.id, getI18nValue(frequent.descriptionKey),
frequent.transactionName, frequent.image));
if (!frequentItem.isEmpty())
this.menu.add(frequentItem);
} catch (Exception e) {
return setAuth(false, stmt, rs, subStmt, subRs);
}
return setAuth(true, stmt, rs, subStmt, subRs);
}
public IMenuItem filterMenu(IMenuItem menuItem, String filter) {
for (IMenuItem item : menuItem) {
if (filter.equals(((MenuItem) item).id))
return item;
IMenuItem result = filterMenu(item, filter);
if (result != null)
return result;
}
return null;
}
@Override
public IMenuItem getMenu() {
if (ContainerUtils.isEmpty(menuFilter))
return menu;
return filterMenu(menu, menuFilter);
}
@Override
protected String getParameter(Map map, String key) {
if (map == null)
return null;
Object o = map.get(key);
if (o == null)
return null;
else if (o instanceof String)
return (String) o;
else if (o instanceof String[])
return ((String[]) o)[0];
else
return o.toString();
}
@Override
public Object getValue(String key) {
if ("usrinr".equals(key))
return userId;
return null;
}
@Override
public String getCustomNumber() {
return "";
}
protected void checkMenu(IMenuItem menu) {
for (int i = menu.size() - 1; i >= 0; i--) {
IMenuItem item = menu.get(i);
if (ContainerUtils.isEmpty(item.getValue())) {
if (item.isEmpty())
menu.remove(item);
else
checkMenu(item);
}
}
}
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 { // 如果为用户信息或第一条角色信息时,直接操作待删除菜单和待删除常用菜单
// 注:多角色叠加菜单时以最大可显示的方式进行处理:可见/常用直接增加,不可见或不常用待全部角色都不可见或不常用时才处理(多角色在所有角色处理结束后再处理)
// 当flag为true时表示直接处理/直接处理待删除菜单和待删除常用菜单、false时表示需多次处理/本次不可见和不常用需要对原有待删除菜单和待删除常用菜单进行比较
List<String> _removeMenuList = flag ? removeMenuList : new ArrayList();
List<String> _removeFrequentList = flag ? removeFrequentList : new ArrayList();
while (rs.next()) {
String id = rs.getString(INDEX_INR);
String parentId = rs.getString(INDEX_PNTINR);
String type = rs.getString(INDEX_TYP);
if (TYPE_FREQUENT.equals(type)) { // 常用菜单直接增加至可见和常用
Menu menu = new Menu(id, parentId, rs.getString(INDEX_FRM), getVersion2String(rs, INDEX_IMG),
getVersion2String(rs, INDEX_STL), getVersion2String(rs, INDEX_CLS), rs.getString(INDEX_DSP),
rs.getString(INDEX_FLG));
if (!menuList.containsKey(id))
menuList.put(id, menu);
if (!frequentList.containsKey(id))
frequentList.put(id, menu);
} else if (TYPE_VISIBLE.equals(type)) { // 可见菜单直接增加至可见,增加待删除常用
if (!menuList.containsKey(id)) {
Menu menu = new Menu(id, parentId, rs.getString(INDEX_FRM), getVersion2String(rs, INDEX_IMG),
getVersion2String(rs, INDEX_STL), getVersion2String(rs, INDEX_CLS), rs.getString(INDEX_DSP),
rs.getString(INDEX_FLG));
menuList.put(id, menu);
}
if (!_removeFrequentList.contains(id))
_removeFrequentList.add(id);
} else if (TYPE_INVISIBLE.equals(type)) { // 不可见菜单,增加待删除和待删除常用
if (!_removeMenuList.contains(id))
_removeMenuList.add(id);
if (!_removeFrequentList.contains(id))
_removeFrequentList.add(id);
}
}
if (!flag) { // 从第二条(含)角色信息开始
// 如果之前为待删除,但在本次不为待删除则剔除;常用菜单处理亦然
for (int i = removeMenuList.size() - 1; i >= 0; i--)
if (!_removeMenuList.contains(removeMenuList.get(i)))
removeMenuList.remove(i);
for (int i = removeFrequentList.size() - 1; i >= 0; i--)
if (!_removeFrequentList.contains(removeFrequentList.get(i)))
removeFrequentList.remove(i);
}
}
class MenuItem extends MenuItemImpl {
String id;
MenuItem() {
}
MenuItem(String id, String label, String transactionName, String image) {
super(label, transactionName, image);
if (image == null && imageNull != null)
this.image = imageNull;
this.id = id;
}
@Override
public String toString() {
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
# unit day
pwdAmeInterval=90
maxfltcnt=5
\ 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