diff --git a/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/AbstractOptAuthn.java b/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/AbstractOptAuthn.java index fb6a7e4f..4e72fd34 100644 --- a/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/AbstractOptAuthn.java +++ b/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/AbstractOptAuthn.java @@ -142,5 +142,12 @@ public abstract class AbstractOptAuthn { this.optType = optType; } + public void setOptTokenStore(AbstractOptTokenStore optTokenStore) { + this.optTokenStore = optTokenStore; + } + + public void initPropertys() { + + } } diff --git a/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/JdbcOptTokenStore.java b/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/JdbcOptTokenStore.java deleted file mode 100644 index 74e582f4..00000000 --- a/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/JdbcOptTokenStore.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright [2020] [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.crypto.password.opt.token; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Types; -import java.util.Date; -import org.joda.time.DateTime; -import org.joda.time.Duration; -import org.joda.time.format.DateTimeFormat; -import org.maxkey.constants.ConstantsStatus; -import org.maxkey.crypto.password.opt.OneTimePassword; -import org.maxkey.domain.UserInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.jdbc.core.JdbcTemplate; -import org.springframework.jdbc.core.RowMapper; - -public class JdbcOptTokenStore extends AbstractOptTokenStore { - private static final Logger logger = LoggerFactory.getLogger(JdbcOptTokenStore.class); - - private static final String DEFAULT_DEFAULT_INSERT_STATEMENT = - "INSERT INTO ONE_TIME_PASSWORD(ID ,OPTTYPE,USERNAME,TOKEN,RECEIVER,CREATETIME,STATUS)" - + " VALUES(?,?,?,?,?,?," + ConstantsStatus.ACTIVE + ")"; - - private static final String DEFAULT_DEFAULT_SELECT_STATEMENT = - "SELECT ID ,OPTTYPE,USERNAME,TOKEN,RECEIVER,CREATETIME FROM ONE_TIME_PASSWORD" - + " WHERE STATUS =" + ConstantsStatus.ACTIVE - + " AND USERNAME = ? AND TOKEN = ? AND OPTTYPE = ?"; - - private static final String DEFAULT_DEFAULT_DELETE_STATEMENT = - "UPDATE ONE_TIME_PASSWORD SET STATUS =" - + ConstantsStatus.DELETE + " WHERE USERNAME = ? AND TOKEN = ? AND OPTTYPE = ?"; - - private final JdbcTemplate jdbcTemplate; - - public JdbcOptTokenStore(JdbcTemplate jdbcTemplate) { - this.jdbcTemplate = jdbcTemplate; - } - - - /** - *store. - */ - public void store(UserInfo userInfo, String token, String receiver, String type) { - jdbcTemplate.update(DEFAULT_DEFAULT_INSERT_STATEMENT, - new Object[] { - java.util.UUID.randomUUID(), - type, - userInfo.getUsername(), - token, - receiver, - new Date() - }, - new int[] { Types.VARCHAR, Types.VARCHAR, - Types.VARCHAR, Types.VARCHAR, - Types.VARCHAR,Types.TIMESTAMP - } - ); - } - - /** - * validate. - * @param userInfo UserInfo - * @param token String - * @param type int - * @return - */ - public boolean validate(UserInfo userInfo, String token, String type,int interval) { - OneTimePassword oneTimePassword = jdbcTemplate.queryForObject( - DEFAULT_DEFAULT_SELECT_STATEMENT, - new OneTimePasswordRowMapper(), userInfo.getUsername(), token, type); - - if (oneTimePassword != null) { - - jdbcTemplate.update( - DEFAULT_DEFAULT_DELETE_STATEMENT, - new Object[] { userInfo.getUsername(), token, type }, - new int[] { Types.VARCHAR, Types.VARCHAR, Types.INTEGER } - ); - DateTime currentdateTime = new DateTime(); - DateTime oneTimePwdData = DateTime.parse(oneTimePassword.getCreateTime(), - DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")); - Duration duration = new Duration(oneTimePwdData, currentdateTime); - int intDuration = Integer.parseInt(duration.getStandardSeconds() + ""); - logger.debug("validate duration " + intDuration); - logger.debug("validate result " + (intDuration <= interval)); - if (intDuration <= interval) { - return true; - } - } - return false; - - } - - public class OneTimePasswordRowMapper implements RowMapper { - - /** - *ResultSet. - */ - public OneTimePassword mapRow(ResultSet rs, int rowNum) throws SQLException { - OneTimePassword oneTimePassword = new OneTimePassword(); - oneTimePassword.setId(rs.getString("ID")); - oneTimePassword.setType(rs.getString("OPTTYPE")); - oneTimePassword.setUsername(rs.getString("USERNAME")); - oneTimePassword.setToken(rs.getString("TOKEN")); - oneTimePassword.setUsername(rs.getString("USERNAME")); - oneTimePassword.setReceiver(rs.getString("RECEIVER")); - oneTimePassword.setCreateTime(rs.getString("CREATETIME")); - return oneTimePassword; - } - } - -} diff --git a/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/RedisOptTokenStore.java b/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/RedisOptTokenStore.java index 03021140..24b35db4 100644 --- a/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/RedisOptTokenStore.java +++ b/maxkey-core/src/main/java/org/maxkey/crypto/password/opt/token/RedisOptTokenStore.java @@ -30,6 +30,11 @@ public class RedisOptTokenStore extends AbstractOptTokenStore { RedisConnectionFactory connectionFactory; + public RedisOptTokenStore(RedisConnectionFactory connectionFactory) { + super(); + this.connectionFactory = connectionFactory; + } + public static String PREFIX = "REDIS_OTP_SERVICE_"; @Override diff --git a/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyConfig.java b/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyConfig.java index be5768e4..43ce8a39 100644 --- a/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyConfig.java +++ b/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyConfig.java @@ -27,6 +27,7 @@ import org.maxkey.authn.realm.activedirectory.ActiveDirectoryAuthenticationRealm import org.maxkey.authn.realm.activedirectory.ActiveDirectoryServer; import org.maxkey.authn.support.kerberos.KerberosProxy; import org.maxkey.authn.support.kerberos.RemoteKerberosService; +import org.maxkey.constants.ConstantsPersistence; import org.maxkey.constants.ConstantsProperties; import org.maxkey.crypto.password.opt.AbstractOptAuthn; import org.maxkey.crypto.password.opt.algorithm.KeyUriFormat; @@ -36,14 +37,15 @@ import org.maxkey.crypto.password.opt.impl.TimeBasedOtpAuthn; import org.maxkey.crypto.password.opt.impl.sms.SmsOtpAuthnAliyun; import org.maxkey.crypto.password.opt.impl.sms.SmsOtpAuthnTencentCloud; import org.maxkey.crypto.password.opt.impl.sms.SmsOtpAuthnYunxin; +import org.maxkey.crypto.password.opt.token.RedisOptTokenStore; import org.maxkey.persistence.ldap.ActiveDirectoryUtils; import org.maxkey.persistence.ldap.LdapUtils; +import org.maxkey.persistence.redis.RedisConnectionFactory; import org.mybatis.spring.annotation.MapperScan; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @@ -51,8 +53,6 @@ import org.springframework.context.annotation.PropertySource; import org.springframework.jdbc.core.JdbcTemplate; - - @Configuration //@ImportResource(locations = { "classpath:spring/maxkey.xml" }) @PropertySource(ConstantsProperties.applicationPropertySource) @@ -160,31 +160,35 @@ public class MaxKeyConfig implements InitializingBean { @Bean(name = "tfaOptAuthn") public AbstractOptAuthn tfaOptAuthn( @Value("${config.login.mfa.type}")String mfaType, - MailOtpAuthn tfaMailOptAuthn) { + @Value("${config.server.persistence}") int persistence, + MailOtpAuthn tfaMailOptAuthn, + RedisConnectionFactory redisConnFactory) { + AbstractOptAuthn tfaOptAuthn = null; if(mfaType.equalsIgnoreCase("SmsOtpAuthnAliyun")) { - SmsOtpAuthnAliyun tfaOptAuthn = new SmsOtpAuthnAliyun(); - tfaOptAuthn.initPropertys(); + tfaOptAuthn = new SmsOtpAuthnAliyun(); _logger.debug("SmsOtpAuthnAliyun inited."); - return tfaOptAuthn; }else if(mfaType.equalsIgnoreCase("SmsOtpAuthnTencentCloud")) { - SmsOtpAuthnTencentCloud tfaOptAuthn = new SmsOtpAuthnTencentCloud(); - tfaOptAuthn.initPropertys(); + tfaOptAuthn = new SmsOtpAuthnTencentCloud(); _logger.debug("SmsOtpAuthnTencentCloud inited."); - return tfaOptAuthn; }else if(mfaType.equalsIgnoreCase("SmsOtpAuthnYunxin")) { - SmsOtpAuthnYunxin tfaOptAuthn = new SmsOtpAuthnYunxin(); - tfaOptAuthn.initPropertys(); + tfaOptAuthn = new SmsOtpAuthnYunxin(); _logger.debug("SmsOtpAuthnYunxin inited."); - return tfaOptAuthn; }else if(mfaType.equalsIgnoreCase("MailOtpAuthn")) { + tfaOptAuthn = tfaMailOptAuthn; _logger.debug("MailOtpAuthn inited."); - return tfaMailOptAuthn; }else { - TimeBasedOtpAuthn tfaOptAuthn = new TimeBasedOtpAuthn(); + tfaOptAuthn = new TimeBasedOtpAuthn(); _logger.debug("TimeBasedOtpAuthn inited."); - return tfaOptAuthn; } + + if (persistence == ConstantsPersistence.REDIS) { + RedisOptTokenStore redisOptTokenStore = new RedisOptTokenStore(redisConnFactory); + tfaOptAuthn.setOptTokenStore(redisOptTokenStore); + } + + tfaOptAuthn.initPropertys(); + return tfaOptAuthn; } @Bean(name = "tfaMailOptAuthn") @@ -202,9 +206,11 @@ public class MaxKeyConfig implements InitializingBean { } @Bean(name = "tfaMobileOptAuthn") - public SmsOtpAuthn smsOtpAuthn(@Value("${config.otp.sms}")String optSmsProvider) { + public SmsOtpAuthn smsOtpAuthn( + @Value("${config.otp.sms}")String optSmsProvider, + @Value("${config.server.persistence}") int persistence, + RedisConnectionFactory redisConnFactory) { SmsOtpAuthn smsOtpAuthn = null; - if(optSmsProvider.equalsIgnoreCase("SmsOtpAuthnAliyun")) { smsOtpAuthn = new SmsOtpAuthnAliyun(); }else if(optSmsProvider.equalsIgnoreCase("SmsOtpAuthnTencentCloud")) { @@ -212,6 +218,10 @@ public class MaxKeyConfig implements InitializingBean { }else { smsOtpAuthn = new SmsOtpAuthnYunxin(); } + if (persistence == ConstantsPersistence.REDIS) { + RedisOptTokenStore redisOptTokenStore = new RedisOptTokenStore(redisConnFactory); + smsOtpAuthn.setOptTokenStore(redisOptTokenStore); + } smsOtpAuthn.initPropertys(); _logger.debug("SmsOtpAuthn inited.");