This commit is contained in:
shimingxy
2020-04-01 15:30:34 +08:00
parent d0d1878608
commit 65deab6676
6 changed files with 337 additions and 244 deletions

View File

@@ -2,11 +2,9 @@ package org.maxkey.authn.support.rememberme;
import java.util.Date; import java.util.Date;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.maxkey.config.ApplicationConfig; import org.maxkey.config.ApplicationConfig;
import org.maxkey.constants.LOGINTYPE; import org.maxkey.constants.LOGINTYPE;
@@ -23,7 +21,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
public abstract class AbstractRemeberMeService { public abstract class AbstractRemeberMeService {
private static final Logger _logger = LoggerFactory.getLogger(AbstractRemeberMeService.class); private static final Logger _logger = LoggerFactory.getLogger(AbstractRemeberMeService.class);
protected Integer remeberMeValidity=RemeberMe.TWO_WEEK; protected Integer remeberMeValidity = RemeberMe.TWO_WEEK;
protected String validity; protected String validity;
@@ -31,44 +29,44 @@ public abstract class AbstractRemeberMeService {
@Qualifier("applicationConfig") @Qualifier("applicationConfig")
protected ApplicationConfig applicationConfig; protected ApplicationConfig applicationConfig;
//follow function is for persist // follow function is for persist
public abstract void save(RemeberMe remeberMe) ; public abstract void save(RemeberMe remeberMe);
public abstract void update(RemeberMe remeberMe) ; public abstract void update(RemeberMe remeberMe);
public abstract RemeberMe read(RemeberMe remeberMe) ; public abstract RemeberMe read(RemeberMe remeberMe);
public abstract void remove(String username); public abstract void remove(String username);
//end persist // end persist
public boolean createRemeberMe(String username,HttpServletRequest request, HttpServletResponse response){ public boolean createRemeberMe(String username, HttpServletRequest request, HttpServletResponse response) {
if(request.getSession().getAttribute(WebConstants.REMEBER_ME_SESSION)!=null&&applicationConfig.getLoginConfig().isRemeberMe()){ if (request.getSession().getAttribute(WebConstants.REMEBER_ME_SESSION) != null
&& applicationConfig.getLoginConfig().isRemeberMe()) {
_logger.debug("Remeber Me ..."); _logger.debug("Remeber Me ...");
RemeberMe remeberMe=new RemeberMe(); RemeberMe remeberMe = new RemeberMe();
remeberMe.setAuthKey(WebContext.genId()); remeberMe.setAuthKey(WebContext.genId());
remeberMe.setId(WebContext.genId()); remeberMe.setId(WebContext.genId());
remeberMe.setUsername(WebContext.getUserInfo().getUsername()); remeberMe.setUsername(WebContext.getUserInfo().getUsername());
remeberMe.setLastLogin(new Date()); remeberMe.setLastLogin(new Date());
save(remeberMe); save(remeberMe);
_logger.debug("Remeber Me "+remeberMe); _logger.debug("Remeber Me " + remeberMe);
_logger.debug("Cookie Name : "+WebConstants.REMEBER_ME_COOKIE); _logger.debug("Cookie Name : " + WebConstants.REMEBER_ME_COOKIE);
String jsonRemeberMe = JsonUtils.object2Json(remeberMe);
_logger.debug("Remeber Me JSON " + jsonRemeberMe);
String jsonRemeberMe=JsonUtils.object2Json(remeberMe); jsonRemeberMe = ReciprocalUtils.encode(jsonRemeberMe);
_logger.debug("Remeber Me JSON "+jsonRemeberMe);
jsonRemeberMe=ReciprocalUtils.encode(jsonRemeberMe);
String cookieValue = Base64Utils.base64UrlEncode(jsonRemeberMe.getBytes()); String cookieValue = Base64Utils.base64UrlEncode(jsonRemeberMe.getBytes());
_logger.debug("Remeber Me JSON "+cookieValue); _logger.debug("Remeber Me JSON " + cookieValue);
Cookie cookie= new Cookie(WebConstants.REMEBER_ME_COOKIE,cookieValue); Cookie cookie = new Cookie(WebConstants.REMEBER_ME_COOKIE, cookieValue);
Integer maxAge=getRemeberMeValidity(); Integer maxAge = getRemeberMeValidity();
_logger.debug("Cookie Max Age :"+maxAge+" seconds."); _logger.debug("Cookie Max Age :" + maxAge + " seconds.");
cookie.setMaxAge(maxAge); cookie.setMaxAge(maxAge);
//cookie.setPath("/"); // cookie.setPath("/");
cookie.setDomain(applicationConfig.getDomainName()); cookie.setDomain(applicationConfig.getDomainName());
response.addCookie(cookie); response.addCookie(cookie);
request.getSession().removeAttribute(WebConstants.REMEBER_ME_SESSION); request.getSession().removeAttribute(WebConstants.REMEBER_ME_SESSION);
@@ -76,63 +74,60 @@ public abstract class AbstractRemeberMeService {
return true; return true;
} }
public boolean login(String remeberMe, HttpServletResponse response) {
_logger.debug("RemeberMe : " + remeberMe);
public boolean login(String remeberMe, HttpServletResponse response){ remeberMe = new String(Base64Utils.base64UrlDecode(remeberMe));
_logger.debug("RemeberMe : "+remeberMe);
remeberMe=new String(Base64Utils.base64UrlDecode(remeberMe)); remeberMe = ReciprocalUtils.decoder(remeberMe);
remeberMe=ReciprocalUtils.decoder(remeberMe); _logger.debug("decoder RemeberMe : " + remeberMe);
RemeberMe remeberMeCookie = new RemeberMe();
remeberMeCookie = (RemeberMe) JsonUtils.json2Object(remeberMe, remeberMeCookie);
_logger.debug("Remeber Me Cookie : " + remeberMeCookie);
_logger.debug("decoder RemeberMe : "+remeberMe); RemeberMe jdbcRemeberMe = read(remeberMeCookie);
RemeberMe remeberMeCookie=new RemeberMe(); DateTime loginDate = new DateTime(jdbcRemeberMe.getLastLogin());
remeberMeCookie=(RemeberMe)JsonUtils.json2Object(remeberMe, remeberMeCookie);
_logger.debug("Remeber Me Cookie : "+remeberMeCookie);
RemeberMe jdbcRemeberMe=read(remeberMeCookie);
DateTime loginDate=new DateTime(jdbcRemeberMe.getLastLogin());
DateTime expiryDate = loginDate.plusSeconds(getRemeberMeValidity()); DateTime expiryDate = loginDate.plusSeconds(getRemeberMeValidity());
DateTime now = new DateTime(); DateTime now = new DateTime();
if(now.isBefore(expiryDate)){ if (now.isBefore(expiryDate)) {
if(WebContext.setAuthentication(jdbcRemeberMe.getUsername(),LOGINTYPE.REMEBER_ME,"","","success")){ if (WebContext.setAuthentication(jdbcRemeberMe.getUsername(), LOGINTYPE.REMEBER_ME, "", "", "success")) {
return updateRemeberMe(remeberMeCookie,response); return updateRemeberMe(remeberMeCookie, response);
} }
} }
return false; return false;
} }
public boolean updateRemeberMe(RemeberMe remeberMe, HttpServletResponse response) {
public boolean updateRemeberMe(RemeberMe remeberMe,HttpServletResponse response){
remeberMe.setAuthKey(WebContext.genId()); remeberMe.setAuthKey(WebContext.genId());
remeberMe.setLastLogin(new Date()); remeberMe.setLastLogin(new Date());
update(remeberMe); update(remeberMe);
_logger.debug("update Remeber Me "+remeberMe); _logger.debug("update Remeber Me " + remeberMe);
_logger.debug("Cookie Name : "+WebConstants.REMEBER_ME_COOKIE); _logger.debug("Cookie Name : " + WebConstants.REMEBER_ME_COOKIE);
String jsonRemeberMe = JsonUtils.object2Json(remeberMe);
String jsonRemeberMe=JsonUtils.object2Json(remeberMe); _logger.debug("Remeber Me JSON " + jsonRemeberMe);
_logger.debug("Remeber Me JSON "+jsonRemeberMe);
_logger.debug("Encode Remeber Me JSON ..."); _logger.debug("Encode Remeber Me JSON ...");
jsonRemeberMe=ReciprocalUtils.encode(jsonRemeberMe); jsonRemeberMe = ReciprocalUtils.encode(jsonRemeberMe);
_logger.debug("Encode Remeber Me JSON "+ jsonRemeberMe); _logger.debug("Encode Remeber Me JSON " + jsonRemeberMe);
String cookieValue = Base64Utils.base64UrlEncode(jsonRemeberMe.getBytes()); String cookieValue = Base64Utils.base64UrlEncode(jsonRemeberMe.getBytes());
Cookie cookie= new Cookie(WebConstants.REMEBER_ME_COOKIE,cookieValue); Cookie cookie = new Cookie(WebConstants.REMEBER_ME_COOKIE, cookieValue);
Integer maxAge=getRemeberMeValidity(); Integer maxAge = getRemeberMeValidity();
_logger.debug("Cookie Max Age :"+maxAge+" seconds."); _logger.debug("Cookie Max Age :" + maxAge + " seconds.");
cookie.setMaxAge(maxAge); cookie.setMaxAge(maxAge);
//cookie.setPath("/"); // cookie.setPath("/");
cookie.setDomain(applicationConfig.getDomainName()); cookie.setDomain(applicationConfig.getDomainName());
response.addCookie(cookie); response.addCookie(cookie);
return true; return true;
} }
public boolean removeRemeberMe(HttpServletResponse response){ public boolean removeRemeberMe(HttpServletResponse response) {
Cookie cookie= new Cookie(WebConstants.REMEBER_ME_COOKIE,null); Cookie cookie = new Cookie(WebConstants.REMEBER_ME_COOKIE, null);
cookie.setMaxAge(0); cookie.setMaxAge(0);
cookie.setDomain(applicationConfig.getDomainName()); cookie.setDomain(applicationConfig.getDomainName());
@@ -160,20 +155,20 @@ public abstract class AbstractRemeberMeService {
} }
public void setValidity(String validity) { public void setValidity(String validity) {
_logger.debug("validity : "+validity); _logger.debug("validity : " + validity);
this.validity = validity; this.validity = validity;
if(Pattern.matches("[0-9]+", validity)){ if (Pattern.matches("[0-9]+", validity)) {
remeberMeValidity=Integer.parseInt(validity); remeberMeValidity = Integer.parseInt(validity);
}else if(validity.equalsIgnoreCase("ONE_DAY")){ } else if (validity.equalsIgnoreCase("ONE_DAY")) {
remeberMeValidity=RemeberMe.ONE_DAY; remeberMeValidity = RemeberMe.ONE_DAY;
}else if(validity.equalsIgnoreCase("ONE_WEEK")){ } else if (validity.equalsIgnoreCase("ONE_WEEK")) {
remeberMeValidity=RemeberMe.ONE_WEEK; remeberMeValidity = RemeberMe.ONE_WEEK;
}else if(validity.equalsIgnoreCase("TWO_WEEK")){ } else if (validity.equalsIgnoreCase("TWO_WEEK")) {
remeberMeValidity=RemeberMe.TWO_WEEK; remeberMeValidity = RemeberMe.TWO_WEEK;
}else if(validity.equalsIgnoreCase("ONE_YEAR")){ } else if (validity.equalsIgnoreCase("ONE_YEAR")) {
remeberMeValidity=RemeberMe.ONE_YEAR; remeberMeValidity = RemeberMe.ONE_YEAR;
} }
_logger.debug("Remeber Me Validity : "+remeberMeValidity); _logger.debug("Remeber Me Validity : " + remeberMeValidity);
} }
} }

View File

@@ -0,0 +1,39 @@
package org.maxkey.authn.support.rememberme;
import java.time.Duration;
import org.ehcache.UserManagedCache;
import org.ehcache.config.builders.ExpiryPolicyBuilder;
import org.ehcache.config.builders.UserManagedCacheBuilder;
public class InMemoryRemeberMeService extends AbstractRemeberMeService {
protected static final UserManagedCache<String, RemeberMe> remeberMeStore =
UserManagedCacheBuilder.newUserManagedCacheBuilder(String.class, RemeberMe.class)
.withExpiry(
ExpiryPolicyBuilder.timeToLiveExpiration(
Duration.ofMinutes(RemeberMe.TWO_WEEK)
)
)
.build(true);
@Override
public void save(RemeberMe remeberMe) {
remeberMeStore.put(remeberMe.getUsername(), remeberMe);
}
@Override
public void update(RemeberMe remeberMe) {
remeberMeStore.put(remeberMe.getUsername(), remeberMe);
}
@Override
public RemeberMe read(RemeberMe remeberMe) {
return remeberMeStore.get(remeberMe.getUsername());
}
@Override
public void remove(String username) {
remeberMeStore.remove(username);
}
}

View File

@@ -4,28 +4,29 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
import java.util.List; import java.util.List;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.RowMapper;
public class JdbcRemeberMeService extends AbstractRemeberMeService {
public class JdbcRemeberMeService extends AbstractRemeberMeService{
private static final Logger _logger = LoggerFactory.getLogger(JdbcRemeberMeService.class); private static final Logger _logger = LoggerFactory.getLogger(JdbcRemeberMeService.class);
private static final String DEFAULT_DEFAULT_INSERT_STATEMENT = "INSERT INTO REMEMBER_ME(ID, USERNAME,AUTHKEY,LASTLOGIN)VALUES( ? , ? , ? , ?)"; private static final String DEFAULT_DEFAULT_INSERT_STATEMENT =
"INSERT INTO REMEMBER_ME(ID, USERNAME,AUTHKEY,LASTLOGIN)VALUES( ? , ? , ? , ?)";
private static final String DEFAULT_DEFAULT_SELECT_STATEMENT = "SELECT ID, USERNAME,AUTHKEY,LASTLOGIN FROM REMEMBER_ME WHERE ID = ? AND USERNAME = ? AND AUTHKEY = ?"; private static final String DEFAULT_DEFAULT_SELECT_STATEMENT =
"SELECT ID, USERNAME,AUTHKEY,LASTLOGIN FROM REMEMBER_ME "
+ " WHERE ID = ? AND USERNAME = ? AND AUTHKEY = ?";
private static final String DEFAULT_DEFAULT_DELETE_STATEMENT = "DELETE FROM REMEMBER_ME WHERE USERNAME = ?"; private static final String DEFAULT_DEFAULT_DELETE_STATEMENT =
"DELETE FROM REMEMBER_ME WHERE USERNAME = ?";
private static final String DEFAULT_DEFAULT_UPDATE_STATEMENT= "UPDATE REMEMBER_ME SET AUTHKEY = ? , LASTLOGIN = ? WHERE ID = ?"; private static final String DEFAULT_DEFAULT_UPDATE_STATEMENT =
"UPDATE REMEMBER_ME SET AUTHKEY = ? , LASTLOGIN = ? WHERE ID = ?";
private final JdbcTemplate jdbcTemplate; private final JdbcTemplate jdbcTemplate;
public JdbcRemeberMeService(JdbcTemplate jdbcTemplate) { public JdbcRemeberMeService(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate; this.jdbcTemplate = jdbcTemplate;
} }
@@ -33,31 +34,36 @@ public class JdbcRemeberMeService extends AbstractRemeberMeService{
@Override @Override
public void save(RemeberMe remeberMe) { public void save(RemeberMe remeberMe) {
jdbcTemplate.update(DEFAULT_DEFAULT_INSERT_STATEMENT, jdbcTemplate.update(DEFAULT_DEFAULT_INSERT_STATEMENT,
new Object[] { remeberMe.getId(),remeberMe.getUsername(),remeberMe.getAuthKey(),remeberMe.getLastLogin() }, new Object[] { remeberMe.getId(), remeberMe.getUsername(), remeberMe.getAuthKey(),
new int[] {Types.VARCHAR, Types.VARCHAR,Types.VARCHAR,Types.TIMESTAMP }); remeberMe.getLastLogin() },
new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.TIMESTAMP });
} }
@Override @Override
public void update(RemeberMe remeberMe) { public void update(RemeberMe remeberMe) {
jdbcTemplate.update(DEFAULT_DEFAULT_UPDATE_STATEMENT, new Object[] {remeberMe.getAuthKey(),remeberMe.getLastLogin(),remeberMe.getId()}); jdbcTemplate.update(DEFAULT_DEFAULT_UPDATE_STATEMENT,
new Object[] {
remeberMe.getAuthKey(),
remeberMe.getLastLogin(),
remeberMe.getId()
});
} }
@Override @Override
public RemeberMe read(RemeberMe remeberMe) { public RemeberMe read(RemeberMe remeberMe) {
List<RemeberMe> listRemeberMe=jdbcTemplate.query(DEFAULT_DEFAULT_SELECT_STATEMENT, new RowMapper<RemeberMe>() { List<RemeberMe> listRemeberMe = jdbcTemplate.query(DEFAULT_DEFAULT_SELECT_STATEMENT,
new RowMapper<RemeberMe>() {
public RemeberMe mapRow(ResultSet rs, int rowNum) throws SQLException { public RemeberMe mapRow(ResultSet rs, int rowNum) throws SQLException {
RemeberMe remeberMe=new RemeberMe(); RemeberMe remeberMe = new RemeberMe();
remeberMe.setId(rs.getString(1)); remeberMe.setId(rs.getString(1));
remeberMe.setUsername(rs.getString(2)); remeberMe.setUsername(rs.getString(2));
remeberMe.setAuthKey(rs.getString(3)); remeberMe.setAuthKey(rs.getString(3));
remeberMe.setLastLogin(rs.getDate(4)); remeberMe.setLastLogin(rs.getDate(4));
return remeberMe; return remeberMe;
} }
},remeberMe.getId(),remeberMe.getUsername(),remeberMe.getAuthKey()); }, remeberMe.getId(), remeberMe.getUsername(), remeberMe.getAuthKey());
_logger.debug("listRemeberMe "+listRemeberMe); _logger.debug("listRemeberMe " + listRemeberMe);
return (listRemeberMe.size()>0)?listRemeberMe.get(0):null; return (listRemeberMe.size() > 0) ? listRemeberMe.get(0) : null;
} }
@Override @Override

View File

@@ -0,0 +1,43 @@
package org.maxkey.authn.support.rememberme;
import org.maxkey.persistence.redis.RedisConnection;
import org.maxkey.persistence.redis.RedisConnectionFactory;
public class RedisRemeberMeService extends AbstractRemeberMeService {
protected int serviceTicketValiditySeconds = RemeberMe.TWO_WEEK;
RedisConnectionFactory connectionFactory;
public static String PREFIX = "REDIS_REMEBER_ME_SERVICE_";
@Override
public void save(RemeberMe remeberMe) {
RedisConnection conn = connectionFactory.getConnection();
conn.setexObject(PREFIX + remeberMe.getUsername(), serviceTicketValiditySeconds, remeberMe);
conn.close();
}
@Override
public void update(RemeberMe remeberMe) {
RedisConnection conn = connectionFactory.getConnection();
conn.setexObject(PREFIX + remeberMe.getUsername(), serviceTicketValiditySeconds, remeberMe);
conn.close();
}
@Override
public RemeberMe read(RemeberMe remeberMe) {
RedisConnection conn = connectionFactory.getConnection();
RemeberMe readRemeberMe = (RemeberMe)conn.getObject(PREFIX + remeberMe.getUsername());
conn.close();
return readRemeberMe;
}
@Override
public void remove(String username) {
RedisConnection conn = connectionFactory.getConnection();
conn.delete(PREFIX + username);
conn.close();
}
}

View File

@@ -1,20 +1,24 @@
package org.maxkey.authn.support.rememberme; package org.maxkey.authn.support.rememberme;
import java.io.Serializable;
import java.util.Date; import java.util.Date;
public class RemeberMe { public class RemeberMe implements Serializable {
private static final long serialVersionUID = 8010496585233991785L;
/** /**
* The number of seconds in one year (= 60 * 60 * 24 * 365). * The number of seconds in one year (= 60 * 60 * 24 * 365).
*/ */
public static final Integer ONE_YEAR = 60 * 60 * 24 * 365; public static final Integer ONE_YEAR = 60 * 60 * 24 * 365;
public static final Integer ONE_DAY = 60 * 60 * 24; //1 day public static final Integer ONE_DAY = 60 * 60 * 24; // 1 day
public static final Integer ONE_WEEK = ONE_DAY * 7; //1 week public static final Integer ONE_WEEK = ONE_DAY * 7; // 1 week
public static final Integer TWO_WEEK = ONE_DAY * 14; //2 week public static final Integer TWO_WEEK = ONE_DAY * 14; // 2 week
public static final Integer TWO_MONTH = ONE_DAY * 30; //1 month public static final Integer TWO_MONTH = ONE_DAY * 30; // 1 month
String id; String id;
@@ -58,7 +62,9 @@ public class RemeberMe {
@Override @Override
public String toString() { public String toString() {
return "RemeberMe [id=" + id + ", username=" + username + ", authKey=" return "RemeberMe [id=" + id
+ authKey + ", lastLogin=" + lastLogin + "]"; + ", username=" + username
+ ", authKey=" + authKey + ", lastLogin=" + lastLogin
+ "]";
} }
} }

View File

@@ -72,10 +72,14 @@
<ref bean="localeChangeInterceptor" /> <ref bean="localeChangeInterceptor" />
</mvc:interceptors> </mvc:interceptors>
<!--
<bean id="remeberMeService" class="org.maxkey.authn.support.rememberme.JdbcRemeberMeService"> <bean id="remeberMeService" class="org.maxkey.authn.support.rememberme.JdbcRemeberMeService">
<constructor-arg ref="jdbcTemplate"/> <constructor-arg ref="jdbcTemplate"/>
<property name="validity" value="${config.login.remeberme.validity}"/> <property name="validity" value="${config.login.remeberme.validity}"/>
</bean>
-->
<bean id="remeberMeService" class="org.maxkey.authn.support.rememberme.InMemoryRemeberMeService">
</bean> </bean>
<bean id="keyUriFormat" class="org.maxkey.crypto.password.opt.algorithm.KeyUriFormat"> <bean id="keyUriFormat" class="org.maxkey.crypto.password.opt.algorithm.KeyUriFormat">