From cecc22edfcce0ba27dd7773360d3212900088980 Mon Sep 17 00:00:00 2001 From: MaxKey Date: Sun, 8 Aug 2021 15:15:39 +0800 Subject: [PATCH] v2.9.0 --- ReleaseNotes.txt | 4 +- build.gradle | 1 + .../org/maxkey/entity/ChangePassword.java | 44 +++++++ .../org/maxkey/entity/HistoryConnector.java | 75 ++++++----- .../ldap/ActiveDirectoryUtils.java | 69 +++++----- .../maxkey/persistence/ldap/LdapUtils.java | 65 ++++++---- .../maxkey/synchronizer/SynchronizerJob.java | 11 +- .../SynchronizerAutoConfiguration.java | 118 ++++++++++++++++++ .../xml/mysql/HistoryLoginAppsMapper.xml | 2 +- .../mapper/xml/mysql/ReportMapper.xml | 5 +- .../mapper/xml/mysql/UserInfoMapper.xml | 8 +- .../main/resources/META-INF/spring.factories | 1 + .../resources/messages/message.properties | 4 +- .../resources/messages/message_en.properties | 4 +- .../messages/message_zh_CN.properties | 4 +- 15 files changed, 310 insertions(+), 105 deletions(-) create mode 100644 maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/autoconfigure/SynchronizerAutoConfiguration.java diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt index 4102f828..6fe17331 100644 --- a/ReleaseNotes.txt +++ b/ReleaseNotes.txt @@ -28,7 +28,9 @@ *(MAXKEY-210627) 找回密码时密码不匹配问题修复 *(MAXKEY-210628) SHELL脚本优化 *(MAXKEY-210629) 官方网站优化 - *(MAXKEY-210630) 依赖jar引用、更新和升级 + *(MAXKEY-210630) 标准构建优化 + *(MAXKEY-210631) maxkey-web-mgt配置文件分离,方便后续不同环境的切换 + *(MAXKEY-210632) 依赖jar引用、更新和升级 spring 5.3.9 springBoot 2.5.3 springSession 2.5.1 diff --git a/build.gradle b/build.gradle index 857610f3..430ed01a 100644 --- a/build.gradle +++ b/build.gradle @@ -459,6 +459,7 @@ task copyMaxKeyLibs(type: Copy) { from "$rootDir/build/maxkey-jars/maxkey-protocol-oauth-2.0-${project.version}.jar" from "$rootDir/build/maxkey-jars/maxkey-protocol-saml-2.0-${project.version}.jar" from "$rootDir/build/maxkey-jars/maxkey-protocol-tokenbased-${project.version}.jar" + from "$rootDir/build/maxkey-jars/maxkey-web-resources-${project.version}.jar" into "$rootDir/build/MaxKey-v${project.version}GA/lib"; } diff --git a/maxkey-core/src/main/java/org/maxkey/entity/ChangePassword.java b/maxkey-core/src/main/java/org/maxkey/entity/ChangePassword.java index faf49abc..991130f0 100644 --- a/maxkey-core/src/main/java/org/maxkey/entity/ChangePassword.java +++ b/maxkey-core/src/main/java/org/maxkey/entity/ChangePassword.java @@ -29,6 +29,10 @@ public class ChangePassword extends JpaBaseEntity{ private String id; private String uid; private String username; + private String email; + private String mobile; + private String windowsAccount; + private String employeeNumber; private String displayName; private String oldPassword; private String password; @@ -155,6 +159,16 @@ public class ChangePassword extends JpaBaseEntity{ } + public String getMobile() { + return mobile; + } + + + public void setMobile(String mobile) { + this.mobile = mobile; + } + + public String getDisplayName() { return displayName; } @@ -165,6 +179,36 @@ public class ChangePassword extends JpaBaseEntity{ } + public String getEmail() { + return email; + } + + + public void setEmail(String email) { + this.email = email; + } + + + public String getWindowsAccount() { + return windowsAccount; + } + + + public void setWindowsAccount(String windowsAccount) { + this.windowsAccount = windowsAccount; + } + + + public String getEmployeeNumber() { + return employeeNumber; + } + + + public void setEmployeeNumber(String employeeNumber) { + this.employeeNumber = employeeNumber; + } + + @Override public String toString() { StringBuilder builder = new StringBuilder(); diff --git a/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java b/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java index 548bb372..32ab4492 100644 --- a/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java +++ b/maxkey-core/src/main/java/org/maxkey/entity/HistoryConnector.java @@ -32,6 +32,9 @@ public class HistoryConnector extends JpaBaseEntity implements Serializable{ @Column String conType; + @Column + String conAction; + @Column String sourceId; @@ -178,36 +181,48 @@ public class HistoryConnector extends JpaBaseEntity implements Serializable{ } - @Override - public String toString() { - StringBuilder builder = new StringBuilder(); - builder.append("HistoryConnector [id="); - builder.append(id); - builder.append(", conName="); - builder.append(conName); - builder.append(", conType="); - builder.append(conType); - builder.append(", sourceId="); - builder.append(sourceId); - builder.append(", sourceName="); - builder.append(sourceName); - builder.append(", objectId="); - builder.append(objectId); - builder.append(", objectName="); - builder.append(objectName); - builder.append(", description="); - builder.append(description); - builder.append(", syncTime="); - builder.append(syncTime); - builder.append(", result="); - builder.append(result); - builder.append(", startDate="); - builder.append(startDate); - builder.append(", endDate="); - builder.append(endDate); - builder.append("]"); - return builder.toString(); - } + public String getConAction() { + return conAction; + } + + + public void setConAction(String conAction) { + this.conAction = conAction; + } + + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("HistoryConnector [id="); + builder.append(id); + builder.append(", conName="); + builder.append(conName); + builder.append(", conType="); + builder.append(conType); + builder.append(", conAction="); + builder.append(conAction); + builder.append(", sourceId="); + builder.append(sourceId); + builder.append(", sourceName="); + builder.append(sourceName); + builder.append(", objectId="); + builder.append(objectId); + builder.append(", objectName="); + builder.append(objectName); + builder.append(", description="); + builder.append(description); + builder.append(", syncTime="); + builder.append(syncTime); + builder.append(", result="); + builder.append(result); + builder.append(", startDate="); + builder.append(startDate); + builder.append(", endDate="); + builder.append(endDate); + builder.append("]"); + return builder.toString(); + } } diff --git a/maxkey-core/src/main/java/org/maxkey/persistence/ldap/ActiveDirectoryUtils.java b/maxkey-core/src/main/java/org/maxkey/persistence/ldap/ActiveDirectoryUtils.java index ed0cf3a7..073079b6 100644 --- a/maxkey-core/src/main/java/org/maxkey/persistence/ldap/ActiveDirectoryUtils.java +++ b/maxkey-core/src/main/java/org/maxkey/persistence/ldap/ActiveDirectoryUtils.java @@ -65,42 +65,41 @@ public class ActiveDirectoryUtils extends LdapUtils { this.ctx = dirContext; } - // connect to ActiveDirectory server @Override - public DirContext openConnection() { - _logger.info("PROVIDER_URL:" + providerUrl); - _logger.info("SECURITY_PRINCIPAL:" + principal); - _logger.info("SECURITY_CREDENTIALS:" + credentials); - // LDAP - Properties props = new Properties(); - props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - props.setProperty(Context.URL_PKG_PREFIXES, "com.sun.jndi.url"); - props.setProperty(Context.REFERRAL, referral); - props.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); - - props.setProperty(Context.PROVIDER_URL, providerUrl); - - if (activeDirectoryDomain == null && domain.indexOf(".") > -1) { - activeDirectoryDomain = domain.substring(0, domain.indexOf(".")); - }else { - activeDirectoryDomain = domain; - } - - _logger.info("PROVIDER_DOMAIN:" + activeDirectoryDomain + " for " + domain); - String activeDirectoryPrincipal = activeDirectoryDomain + "\\" + principal; - _logger.debug("Active Directory SECURITY_PRINCIPAL : " + activeDirectoryPrincipal); - props.setProperty(Context.SECURITY_PRINCIPAL, activeDirectoryPrincipal); - props.setProperty(Context.SECURITY_CREDENTIALS, credentials); - - if (ssl && providerUrl.toLowerCase().startsWith("ldaps")) { - _logger.info("ldaps security protocol."); - System.setProperty("javax.net.ssl.trustStore", trustStore); - System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); - props.put(Context.SECURITY_PROTOCOL, "ssl"); - } - props.put(Context.REFERRAL, "follow"); - - return InitialDirContext(props); + protected void initEnvironment() { + if(props == null) { + _logger.info("PROVIDER_URL:" + providerUrl); + _logger.info("SECURITY_PRINCIPAL:" + principal); + _logger.info("SECURITY_CREDENTIALS:" + credentials); + // LDAP + props = new Properties(); + props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.setProperty(Context.URL_PKG_PREFIXES, "com.sun.jndi.url"); + props.setProperty(Context.REFERRAL, referral); + props.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); + + props.setProperty(Context.PROVIDER_URL, providerUrl); + + if (domain.indexOf(".") > -1) { + activeDirectoryDomain = domain.substring(0, domain.indexOf(".")); + }else { + activeDirectoryDomain = domain; + } + + _logger.info("PROVIDER_DOMAIN:" + activeDirectoryDomain + " for " + domain); + String activeDirectoryPrincipal = activeDirectoryDomain + "\\" + principal; + _logger.debug("Active Directory SECURITY_PRINCIPAL : " + activeDirectoryPrincipal); + props.setProperty(Context.SECURITY_PRINCIPAL, activeDirectoryPrincipal); + props.setProperty(Context.SECURITY_CREDENTIALS, credentials); + + if (ssl && providerUrl.toLowerCase().startsWith("ldaps")) { + _logger.info("ldaps security protocol."); + System.setProperty("javax.net.ssl.trustStore", trustStore); + System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); + props.put(Context.SECURITY_PROTOCOL, "ssl"); + } + props.put(Context.REFERRAL, "follow"); + } } public String getDomain() { diff --git a/maxkey-core/src/main/java/org/maxkey/persistence/ldap/LdapUtils.java b/maxkey-core/src/main/java/org/maxkey/persistence/ldap/LdapUtils.java index 87b1b892..4f4b7aae 100644 --- a/maxkey-core/src/main/java/org/maxkey/persistence/ldap/LdapUtils.java +++ b/maxkey-core/src/main/java/org/maxkey/persistence/ldap/LdapUtils.java @@ -53,6 +53,7 @@ public class LdapUtils { protected String trustStorePassword; protected boolean ssl; protected int searchScope; + protected Properties props; /** * @@ -90,42 +91,60 @@ public class LdapUtils { } protected DirContext InitialDirContext(Properties properties) { + if(ctx == null) { + ctx =createDirContext(properties); + } + return ctx; + } + + protected DirContext createDirContext(Properties properties) { + DirContext ctx = null; try { - ctx = new InitialDirContext(properties); + ctx = new InitialDirContext(properties); _logger.info("connect to ldap " + providerUrl + " seccessful."); } catch (NamingException e) { _logger.error("connect to ldap " + providerUrl + " fail."); - e.printStackTrace(); _logger.error(e.getMessage()); } return ctx; } + + protected void initEnvironment() { + // LDAP + if(props == null) { + _logger.debug("PROVIDER_URL:" + providerUrl); + _logger.debug("SECURITY_PRINCIPAL:" + principal); + _logger.trace("SECURITY_CREDENTIALS:" + credentials); + props = new Properties(); + props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); + props.setProperty(Context.URL_PKG_PREFIXES, "com.sun.jndi.url"); + props.setProperty(Context.REFERRAL, referral); + props.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); + + props.setProperty(Context.PROVIDER_URL, providerUrl); + props.setProperty(Context.SECURITY_PRINCIPAL, principal); + props.setProperty(Context.SECURITY_CREDENTIALS, credentials); + + if (ssl && providerUrl.toLowerCase().startsWith("ldaps")) { + System.setProperty("javax.net.ssl.trustStore", trustStore); + System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); + props.put(Context.SECURITY_PROTOCOL, "ssl"); + props.put(Context.REFERRAL, "follow"); + } + } + } // connect to ldap server public DirContext openConnection() { - _logger.debug("PROVIDER_URL:" + providerUrl); - _logger.debug("SECURITY_PRINCIPAL:" + principal); - _logger.trace("SECURITY_CREDENTIALS:" + credentials); - // LDAP - Properties props = new Properties(); - props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - props.setProperty(Context.URL_PKG_PREFIXES, "com.sun.jndi.url"); - props.setProperty(Context.REFERRAL, referral); - props.setProperty(Context.SECURITY_AUTHENTICATION, "simple"); - - props.setProperty(Context.PROVIDER_URL, providerUrl); - props.setProperty(Context.SECURITY_PRINCIPAL, principal); - props.setProperty(Context.SECURITY_CREDENTIALS, credentials); - - if (ssl && providerUrl.toLowerCase().startsWith("ldaps")) { - System.setProperty("javax.net.ssl.trustStore", trustStore); - System.setProperty("javax.net.ssl.trustStorePassword", trustStorePassword); - props.put(Context.SECURITY_PROTOCOL, "ssl"); - props.put(Context.REFERRAL, "follow"); - } - + initEnvironment(); return InitialDirContext(props); } + + // connect to ldap server + public DirContext createConnection() { + initEnvironment(); + return createDirContext(props); + } public boolean authenticate() { openConnection(); diff --git a/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/SynchronizerJob.java b/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/SynchronizerJob.java index 00825b18..0c2f3e7b 100644 --- a/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/SynchronizerJob.java +++ b/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/SynchronizerJob.java @@ -17,6 +17,8 @@ package org.maxkey.synchronizer; +import org.apache.mybatis.jpa.util.WebContext; +import org.maxkey.entity.Synchronizers; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.slf4j.Logger; @@ -44,10 +46,13 @@ public class SynchronizerJob implements Job { _logger.debug("SynchronizerJob is running ... " ); jobStatus = JOBSTATUS.RUNNING; try { - ISynchronizerService service = - (ISynchronizerService)context.getMergedJobDataMap().get("synchronizerService"); + Synchronizers synchronizer = (Synchronizers)context.getMergedJobDataMap().get("synchronizer"); + _logger.debug("synchronizer : " + synchronizer.getName()+"("+synchronizer.getId()+"_"+synchronizer.getSourceType()+")"); + _logger.debug("synchronizer service : " + synchronizer.getService()); + _logger.debug("synchronizer Scheduler : " + synchronizer.getScheduler()); + ISynchronizerService service = (ISynchronizerService)WebContext.getBean(synchronizer.getService()); + service.setSynchronizer(synchronizer); service.sync(); - Thread.sleep(10 *1000); _logger.debug("SynchronizerJob is success " ); }catch(Exception e) { diff --git a/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/autoconfigure/SynchronizerAutoConfiguration.java b/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/autoconfigure/SynchronizerAutoConfiguration.java new file mode 100644 index 00000000..a63d46dc --- /dev/null +++ b/maxkey-identitys/maxkey-synchronizers/src/main/java/org/maxkey/synchronizer/autoconfigure/SynchronizerAutoConfiguration.java @@ -0,0 +1,118 @@ +package org.maxkey.synchronizer.autoconfigure; + +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; + +import org.maxkey.constants.ConstantsProperties; +import org.maxkey.entity.Synchronizers; +import org.maxkey.synchronizer.SynchronizerJob; +import org.quartz.CronExpression; +import org.quartz.CronScheduleBuilder; +import org.quartz.CronTrigger; +import org.quartz.JobBuilder; +import org.quartz.JobDataMap; +import org.quartz.JobDetail; +import org.quartz.Scheduler; +import org.quartz.SchedulerException; +import org.quartz.TriggerBuilder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.jdbc.core.RowMapper; +import org.springframework.scheduling.quartz.SchedulerFactoryBean; + +@Configuration +@PropertySource(ConstantsProperties.applicationPropertySource) +public class SynchronizerAutoConfiguration implements InitializingBean { + private static final Logger _logger = + LoggerFactory.getLogger(SynchronizerAutoConfiguration.class); + public static final String SYNCHRONIZERS_SELECT_STATEMENT = "select * from mxk_synchronizers where status ='1'"; + + @Bean(name = "schedulerSynchronizerJobs") + public Scheduler schedulerSynchronizerJobs( + JdbcTemplate jdbcTemplate, + SchedulerFactoryBean schedulerFactoryBean, + @Value("${maxkey.job.cron.enable}") boolean jobCronEnable + ) throws SchedulerException { + + Scheduler scheduler = schedulerFactoryBean.getScheduler(); + if(jobCronEnable) { + List synchronizerList = querySynchronizers(jdbcTemplate); + for(Synchronizers synchronizer : synchronizerList) { + if(synchronizer.getScheduler()!=null + && !synchronizer.getScheduler().equals("") + && CronExpression.isValidExpression(synchronizer.getScheduler())) { + _logger.debug("synchronizer details : " + synchronizer); + buildJob(scheduler,synchronizer); + } + } + } + return scheduler; + } + + + private void buildJob(Scheduler scheduler , + Synchronizers synchronizer) throws SchedulerException { + JobDetail jobDetail = + JobBuilder.newJob(SynchronizerJob.class) + .withIdentity(synchronizer.getService()+"Job", "SynchronizerGroups") + .build(); + + JobDataMap jobDataMap = new JobDataMap(); + jobDataMap.put("synchronizer", synchronizer); + _logger.debug("synchronizer : " + synchronizer.getName()+"("+synchronizer.getId()+"_"+synchronizer.getSourceType()+")"); + _logger.debug("synchronizer service : " + synchronizer.getService()); + _logger.debug("synchronizer Scheduler : " + synchronizer.getScheduler()); + CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(synchronizer.getScheduler()); + CronTrigger cronTrigger = + TriggerBuilder.newTrigger() + .withIdentity("trigger"+synchronizer.getService(), "SynchronizerGroups") + .usingJobData(jobDataMap) + .withSchedule(scheduleBuilder) + .build(); + scheduler.scheduleJob(jobDetail,cronTrigger); + } + + public List querySynchronizers(JdbcTemplate jdbcTemplate) { + List synchronizerList = jdbcTemplate.query(SYNCHRONIZERS_SELECT_STATEMENT, new RowMapper() { + public Synchronizers mapRow(ResultSet rs, int rowNum) throws SQLException { + Synchronizers synchronizer = new Synchronizers(); + synchronizer.setId( rs.getString("id")); + synchronizer.setName( rs.getString("name")); + synchronizer.setScheduler( rs.getString("scheduler")); + synchronizer.setSourceType( rs.getString("sourcetype")); + synchronizer.setProviderUrl(rs.getString("providerurl")); + synchronizer.setDriverClass(rs.getString("driverclass")); + synchronizer.setPrincipal( rs.getString("principal")); + synchronizer.setCredentials(rs.getString("credentials")); + synchronizer.setResumeTime( rs.getString("resumetime")); + synchronizer.setSuspendTime(rs.getString("suspendtime")); + synchronizer.setFilters( rs.getString("filters")); + synchronizer.setBasedn( rs.getString("basedn")); + synchronizer.setMsadDomain( rs.getString("msaddomain")); + synchronizer.setSslSwitch( rs.getString("sslswitch")); + synchronizer.setTrustStore( rs.getString("truststore")); + synchronizer.setStatus( rs.getString("status")); + synchronizer.setDescription(rs.getString("description")); + synchronizer.setSyncStartTime(rs.getInt("syncstarttime")); + synchronizer.setService(rs.getString("service")); + + return synchronizer; + } + }); + + return synchronizerList; + } + + @Override + public void afterPropertiesSet() throws Exception { + // TODO Auto-generated method stub + + } +} diff --git a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryLoginAppsMapper.xml b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryLoginAppsMapper.xml index debe838d..ca9415fd 100644 --- a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryLoginAppsMapper.xml +++ b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryLoginAppsMapper.xml @@ -19,7 +19,7 @@ and uid = #{uid} - and username = #{username} + and username = #{username} and displayname like concat('%',#{displayName},'%') diff --git a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ReportMapper.xml b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ReportMapper.xml index 5a88017e..2c3e8bd3 100644 --- a/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ReportMapper.xml +++ b/maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/ReportMapper.xml @@ -22,8 +22,9 @@ select count(*) reportcount from mxk_userinfo - where - lastlogintime -lastlogofftime + where online = 1 + and now() - lastlogintime between 1 and 10000 + and lastlogintime > lastlogofftime