SessionManager optimize

This commit is contained in:
MaxKey
2022-05-18 19:38:55 +08:00
parent 7354f80517
commit 25e1904c1f
17 changed files with 215 additions and 189 deletions

View File

@@ -124,7 +124,8 @@ public abstract class AbstractAuthenticationRealm {
historyLogin.setSessionId(WebContext.genId());
historyLogin.setSessionStatus(7);
Authentication authentication = (Authentication ) WebContext.getAttribute(WebConstants.AUTHENTICATION);
if(authentication.getPrincipal() instanceof SignPrincipal) {
if(authentication != null
&& authentication.getPrincipal() instanceof SignPrincipal) {
historyLogin.setSessionStatus(1);
historyLogin.setSessionId(userInfo.getSessionId());
}

View File

@@ -21,6 +21,7 @@ import org.maxkey.authn.realm.AbstractAuthenticationRealm;
import org.maxkey.authn.realm.ldap.LdapAuthenticationRealm;
import org.maxkey.authn.realm.ldap.LdapAuthenticationRealmService;
import org.maxkey.constants.ConstsLoginType;
import org.maxkey.constants.ConstsStatus;
import org.maxkey.entity.ChangePassword;
import org.maxkey.entity.PasswordPolicy;
import org.maxkey.entity.UserInfo;
@@ -100,15 +101,21 @@ public class JdbcAuthenticationRealm extends AbstractAuthenticationRealm {
if(ldapAuthenticationRealmService != null) {
//passwordMatches == false and ldapSupport ==true
//validate password with LDAP
LdapAuthenticationRealm ldapRealm = ldapAuthenticationRealmService.getByInstId(userInfo.getInstId());
if(!passwordMatches && ldapRealm != null && ldapRealm.isLdapSupport()) {
passwordMatches = ldapRealm.passwordMatches(userInfo, password);
if(passwordMatches) {
//write password to database Realm
ChangePassword changePassword = new ChangePassword(userInfo);
changePassword.setPassword(password);
userInfoService.changePassword(changePassword, false);
}
try {
LdapAuthenticationRealm ldapRealm = ldapAuthenticationRealmService.getByInstId(userInfo.getInstId());
if(!passwordMatches && ldapRealm != null
&& ldapRealm.isLdapSupport()
&& userInfo.getIsLocked() == ConstsStatus.ACTIVE) {
passwordMatches = ldapRealm.passwordMatches(userInfo, password);
if(passwordMatches) {
//write password to database Realm
ChangePassword changePassword = new ChangePassword(userInfo);
changePassword.setPassword(password);
userInfoService.changePassword(changePassword, false);
}
}
}catch(Exception e) {
_logger.debug("passwordvalid Exception : {}" , e);
}
}
_logger.debug("passwordvalid : {}" , passwordMatches);

View File

@@ -66,7 +66,11 @@ public class LdapAuthenticationRealm extends AbstractAuthenticationRealm{
username = userInfo.getWindowsAccount();
}
_logger.debug("Attempting to authenticate {} at {}", username, ldapServer);
isAuthenticated= ldapServer.authenticate(username, password);
try {
isAuthenticated = ldapServer.authenticate(username, password);
}catch(Exception e) {
_logger.debug("Attempting Authenticated fail .");
}
if (isAuthenticated ) {
return true;
}

View File

@@ -1,126 +0,0 @@
/*
* Copyright [2022] [MaxKey of copyright http://www.maxkey.top]
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.maxkey.authn.session;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import org.maxkey.entity.HistoryLogin;
import org.maxkey.entity.UserInfo;
import org.maxkey.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class AbstractSessionManager implements SessionManager{
private static Logger _logger = LoggerFactory.getLogger(AbstractSessionManager.class);
protected JdbcTemplate jdbcTemplate;
protected int validitySeconds = 60 * 30; //default 30 minutes.
private static final String DEFAULT_DEFAULT_SELECT_STATEMENT =
"select id,sessionid,userId,username,displayname,logintime from mxk_history_login where sessionstatus = 1";
private static final String LOGOUT_USERINFO_UPDATE_STATEMENT =
"update mxk_userinfo set lastlogofftime = ? , online = " + UserInfo.ONLINE.OFFLINE + " where id = ?";
private static final String HISTORY_LOGOUT_UPDATE_STATEMENT =
"update mxk_history_login set logouttime = ? ,sessionstatus = 7 where sessionid = ?";
@Override
public List<HistoryLogin> querySessions() {
List<HistoryLogin> listSessions = jdbcTemplate.query(
DEFAULT_DEFAULT_SELECT_STATEMENT,
new OnlineTicketRowMapper());
return listSessions;
}
public void profileLastLogoffTime(String userId,String lastLogoffTime) {
_logger.trace("userId {} , lastlogofftime {}" ,userId, lastLogoffTime);
jdbcTemplate.update( LOGOUT_USERINFO_UPDATE_STATEMENT,
new Object[] { lastLogoffTime, userId },
new int[] { Types.TIMESTAMP, Types.VARCHAR });
}
public void sessionLogoff(String sessionId,String lastLogoffTime) {
_logger.trace("sessionId {} , lastlogofftime {}" ,sessionId, lastLogoffTime);
jdbcTemplate.update(HISTORY_LOGOUT_UPDATE_STATEMENT,
new Object[] { lastLogoffTime, sessionId },
new int[] { Types.VARCHAR, Types.VARCHAR });
}
@Override
public void terminate(String onlineTicket,String userId,String username) {
String lastLogoffTime = DateUtils.formatDateTime(new Date());
_logger.trace("{} user {} terminate Ticket {} ." ,lastLogoffTime,username, onlineTicket);
this.profileLastLogoffTime(userId, lastLogoffTime);
this.sessionLogoff(onlineTicket, lastLogoffTime);
remove(onlineTicket);
}
private final class OnlineTicketRowMapper implements RowMapper<HistoryLogin> {
@Override
public HistoryLogin mapRow(ResultSet rs, int rowNum)
throws SQLException {
HistoryLogin history=new HistoryLogin();
history.setId(rs.getString(1));
history.setSessionId(rs.getString(2));
history.setUserId(rs.getString(3));
history.setUsername(rs.getString(4));
history.setDisplayName(rs.getString(5));
history.setLoginTime(rs.getString(6));
return history;
}
}
@Override
public void create(String sessionId, Session session) {
}
@Override
public Session remove(String sessionId) {
return null;
}
@Override
public Session get(String sessionId) {
return null;
}
@Override
public Session refresh(String sessionId, LocalTime refreshTime) {
return null;
}
@Override
public Session refresh(String sessionId) {
return null;
}
@Override
public void setValiditySeconds(int validitySeconds) {
}
}

View File

@@ -19,28 +19,30 @@ package org.maxkey.authn.session;
import java.time.Duration;
import java.time.LocalTime;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.maxkey.entity.HistoryLogin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
public class InMemorySessionManager extends AbstractSessionManager{
public class InMemorySessionManager implements SessionManager{
private static final Logger _logger = LoggerFactory.getLogger(InMemorySessionManager.class);
protected int validitySeconds = 60 * 30; //default 30 minutes.
protected static Cache<String, Session> sessionStore =
Caffeine.newBuilder()
.expireAfterWrite(10, TimeUnit.MINUTES)
.maximumSize(2000000)
.build();
public InMemorySessionManager(JdbcTemplate jdbcTemplate,int validitySeconds) {
public InMemorySessionManager(int validitySeconds) {
super();
this.jdbcTemplate = jdbcTemplate;
sessionStore =
Caffeine.newBuilder()
.expireAfterWrite(validitySeconds, TimeUnit.SECONDS)
@@ -67,16 +69,6 @@ public class InMemorySessionManager extends AbstractSessionManager{
return session;
}
@Override
public void setValiditySeconds(int validitySeconds) {
sessionStore =
Caffeine.newBuilder()
.expireAfterWrite(validitySeconds, TimeUnit.SECONDS)
.maximumSize(200000)
.build();
}
@Override
public Session refresh(String sessionId,LocalTime refreshTime) {
Session session = get(sessionId);
@@ -101,4 +93,16 @@ public class InMemorySessionManager extends AbstractSessionManager{
return session;
}
@Override
public List<HistoryLogin> querySessions() {
// TODO Auto-generated method stub
return null;
}
@Override
public void terminate(String sessionId, String userId, String username) {
// TODO Auto-generated method stub
}
}

View File

@@ -19,17 +19,20 @@ package org.maxkey.authn.session;
import java.time.Duration;
import java.time.LocalTime;
import java.util.List;
import org.maxkey.entity.HistoryLogin;
import org.maxkey.persistence.redis.RedisConnection;
import org.maxkey.persistence.redis.RedisConnectionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
public class RedisSessionManager extends AbstractSessionManager {
public class RedisSessionManager implements SessionManager {
private static final Logger _logger = LoggerFactory.getLogger(RedisSessionManager.class);
protected int validitySeconds = 60 * 30; //default 30 minutes.
RedisConnectionFactory connectionFactory;
public static String PREFIX="REDIS_SESSION_";
@@ -43,10 +46,9 @@ public class RedisSessionManager extends AbstractSessionManager {
*/
public RedisSessionManager(
RedisConnectionFactory connectionFactory,
JdbcTemplate jdbcTemplate,int validitySeconds) {
int validitySeconds) {
super();
this.connectionFactory = connectionFactory;
this.jdbcTemplate = jdbcTemplate;
this.validitySeconds = validitySeconds;
}
@@ -118,5 +120,17 @@ public class RedisSessionManager extends AbstractSessionManager {
return session;
}
@Override
public List<HistoryLogin> querySessions() {
// TODO Auto-generated method stub
return null;
}
@Override
public void terminate(String sessionId, String userId, String username) {
// TODO Auto-generated method stub
}
}

View File

@@ -33,8 +33,6 @@ public interface SessionManager {
public Session refresh(String sessionId ,LocalTime refreshTime);
public Session refresh(String sessionId);
public void setValiditySeconds(int validitySeconds);
public List<HistoryLogin> querySessions();

View File

@@ -17,33 +17,149 @@
package org.maxkey.authn.session;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.time.LocalTime;
import java.util.Date;
import java.util.List;
import org.maxkey.constants.ConstsPersistence;
import org.maxkey.entity.HistoryLogin;
import org.maxkey.entity.UserInfo;
import org.maxkey.persistence.redis.RedisConnectionFactory;
import org.maxkey.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
public class SessionManagerFactory {
public class SessionManagerFactory implements SessionManager{
private static final Logger _logger =
LoggerFactory.getLogger(SessionManagerFactory.class);
public SessionManager getManager(
int persistence,
private static final String DEFAULT_DEFAULT_SELECT_STATEMENT =
"select id,sessionid,userId,username,displayname,logintime from mxk_history_login where sessionstatus = 1";
private static final String LOGOUT_USERINFO_UPDATE_STATEMENT =
"update mxk_userinfo set lastlogofftime = ? , online = " + UserInfo.ONLINE.OFFLINE + " where id = ?";
private static final String HISTORY_LOGOUT_UPDATE_STATEMENT =
"update mxk_history_login set logouttime = ? ,sessionstatus = 7 where sessionid = ?";
private JdbcTemplate jdbcTemplate;
private InMemorySessionManager inMemorySessionManager;
private RedisSessionManager redisSessionManager;
private boolean isRedis = false;
public SessionManagerFactory(int persistence,
JdbcTemplate jdbcTemplate,
RedisConnectionFactory redisConnFactory,
int validitySeconds){
SessionManager sessionService = null;
if (persistence == ConstsPersistence.INMEMORY) {
sessionService = new InMemorySessionManager(jdbcTemplate,validitySeconds);
_logger.debug("InMemorySessionManager");
} else if (persistence == ConstsPersistence.JDBC) {
_logger.debug("JdbcSessionService not support ");
} else if (persistence == ConstsPersistence.REDIS) {
sessionService = new RedisSessionManager(
redisConnFactory,jdbcTemplate,validitySeconds);
_logger.debug("RedisSessionManager");
int validitySeconds) {
this.jdbcTemplate = jdbcTemplate;
this.inMemorySessionManager =
new InMemorySessionManager(validitySeconds);
_logger.debug("InMemorySessionManager");
if (persistence == ConstsPersistence.REDIS) {
isRedis = true;
this.redisSessionManager =
new RedisSessionManager(redisConnFactory,validitySeconds);
_logger.debug("RedisSessionManager");
}
}
public void create(String sessionId, Session session) {
inMemorySessionManager.create(sessionId, session);
if(isRedis) {
redisSessionManager.create(sessionId, session);
}
}
public Session remove(String sessionId) {
Session session = inMemorySessionManager.remove(sessionId);
if(isRedis) {
session = redisSessionManager.remove(sessionId);
}
return session;
}
public Session get(String sessionId) {
Session session = inMemorySessionManager.get(sessionId);
if(session == null && isRedis) {
session = redisSessionManager.get(sessionId);
}
return session;
}
public Session refresh(String sessionId, LocalTime refreshTime) {
Session session = null;
if(isRedis) {
session = redisSessionManager.refresh(sessionId,refreshTime);
//renew one
inMemorySessionManager.create(sessionId, session);
}else {
session = inMemorySessionManager.refresh(sessionId,refreshTime);
}
return session;
}
public Session refresh(String sessionId) {
Session session = null;
if(isRedis) {
session = redisSessionManager.refresh(sessionId);
//renew one
inMemorySessionManager.create(sessionId, session);
}else {
session = inMemorySessionManager.refresh(sessionId);
}
return sessionService;
return session;
}
public List<HistoryLogin> querySessions() {
List<HistoryLogin> listSessions = jdbcTemplate.query(
DEFAULT_DEFAULT_SELECT_STATEMENT,
new OnlineTicketRowMapper());
return listSessions;
}
private void profileLastLogoffTime(String userId,String lastLogoffTime) {
_logger.trace("userId {} , lastlogofftime {}" ,userId, lastLogoffTime);
jdbcTemplate.update( LOGOUT_USERINFO_UPDATE_STATEMENT,
new Object[] { lastLogoffTime, userId },
new int[] { Types.TIMESTAMP, Types.VARCHAR });
}
private void sessionLogoff(String sessionId,String lastLogoffTime) {
_logger.trace("sessionId {} , lastlogofftime {}" ,sessionId, lastLogoffTime);
jdbcTemplate.update(HISTORY_LOGOUT_UPDATE_STATEMENT,
new Object[] { lastLogoffTime, sessionId },
new int[] { Types.VARCHAR, Types.VARCHAR });
}
public void terminate(String sessionId, String userId, String username) {
String lastLogoffTime = DateUtils.formatDateTime(new Date());
_logger.trace("{} user {} terminate Ticket {} ." ,lastLogoffTime,username, sessionId);
this.profileLastLogoffTime(userId, lastLogoffTime);
this.sessionLogoff(sessionId, lastLogoffTime);
this.remove(sessionId);
}
private final class OnlineTicketRowMapper implements RowMapper<HistoryLogin> {
@Override
public HistoryLogin mapRow(ResultSet rs, int rowNum)
throws SQLException {
HistoryLogin history=new HistoryLogin();
history.setId(rs.getString(1));
history.setSessionId(rs.getString(2));
history.setUserId(rs.getString(3));
history.setUsername(rs.getString(4));
history.setDisplayName(rs.getString(5));
history.setLoginTime(rs.getString(6));
return history;
}
}
}

View File

@@ -204,7 +204,7 @@ public class AuthenticationAutoConfiguration implements InitializingBean {
) {
_logger.trace("session timeout " + timeout);
SessionManager sessionManager =
new SessionManagerFactory().getManager(
new SessionManagerFactory(
persistence, jdbcTemplate, redisConnFactory,timeout);
return sessionManager;
}