Identity Provisioning based on Kafka

Identity Provisioning based on Kafka, Have many connectors
This commit is contained in:
shimingxy 2020-06-14 13:05:49 +08:00
parent fbad51f4f7
commit 0ae9bcda77
87 changed files with 2611 additions and 11 deletions

View File

@ -2,6 +2,6 @@
<fileset-config file-format-version="1.2.0" simple-config="true" sync-formatter="false">
<fileset name="all" enabled="true" check-config-name="checkstyle-rules" local="false">
<file-match-pattern match-pattern=".*" include-pattern="true"/>
<file-match-pattern match-pattern="." include-pattern="true"/>
</fileset>
</fileset-config>

View File

@ -31,11 +31,15 @@ allprojects {
compileJava.options.encoding = 'UTF-8'
eclipse {
jdt {
File f = file('.settings/org.eclipse.core.resources.prefs')
f.write('eclipse.preferences.version=1\n')
f.append('encoding/<project>=UTF-8') //use UTF-8
}/*
}
/**/
/*
wtp {
facet {
facet name: 'jst.web', type: Facet.FacetType.fixed
@ -174,7 +178,7 @@ subprojects {
//compile group: 'org.springframework', name: 'spring-jcl', version: "${springVersion}"
compile group: 'org.springframework', name: 'spring-jdbc', version: "${springVersion}"
//compile group: 'org.springframework', name: 'spring-jms', version: "${springVersion}"
//compile group: 'org.springframework', name: 'spring-messaging', version: "${springVersion}"
compile group: 'org.springframework', name: 'spring-messaging', version: "${springVersion}"
//compile group: 'org.springframework', name: 'spring-orm', version: "${springVersion}"
compile group: 'org.springframework', name: 'spring-oxm', version: "${springVersion}"
compile group: 'org.springframework', name: 'spring-tx', version: "${springVersion}"
@ -183,6 +187,15 @@ subprojects {
compile group: 'org.springframework', name: 'spring-webmvc', version: "${springVersion}"
//compile group: 'org.springframework', name: 'spring-websocket', version: "${springVersion}"
testCompile group: 'org.springframework', name: 'spring-test', version: "${springVersion}"
// https://mvnrepository.com/artifact/org.apache.kafka/kafka-clients
compile group: 'org.apache.kafka', name: 'kafka-clients', version: '2.5.0'
// https://mvnrepository.com/artifact/org.springframework.kafka/spring-kafka
compile group: 'org.springframework.kafka', name: 'spring-kafka', version: '2.5.2.RELEASE'
// https://mvnrepository.com/artifact/org.springframework.retry/spring-retry
compile group: 'org.springframework.retry', name: 'spring-retry', version: '1.3.0'
//spring-security
compile group: 'org.springframework.security', name: 'spring-security-core', version: "${springSecurityVersion}"
compile group: 'org.springframework.security', name: 'spring-security-web', version: "${springSecurityVersion}"

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer"/>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connectors</name>
<comment>Project maxkey-connectors created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
<attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-activedirectory</name>
<comment>Project maxkey-connectors-activedirectory created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
connection.project.dir=../..
eclipse.preferences.version=1

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,14 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="maxkey-connector-activedirectory">
<wb-resource deploy-path="/" source-path="src/main/resources"/>
<wb-resource deploy-path="/" source-path="src/main/java"/>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-connector-base/maxkey-connector-base">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-identity-kafka/maxkey-identity-kafka">
<dependency-type>uses</dependency-type>
</dependent-module>
</wb-module>
</project-modules>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.java"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="jst.java" version="1.8"/>
</faceted-project>

View File

@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

View File

@ -0,0 +1,17 @@
description = "maxkey-connector-activedirectory"
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
dependencies {
//local jars
compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
compile project(":maxkey-core")
compile project(":maxkey-dao")
compile project(":maxkey-client-sdk")
compile project(":maxkey-connectors:maxkey-connector-base")
compile project(":maxkey-identitys:maxkey-identity-kafka")
}

View File

@ -0,0 +1,56 @@
package org.maxkey.connector;
import org.maxkey.constants.ConstantsProperties;
import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(ConstantsProperties.applicationPropertySource)
@SpringBootApplication
@ComponentScan(basePackages = {
"org.maxkey.connector",
"org.maxkey.connector.receiver",
"org.maxkey.connector.activedirectory"
})
public class ActivedirectoryConsumerApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(ActivedirectoryConsumerApplication.class, args);
}
//@Bean(name = "activeDirectoryUtils")
public ActiveDirectoryUtils getLdapConnection(
@Value("${config.connector.activedirectory.providerUrl}") String providerUrl,
@Value("${config.connector.activedirectory.principal}") String principal,
@Value("${config.connector.activedirectory.credentials}") String credentials,
@Value("${config.connector.activedirectory.baseDN}") String baseDn,
@Value("${config.connector.activedirectory.domain}") String domain,
@Value("${config.connector.activedirectory.trustStore}") String trustStore,
@Value("${config.connector.activedirectory.trustStore.password}") String trustStorePassword
)throws Exception{
ActiveDirectoryUtils ldapUtils=new ActiveDirectoryUtils(
providerUrl,
principal,
credentials,
baseDn,
domain);
ldapUtils.setTrustStore(trustStore);
ldapUtils.setTrustStorePassword(trustStorePassword);
ldapUtils.setSsl(true);
if(ldapUtils.openConnection()==null){
throw new Exception("connection to Ldap Error.");
}
return ldapUtils;
}
}

View File

@ -0,0 +1,181 @@
package org.maxkey.connector.activedirectory;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.GroupConnector;
import org.maxkey.domain.GroupMember;
import org.maxkey.domain.Groups;
import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "groupConnector")
public class Group2Activedirectory extends GroupConnector {
private final static Logger logger = LoggerFactory.getLogger(Group2Activedirectory.class);
ActiveDirectoryUtils ldapUtils;
public Group2Activedirectory() {
// TODO Auto-generated constructor stub
}
@Override
public boolean create(Groups group) throws Exception{
logger.info("create");
try {
Attributes attributes = new BasicAttributes();
Attribute objectClass = new BasicAttribute("objectClass");
objectClass.add("top");
objectClass.add("group");
attributes.put(objectClass);
attributes.put(new BasicAttribute("cn",group.getName()));
attributes.put(new BasicAttribute("member","CN=dummy,"+ldapUtils.getBaseDN()));
String dn="cn="+group.getName()+",cn=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().createSubcontext(dn, attributes);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean update(Groups group) throws Exception{
logger.info("update");
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+group.getName()+")", constraints);
String oldDn="";
String rdn="";
if (results == null || !results.hasMore()) {
return create(group);
}else{
SearchResult sr = (SearchResult) results.next();
oldDn =sr.getNameInNamespace();
String[] dnSplit=oldDn.split(",");
rdn=oldDn.substring(oldDn.indexOf(","), oldDn.length());
String groupName=dnSplit[0].split("=")[1];
if(group.getName()!=groupName){
String newDn="cn="+group.getName()+","+rdn;
ldapUtils.getCtx().rename(oldDn, newDn);
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("cn",groupName));
ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
}
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean delete(Groups group) throws Exception {
logger.info("delete");
try {
String dn="cn="+group.getName()+",cn=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().destroySubcontext(dn);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean addMember(GroupMember groupMember) throws Exception {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
if (results == null || !results.hasMore()) {
Groups group =new Groups();
group.setName(groupMember.getGroupName());
return create(group);
}
String uniqueMember="";
SearchControls memberSearchControls = new SearchControls();
logger.debug("user Search : "+"(sAMAccountName="+groupMember.getMemberName()+")");
memberSearchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> memberResults = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+groupMember.getMemberName()+")", memberSearchControls);
if (memberResults == null || !memberResults.hasMore()) {
}else{
SearchResult memberSr = (SearchResult) memberResults.next();
uniqueMember =memberSr.getNameInNamespace();
logger.debug("uniqueMember : "+uniqueMember);
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("member",uniqueMember));
String dn="cn="+groupMember.getGroupName()+",cn=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean deleteMember(GroupMember groupMember) throws Exception{
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
if (results == null || !results.hasMore()) {
return true;
}
String uniqueMember="";
SearchControls memberSearchControls = new SearchControls();
memberSearchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> memberResults = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+groupMember.getMemberName()+")", memberSearchControls);
if (memberResults == null || !memberResults.hasMore()) {
}else{
SearchResult memberSr = (SearchResult) memberResults.next();
uniqueMember =memberSr.getNameInNamespace();
logger.debug("uniqueMember : "+uniqueMember);
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("member",uniqueMember));
String dn="cn="+groupMember.getGroupName()+",cn=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
}

View File

@ -0,0 +1,124 @@
package org.maxkey.connector.activedirectory;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.OrganizationConnector;
import org.maxkey.domain.Organizations;
import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "organizationConnector")
public class Organization2Activedirectory extends OrganizationConnector{
private final static Logger logger = LoggerFactory.getLogger(Organization2Activedirectory.class);
ActiveDirectoryUtils ldapUtils;
public Organization2Activedirectory() {
// TODO Auto-generated constructor stub
}
@Override
public boolean create(Organizations organization) throws Exception {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getpId()+"))", constraints);
String rdn="";
if (results == null || !results.hasMore()) {
rdn=ldapUtils.getBaseDN();
}else{
SearchResult sr = (SearchResult) results.next();
rdn =sr.getNameInNamespace();
}
Attributes attributes = new BasicAttributes();
attributes.put(new BasicAttribute("objectClass","organizationalUnit"));
attributes.put(new BasicAttribute("ou",organization.getName()));
//attributes.put(new BasicAttribute("name",organization.getName()));
//attributes.put(new BasicAttribute("id",organization.getId()));
//attributes.put(new BasicAttribute("porgname",organization.getpName()));
//attributes.put(new BasicAttribute("porgid",organization.getpId()));
attributes.put(new BasicAttribute("description",organization.getId()));
String dn="ou="+organization.getName()+","+rdn;
ldapUtils.getCtx().createSubcontext(dn, attributes);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return super.create(organization);
}
@Override
public boolean update(Organizations organization) throws Exception{
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
String oldDn="";
String rdn="";
if (results == null || !results.hasMore()) {
return create(organization);
}else{
SearchResult sr = (SearchResult) results.next();
oldDn =sr.getNameInNamespace();
String[] dnSplit=oldDn.split(",");
rdn=oldDn.substring(oldDn.indexOf(",")+1, oldDn.length());
String ouName=dnSplit[0].split("=")[1];
if(organization.getName()!=ouName){
String newDn="ou="+organization.getName()+","+rdn;
logger.debug("oldDn : "+oldDn);
logger.debug("newDn : "+newDn);
ldapUtils.getCtx().rename(oldDn, newDn);
//ModificationItem[] modificationItems = new ModificationItem[1];
//modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("ou",ouName));
//modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("name",organization.getName()));
//ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
}
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return super.update(organization);
}
@Override
public boolean delete(Organizations organization) throws Exception {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
String dn="";
if (results == null || !results.hasMore()) {
}else{
SearchResult sr = (SearchResult) results.next();
dn =sr.getNameInNamespace();
ldapUtils.getCtx().destroySubcontext(dn);
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return super.delete(organization);
}
}

View File

@ -0,0 +1,86 @@
package org.maxkey.connector.activedirectory;
import java.io.UnsupportedEncodingException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.PasswordConnector;
import org.maxkey.crypto.ReciprocalUtils;
import org.maxkey.domain.UserInfo;
import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "passwordConnector")
public class Password2Activedirectory extends PasswordConnector{
private final static Logger logger = LoggerFactory.getLogger(Password2Activedirectory.class);
ActiveDirectoryUtils ldapUtils;
/**
* userAccountControl鍊煎緱璇存槑
* http://support.microsoft.com/zh-cn/kb/305144
* 灞炴<EFBFBD>ф爣蹇<EFBFBD> 鍗佸叚杩涘埗鍊<EFBFBD> 鍗佽繘鍒跺<EFBFBD><EFBFBD>
SCRIPT 0x0001 1
ACCOUNTDISABLE 0x0002 2
HOMEDIR_REQUIRED 0x0008 8
LOCKOUT 0x0010 16
PASSWD_NOTREQD 0x0020 32
PASSWD_CANT_CHANGE 0x0040 64
ENCRYPTED_TEXT_PWD_ALLOWED 0x0080 128
TEMP_DUPLICATE_ACCOUNT 0x0100 256
NORMAL_ACCOUNT 0x0200 512
INTERDOMAIN_TRUST_ACCOUNT 0x0800 2048
WORKSTATION_TRUST_ACCOUNT 0x1000 4096
SERVER_TRUST_ACCOUNT 0x2000 8192
DONT_EXPIRE_PASSWORD 0x10000 65536
MNS_LOGON_ACCOUNT 0x20000 131072
SMARTCARD_REQUIRED 0x40000 262144
TRUSTED_FOR_DELEGATION 0x80000 524288
NOT_DELEGATED 0x100000 1048576
USE_DES_KEY_ONLY 0x200000 2097152
DONT_REQ_PREAUTH 0x400000 4194304
PASSWORD_EXPIRED 0x800000 8388608
TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000 16777216
*/
public Password2Activedirectory() {
}
@Override
public boolean sync(UserInfo userInfo) throws Exception{
try {
String dn=null;
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+userInfo.getUsername()+")", searchControls);
if (results == null || !results.hasMore()) {
}else{
SearchResult sr = (SearchResult) results.next();
dn =sr.getNameInNamespace();
ModificationItem[] modificationItems = new ModificationItem[1];
logger.info("decipherable : "+userInfo.getDecipherable());
String password=ReciprocalUtils.decoder(userInfo.getDecipherable());
//modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userPassword",password));
modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("unicodePwd",("\"" + password + "\"").getBytes("UTF-16LE")));
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return true;
}
}

View File

@ -0,0 +1,271 @@
package org.maxkey.connector.activedirectory;
import java.io.UnsupportedEncodingException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.UserInfoConnector;
import org.maxkey.crypto.ReciprocalUtils;
import org.maxkey.domain.UserInfo;
import org.maxkey.persistence.ldap.ActiveDirectoryUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "userInfoConnector")
public class UserInfo2Activedirectory extends UserInfoConnector{
private final static Logger logger = LoggerFactory.getLogger(UserInfo2Activedirectory.class);
ActiveDirectoryUtils ldapUtils;
/**
* userAccountControl值得说明
* http://support.microsoft.com/zh-cn/kb/305144
* <EFBFBD>?<EFBFBD><EFBFBD>? 十六进制<EFBFBD>? 十进制<EFBFBD>??
SCRIPT 0x0001 1
ACCOUNTDISABLE 0x0002 2
HOMEDIR_REQUIRED 0x0008 8
LOCKOUT 0x0010 16
PASSWD_NOTREQD 0x0020 32
PASSWD_CANT_CHANGE 0x0040 64
ENCRYPTED_TEXT_PWD_ALLOWED 0x0080 128
TEMP_DUPLICATE_ACCOUNT 0x0100 256
NORMAL_ACCOUNT 0x0200 512
INTERDOMAIN_TRUST_ACCOUNT 0x0800 2048
WORKSTATION_TRUST_ACCOUNT 0x1000 4096
SERVER_TRUST_ACCOUNT 0x2000 8192
DONT_EXPIRE_PASSWORD 0x10000 65536
MNS_LOGON_ACCOUNT 0x20000 131072
SMARTCARD_REQUIRED 0x40000 262144
TRUSTED_FOR_DELEGATION 0x80000 524288
NOT_DELEGATED 0x100000 1048576
USE_DES_KEY_ONLY 0x200000 2097152
DONT_REQ_PREAUTH 0x400000 4194304
PASSWORD_EXPIRED 0x800000 8388608
TRUSTED_TO_AUTH_FOR_DELEGATION 0x1000000 16777216
*/
public UserInfo2Activedirectory() {
}
@Override
public boolean create(UserInfo userInfo) throws Exception{
try {
Attributes attributes = new BasicAttributes();
Attribute objectClass = new BasicAttribute("objectClass");
objectClass.add("top");
objectClass.add("person");
objectClass.add("organizationalPerson");
objectClass.add("user");
attributes.put(objectClass);
attributes.put(new BasicAttribute("sAMAccountName",userInfo.getUsername()));
logger.debug("decipherable : "+userInfo.getDecipherable());
String password=ReciprocalUtils.decoder(userInfo.getDecipherable());
attributes.put(new BasicAttribute("unicodePwd",("\"" + password + "\"").getBytes("UTF-16LE")));
//attributes.put(new BasicAttribute("cn",userInfo.getDisplayName()));
attributes.put(new BasicAttribute("cn",userInfo.getUsername()));
attributes.put(new BasicAttribute("displayName",userInfo.getDisplayName()));
attributes.put(new BasicAttribute("givenName",userInfo.getGivenName()));
attributes.put(new BasicAttribute("sn",userInfo.getFamilyName()));
attributes.put(new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"00000000000":userInfo.getWorkPhoneNumber()));
attributes.put(new BasicAttribute("mail",userInfo.getWorkEmail()==null?"email@default.com":userInfo.getWorkEmail()));
attributes.put(new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"0":userInfo.getEmployeeNumber()));
attributes.put(new BasicAttribute("ou",userInfo.getDepartment()==null?"default":userInfo.getDepartment()));
String managerDn="CN=dummy,"+ldapUtils.getBaseDN();
if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
logger.debug("manager is null.");
}else{
UserInfo queryManager=new UserInfo();
queryManager.setId(userInfo.getManagerId());
UserInfo manager=loadUser(queryManager);
SearchControls managerSearchControls = new SearchControls();
managerSearchControls.setSearchScope(ldapUtils.getSearchScope());
logger.debug("managerResults : "+ldapUtils.getBaseDN());
logger.debug("filter : "+"(sAMAccountName="+manager.getUsername()+")");
logger.debug("managerSearchControls : "+managerSearchControls);
NamingEnumeration<SearchResult> managerResults = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+manager.getUsername()+")", managerSearchControls);
if (managerResults == null || !managerResults.hasMore()) {
}else{
SearchResult managerSr = (SearchResult) managerResults.next();
managerDn =managerSr.getNameInNamespace();
}
}
attributes.put(new BasicAttribute("manager",managerDn));
attributes.put(new BasicAttribute("department",userInfo.getDepartment()==null?"default":userInfo.getDepartment()));
attributes.put(new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"default":userInfo.getDepartmentId()));
attributes.put(new BasicAttribute("title",userInfo.getJobTitle()==null?"default":userInfo.getJobTitle()));
//for kerberos login
attributes.put(new BasicAttribute("servicePrincipalName",this.properties.getProperty("servicePrincipalName")));
attributes.put(new BasicAttribute("userPrincipalName",userInfo.getUsername()+"@"+this.properties.getProperty("domain")));
attributes.put(new BasicAttribute("userAccountControl",Integer.toString(66048)));
String rdn="";
if(userInfo.getDepartmentId()!=null&&
!userInfo.getDepartmentId().equals("")){
//get organization dn
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(ldapUtils.getSearchScope());
logger.debug("managerResults : "+ldapUtils.getBaseDN());
logger.debug("filter : "+"(&(objectClass=organizationalUnit)(description="+userInfo.getDepartmentId()+"))");
logger.debug("searchControls : "+searchControls);
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+userInfo.getDepartmentId()+"))", searchControls);
if (results == null || !results.hasMore()) {
rdn=ldapUtils.getBaseDN();
}else{
SearchResult sr = (SearchResult) results.next();
rdn =sr.getNameInNamespace();
}
}else{
rdn=ldapUtils.getBaseDN();
}
//String dn="CN="+userInfo.getDisplayName()+","+rdn;
String dn="CN="+userInfo.getUsername()+","+rdn;
logger.debug("dn : "+dn);
ldapUtils.getCtx().createSubcontext(dn, attributes);
ldapUtils.close();
super.create(userInfo);
} catch (NamingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean update(UserInfo userInfo) throws Exception{
try {
String dn=null;
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+userInfo.getUsername()+")", searchControls);
if (results == null || !results.hasMore()) {
return create(loadUser(userInfo));
}
SearchResult sr = (SearchResult) results.next();
dn =sr.getNameInNamespace();
ModificationItem[] modificationItems = new ModificationItem[8];
//modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName",userInfo.getDisplayName()));
//modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("cn",userInfo.getDisplayName()));
//modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("givenName",userInfo.getGivenName()));
//modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("sn",userInfo.getFamilyName()));
modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"00000000000":userInfo.getWorkPhoneNumber()));
modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mail",userInfo.getWorkEmail()==null?"email@default.com":userInfo.getWorkEmail()));
modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"default":userInfo.getEmployeeNumber()));
modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("ou",userInfo.getDepartment()==null?"default":userInfo.getDepartment()));
modificationItems[4]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("department",userInfo.getDepartmentId()==null?"default":userInfo.getDepartment()));
modificationItems[5]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"default":userInfo.getDepartmentId()));
modificationItems[6]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("title",userInfo.getJobTitle()==null?"default":userInfo.getJobTitle()));
String managerDn="CN=dummy,"+ldapUtils.getBaseDN();
if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
}else{
UserInfo queryManager=new UserInfo();
queryManager.setId(userInfo.getManagerId());
UserInfo manager=loadUser(queryManager);
SearchControls managerSearchControls = new SearchControls();
managerSearchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> managerResults = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+manager.getUsername()+")", managerSearchControls);
if (managerResults == null || !managerResults.hasMore()) {
}else{
SearchResult managerSr = (SearchResult) managerResults.next();
managerDn =managerSr.getNameInNamespace();
}
}
modificationItems[7]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("manager",managerDn));
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
if(userInfo.getDepartmentId()!=null&&
!userInfo.getDepartmentId().equals("")){
//get organization dn
SearchControls orgSearchControls = new SearchControls();
orgSearchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> orgResults = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+userInfo.getDepartmentId()+"))", orgSearchControls);
String orgRdn="";
if (orgResults == null || !orgResults.hasMore()) {
orgRdn=ldapUtils.getBaseDN();
}else{
SearchResult orgSearchResult = (SearchResult) orgResults.next();
orgRdn =orgSearchResult.getNameInNamespace();
}
//String newDn="CN="+userInfo.getDisplayName()+","+orgRdn;
String newDn="CN="+userInfo.getUsername()+","+orgRdn;
if(!dn.equals(newDn)){
logger.debug("oldDn : "+dn);
logger.debug("newDn : "+newDn);
ldapUtils.getCtx().rename(dn, newDn);
}
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean delete(UserInfo userInfo) throws Exception{
try {
String dn=null;
SearchControls searchControls = new SearchControls();
searchControls.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(sAMAccountName="+userInfo.getUsername()+")", searchControls);
if (results == null || !results.hasMore()) {
}else{
SearchResult sr = (SearchResult) results.next();
dn =sr.getNameInNamespace();
logger.debug("delete dn : "+dn);
ldapUtils.getCtx().destroySubcontext(dn);
}
ldapUtils.close();
super.delete(userInfo);
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
public UserInfo loadUser(UserInfo UserInfo) {
return null;
}
}

View File

@ -0,0 +1,48 @@
#spring.profiles.active=dev
#application
application.title=MaxKey-Connector-ActiveDirectory
application.name=MaxKey-Connector-ActiveDirectory
application.formatted-version=v2.0.0 GA
#server port
server.port=9602
#datasource
spring.datasource.username=root
spring.datasource.password=maxkey
spring.datasource.url=jdbc:mysql://localhost/maxkey?autoReconnect=true&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.kafka.bootstrap-servers=localhost:9092
###########【初始化消费者配置】###########
# 默认的消费组ID
spring.kafka.consumer.properties.group.id=defaultConsumerGroup
# 是否自动提交offset
spring.kafka.consumer.enable-auto-commit=true
# 提交offset延时(接收到消息后多久提交offset)
spring.kafka.consumer.auto.commit.interval.ms=1000
# 当kafka中没有初始offset或offset超出范围时将自动重置offset
# earliest:重置为分区中最小的offset;
# latest:重置为分区中最新的offset(消费分区中新产生的数据);
# none:只要有一个分区不存在已提交的offset,就抛出异常;
spring.kafka.consumer.auto-offset-reset=latest
# 消费会话超时时间(超过这个时间consumer没有发送心跳,就会触发rebalance操作)
spring.kafka.consumer.properties.session.timeout.ms=120000
# 消费请求超时时间
spring.kafka.consumer.properties.request.timeout.ms=180000
# Kafka提供的序列化和反序列化类
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
# 消费端监听的topic不存在时项目启动会报错(关掉)
spring.kafka.listener.missing-topics-fatal=false
# 设置批量消费
# spring.kafka.listener.type=batch
# 批量消费每次最多消费多少条消息
# spring.kafka.consumer.max-poll-records=50
config.connector.activedirectory.providerUrl=ldap://
config.connector.activedirectory.principal=maxkey
config.connector.activedirectory.credentials=maxkey
config.connector.activedirectory.baseDN=dc=maxkey,dc=top
config.connector.activedirectory.domain=MAXKEY
config.connector.activedirectory.trustStore=maxkey
config.connector.activedirectory.trustStore.password=maxkey

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
<attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-base</name>
<comment>Project maxkey-connectors-base created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
connection.project.dir=../..
eclipse.preferences.version=1

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,14 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="maxkey-connector-base">
<wb-resource deploy-path="/" source-path="src/main/resources"/>
<wb-resource deploy-path="/" source-path="src/main/java"/>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-identity-kafka/maxkey-identity-kafka">
<dependency-type>uses</dependency-type>
</dependent-module>
</wb-module>
</project-modules>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.java"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="jst.java" version="1.8"/>
</faceted-project>

View File

@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

View File

@ -0,0 +1,16 @@
description = "maxkey-connector-base"
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
dependencies {
//local jars
compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
compile project(":maxkey-core")
compile project(":maxkey-dao")
compile project(":maxkey-client-sdk")
compile project(":maxkey-identitys:maxkey-identity-kafka")
}

View File

@ -0,0 +1,53 @@
package org.maxkey.connector;
import java.util.Properties;
import org.springframework.jdbc.core.JdbcTemplate;
public abstract class AbstractConnector<T>{
public static class CONNECTOR_TYPE{
public static int USERINFO_TYPE=1;
public static int ORG_TYPE=2;
public static int GROUP_TYPE=3;
public static int PASSWORD_TYPE=4;
}
protected Properties properties;
protected JdbcTemplate jdbcTemplate;
public boolean create(T entity) throws Exception{
return true;
}
public boolean update(T entity) throws Exception{
return true;
}
public boolean delete(T entity) throws Exception{
return true;
}
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}

View File

@ -0,0 +1,33 @@
package org.maxkey.connector;
import org.maxkey.domain.GroupMember;
import org.maxkey.domain.Groups;
public abstract class GroupConnector extends AbstractConnector <Groups> {
@Override
public boolean create(Groups group) throws Exception{
return true;
}
@Override
public boolean update(Groups group) throws Exception{
return true;
}
@Override
public boolean delete(Groups group) throws Exception{
return true;
}
public boolean addMember(GroupMember groupMember) throws Exception{
return true;
}
public boolean deleteMember(GroupMember groupMember) throws Exception{
return true;
}
}

View File

@ -0,0 +1,22 @@
package org.maxkey.connector;
import org.maxkey.domain.Organizations;
public abstract class OrganizationConnector extends AbstractConnector <Organizations> {
@Override
public boolean create(Organizations organization) throws Exception{
return true;
}
@Override
public boolean update(Organizations organization) throws Exception{
return true;
}
@Override
public boolean delete(Organizations organization) throws Exception{
return true;
}
}

View File

@ -0,0 +1,13 @@
package org.maxkey.connector;
import org.maxkey.domain.UserInfo;
public abstract class PasswordConnector extends AbstractConnector<UserInfo> {
public boolean sync(UserInfo userInfo) throws Exception{
return true;
}
}

View File

@ -0,0 +1,23 @@
package org.maxkey.connector;
import org.maxkey.domain.UserInfo;
public abstract class UserInfoConnector extends AbstractConnector<UserInfo> {
@Override
public boolean create(UserInfo userInfo) throws Exception {
return true;
}
@Override
public boolean update(UserInfo userInfo) throws Exception{
return true;
}
@Override
public boolean delete(UserInfo userInfo) throws Exception{
return true;
}
}

View File

@ -0,0 +1,34 @@
package org.maxkey.connector.receiver;
import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.GroupConnector;
import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class KafkaGroupsTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaGroupsTopicReceiver.class);
@Autowired
GroupConnector groupConnector;
@KafkaListener(topics = {KafkaIdentityTopic.GROUP_TOPIC})
public void listen(ConsumerRecord<?, ?> record) {
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record);
_logger.info("------------------ message =" + message);
}
}
}

View File

@ -0,0 +1,34 @@
package org.maxkey.connector.receiver;
import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.OrganizationConnector;
import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class KafkaOrgsTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaOrgsTopicReceiver.class);
@Autowired
OrganizationConnector organizationConnector;
@KafkaListener(topics = {KafkaIdentityTopic.ORG_TOPIC})
public void listen(ConsumerRecord<?, ?> record) {
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record);
_logger.info("------------------ message =" + message);
}
}
}

View File

@ -0,0 +1,34 @@
package org.maxkey.connector.receiver;
import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.PasswordConnector;
import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class KafkaPasswordTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaPasswordTopicReceiver.class);
@Autowired
PasswordConnector passwordConnector;
@KafkaListener(topics = {KafkaIdentityTopic.PASSWORD_TOPIC})
public void listen(ConsumerRecord<?, ?> record) {
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record);
_logger.info("------------------ message =" + message);
}
}
}

View File

@ -0,0 +1,34 @@
package org.maxkey.connector.receiver;
import java.util.Optional;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.maxkey.connector.UserInfoConnector;
import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.stereotype.Component;
@Component
public class KafkaUserInfoTopicReceiver {
private static final Logger _logger = LoggerFactory.getLogger(KafkaUserInfoTopicReceiver.class);
@Autowired
UserInfoConnector userInfoConnector;
@KafkaListener(topics = {KafkaIdentityTopic.USERINFO_TOPIC})
public void listen(ConsumerRecord<?, ?> record) {
Optional<?> kafkaMessage = Optional.ofNullable(record.value());
if (kafkaMessage.isPresent()) {
Object message = kafkaMessage.get();
_logger.info("----------------- record =" + record);
_logger.info("------------------ message =" + message);
}
}
}

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
<attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-connector-ldap</name>
<comment>Project maxkey-connectors-ldap created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
connection.project.dir=../..
eclipse.preferences.version=1

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,14 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="maxkey-connector-ldap">
<wb-resource deploy-path="/" source-path="src/main/resources"/>
<wb-resource deploy-path="/" source-path="src/main/java"/>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-connector-base/maxkey-connector-base">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-identity-kafka/maxkey-identity-kafka">
<dependency-type>uses</dependency-type>
</dependent-module>
</wb-module>
</project-modules>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.java"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="jst.java" version="1.8"/>
</faceted-project>

View File

@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

View File

@ -0,0 +1,17 @@
description = "maxkey-connector-ldap"
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
dependencies {
//local jars
compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
compile project(":maxkey-core")
compile project(":maxkey-dao")
compile project(":maxkey-client-sdk")
compile project(":maxkey-connectors:maxkey-connector-base")
compile project(":maxkey-identitys:maxkey-identity-kafka")
}

View File

@ -0,0 +1,55 @@
package org.maxkey.connector;
import org.maxkey.constants.ConstantsProperties;
import org.maxkey.persistence.ldap.LdapUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource(ConstantsProperties.applicationPropertySource)
@SpringBootApplication
@ComponentScan(basePackages = {
"org.maxkey.connector",
"org.maxkey.connector.receiver",
"org.maxkey.connector.ldap"
})
public class LdapConsumerApplication {
public static void main(String[] args) {
// TODO Auto-generated method stub
ConfigurableApplicationContext context = SpringApplication.run(LdapConsumerApplication.class, args);
}
//@Bean(name = "ldapUtils")
public LdapUtils getLdapConnection(
@Value("${config.connector.ldap.providerUrl}") String providerUrl,
@Value("${config.connector.ldap.principal}") String principal,
@Value("${config.connector.ldap.credentials}") String credentials,
@Value("${config.connector.ldap.baseDN}") String baseDn
)throws Exception{
LdapUtils ldapUtils=new LdapUtils(
providerUrl,
principal,
credentials,
baseDn);
if(ldapUtils.openConnection()==null){
throw new Exception("connection to Ldap Error.");
}
return ldapUtils;
}
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(LdapConsumerApplication.class);
}
}

View File

@ -0,0 +1,153 @@
package org.maxkey.connector.ldap;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.GroupConnector;
import org.maxkey.domain.GroupMember;
import org.maxkey.domain.Groups;
import org.maxkey.persistence.ldap.LdapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "groupConnector")
public class Group2Ldap extends GroupConnector {
private final static Logger logger = LoggerFactory.getLogger(Group2Ldap.class);
LdapUtils ldapUtils;
public Group2Ldap() {
}
@Override
public boolean create(Groups group) throws Exception{
logger.info("create");
try {
Attributes attributes = new BasicAttributes();
attributes.put(new BasicAttribute("objectClass","groupOfUniqueNames"));
attributes.put(new BasicAttribute("cn",group.getName()));
attributes.put(new BasicAttribute("uniqueMember","uid=dummy"));
String dn="cn="+group.getName()+",dc=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().createSubcontext(dn, attributes);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean update(Groups group) throws Exception{
logger.info("update");
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+group.getName()+")", constraints);
String oldDn="";
String rdn="";
if (results == null || !results.hasMore()) {
return create(group);
}else{
SearchResult sr = (SearchResult) results.next();
oldDn =sr.getNameInNamespace();
String[] dnSplit=oldDn.split(",");
rdn=oldDn.substring(oldDn.indexOf(","), oldDn.length());
String groupName=dnSplit[0].split("=")[1];
if(group.getName()!=groupName){
String newDn="cn="+group.getName()+","+rdn;
ldapUtils.getCtx().rename(oldDn, newDn);
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("cn",groupName));
ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
}
}
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean delete(Groups group) throws Exception {
logger.info("delete");
try {
String dn="cn="+group.getName()+",dc=groups,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().destroySubcontext(dn);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean addMember(GroupMember groupMember) throws Exception {
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
if (results == null || !results.hasMore()) {
Groups group =new Groups();
group.setName(groupMember.getGroupName());
create(group);
}
String uniqueMember="uid="+groupMember.getMemberName()+",dc=users,"+ldapUtils.getBaseDN();
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.ADD_ATTRIBUTE,new BasicAttribute("uniqueMember",uniqueMember));
String dn="cn="+groupMember.getGroupName()+",dc=groups,"+ldapUtils.getBaseDN();
logger.debug("dn : "+dn);
logger.debug("uniqueMember : "+uniqueMember);
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean deleteMember(GroupMember groupMember) throws Exception{
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(cn="+groupMember.getGroupName()+")", constraints);
if (results == null || !results.hasMore()) {
return true;
}
String uniqueMember="uid="+groupMember.getMemberName()+",dc=users,"+ldapUtils.getBaseDN();
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("uniqueMember",uniqueMember));
String dn="cn="+groupMember.getGroupName()+",dc=groups,"+ldapUtils.getBaseDN();
logger.debug("dn : "+dn);
logger.debug("uniqueMember : "+uniqueMember);
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
}

View File

@ -0,0 +1,119 @@
package org.maxkey.connector.ldap;
import javax.naming.NamingEnumeration;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.OrganizationConnector;
import org.maxkey.domain.Organizations;
import org.maxkey.persistence.ldap.LdapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "organizationConnector")
public class Organization2Ldap extends OrganizationConnector{
private final static Logger logger = LoggerFactory.getLogger(Organization2Ldap.class);
LdapUtils ldapUtils;
public Organization2Ldap() {
}
@Override
public boolean create(Organizations organization) throws Exception {
logger.info("create");
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getpId()+"))", constraints);
String rdn="";
if (results == null || !results.hasMore()) {
rdn=ldapUtils.getBaseDN();
}else{
SearchResult sr = (SearchResult) results.next();
rdn =sr.getNameInNamespace();
}
Attributes attributes = new BasicAttributes();
attributes.put(new BasicAttribute("objectClass","organizationalUnit"));
attributes.put(new BasicAttribute("ou",organization.getName()));
//attributes.put(new BasicAttribute("name",organization.getName()));
//attributes.put(new BasicAttribute("id",organization.getId()));
//attributes.put(new BasicAttribute("porgname",organization.getpName()));
//attributes.put(new BasicAttribute("porgid",organization.getpId()));
attributes.put(new BasicAttribute("description",organization.getId()));
String dn="ou="+organization.getName()+","+rdn;
ldapUtils.getCtx().createSubcontext(dn, attributes);
ldapUtils.close();
return super.create(organization);
}
@Override
public boolean update(Organizations organization) throws Exception{
logger.info("update");
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
String oldDn="";
String rdn="";
if (results == null || !results.hasMore()) {
return create(organization);
}else{
SearchResult sr = (SearchResult) results.next();
oldDn =sr.getNameInNamespace();
String[] dnSplit=oldDn.split(",");
rdn=oldDn.substring(oldDn.indexOf(",")+1, oldDn.length());
String ouName=dnSplit[0].split("=")[1];
if(organization.getName()!=ouName){
String newDn="ou="+organization.getName()+","+rdn;
logger.debug("oldDn : "+oldDn);
logger.debug("newDn : "+newDn);
ldapUtils.getCtx().rename(oldDn, newDn);
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.REMOVE_ATTRIBUTE,new BasicAttribute("ou",ouName));
//modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("name",organization.getName()));
//modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("id",organization.getId()));
//modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("porgname",organization.getpName()));
//modificationItems[4]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("porgid",organization.getpId()));
ldapUtils.getCtx().modifyAttributes(newDn, modificationItems);
}
}
ldapUtils.close();
return super.update(organization);
}
@Override
public boolean delete(Organizations organization) throws Exception{
logger.info("delete");
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=organizationalUnit)(description="+organization.getId()+"))", constraints);
String dn="";
if (results == null || !results.hasMore()) {
}else{
SearchResult sr = (SearchResult) results.next();
dn =sr.getNameInNamespace();
ldapUtils.getCtx().destroySubcontext(dn);
}
ldapUtils.close();
return super.delete(organization);
}
}

View File

@ -0,0 +1,45 @@
package org.maxkey.connector.ldap;
import javax.naming.NamingException;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import org.maxkey.connector.PasswordConnector;
import org.maxkey.crypto.ReciprocalUtils;
import org.maxkey.domain.UserInfo;
import org.maxkey.persistence.ldap.LdapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "passwordConnector")
public class Password2Ldap extends PasswordConnector{
private final static Logger logger = LoggerFactory.getLogger(Password2Ldap.class);
LdapUtils ldapUtils;
public Password2Ldap() {
}
@Override
public boolean sync(UserInfo userInfo) throws Exception{
logger.info("changePassword");
try {
ModificationItem[] modificationItems = new ModificationItem[1];
modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("userPassword",ReciprocalUtils.decoder(userInfo.getDecipherable())));
String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
}

View File

@ -0,0 +1,140 @@
package org.maxkey.connector.ldap;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import org.maxkey.connector.UserInfoConnector;
import org.maxkey.crypto.ReciprocalUtils;
import org.maxkey.domain.UserInfo;
import org.maxkey.persistence.ldap.LdapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component(value = "userInfoConnector")
public class UserInfo2Ldap extends UserInfoConnector{
private final static Logger logger = LoggerFactory.getLogger(UserInfo2Ldap.class);
LdapUtils ldapUtils;
public UserInfo2Ldap() {
}
@Override
public boolean create(UserInfo userInfo) throws Exception{
logger.info("create");
try {
Attributes attributes = new BasicAttributes();
attributes.put(new BasicAttribute("objectClass","inetOrgPerson"));
attributes.put(new BasicAttribute("uid",userInfo.getUsername()));
attributes.put(new BasicAttribute("userPassword",ReciprocalUtils.decoder(userInfo.getDecipherable())));
attributes.put(new BasicAttribute("displayName",userInfo.getDisplayName()));
attributes.put(new BasicAttribute("cn",userInfo.getDisplayName()));
attributes.put(new BasicAttribute("givenName",userInfo.getGivenName()));
attributes.put(new BasicAttribute("sn",userInfo.getFamilyName()));
attributes.put(new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"":userInfo.getWorkPhoneNumber()));
attributes.put(new BasicAttribute("mail",userInfo.getWorkEmail()==null?"":userInfo.getWorkEmail()));
attributes.put(new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"":userInfo.getEmployeeNumber()));
attributes.put(new BasicAttribute("ou",userInfo.getDepartment()==null?"":userInfo.getDepartment()));
String managerDn="uid=dummy";
if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
}else{
UserInfo queryManager=new UserInfo();
queryManager.setId(userInfo.getManagerId());
UserInfo manager=loadUser(queryManager);
managerDn="uid="+manager.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
}
attributes.put(new BasicAttribute("manager",managerDn));
attributes.put(new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"":userInfo.getDepartmentId()));
attributes.put(new BasicAttribute("title",userInfo.getJobTitle()==null?"":userInfo.getJobTitle()));
String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().createSubcontext(dn, attributes);
ldapUtils.close();
super.create(userInfo);
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean update(UserInfo userInfo) throws Exception{
logger.info("update");
try {
SearchControls constraints = new SearchControls();
constraints.setSearchScope(ldapUtils.getSearchScope());
NamingEnumeration<SearchResult> results = ldapUtils.getConnection()
.search(ldapUtils.getBaseDN(), "(&(objectClass=inetOrgPerson)(uid="+userInfo.getUsername()+"))", constraints);
if (results == null || !results.hasMore()) {
return create(loadUser(userInfo));
}
ModificationItem[] modificationItems = new ModificationItem[10];
modificationItems[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("displayName",userInfo.getDisplayName()));
modificationItems[1]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("cn",userInfo.getDisplayName()));
modificationItems[2]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("givenName",userInfo.getGivenName()));
modificationItems[3]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("sn",userInfo.getFamilyName()));
modificationItems[4]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mobile",userInfo.getWorkPhoneNumber()==null?"":userInfo.getWorkPhoneNumber()));
modificationItems[5]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("mail",userInfo.getWorkEmail()==null?"":userInfo.getWorkEmail()));
modificationItems[6]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("employeeNumber",userInfo.getEmployeeNumber()==null?"":userInfo.getEmployeeNumber()));
modificationItems[7]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("ou",userInfo.getDepartment()==null?"":userInfo.getDepartment()));
modificationItems[8]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("departmentNumber",userInfo.getDepartmentId()==null?"":userInfo.getDepartmentId()));
modificationItems[9]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("title",userInfo.getJobTitle()==null?"":userInfo.getJobTitle()));
String managerDn="uid=dummy";
if(userInfo.getManagerId()==null||userInfo.getManagerId().equals("")){
}else{
UserInfo queryManager=new UserInfo();
queryManager.setId(userInfo.getManagerId());
UserInfo manager=loadUser(queryManager);
managerDn="uid="+manager.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
}
modificationItems[9]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,new BasicAttribute("manager",managerDn));
String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().modifyAttributes(dn, modificationItems);
ldapUtils.close();
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
@Override
public boolean delete(UserInfo userInfo) throws Exception{
logger.info("delete");
try {
String dn="uid="+userInfo.getUsername()+",dc=users,"+ldapUtils.getBaseDN();
ldapUtils.getCtx().destroySubcontext(dn);
ldapUtils.close();
super.delete(userInfo);
} catch (NamingException e) {
e.printStackTrace();
}
return true;
}
public UserInfo loadUser(UserInfo UserInfo) {
return null;
}
}

View File

@ -0,0 +1,47 @@
#spring.profiles.active=dev
#application
application.title=MaxKey-Connector-LDAP
application.name=MaxKey-Connector-LDAP
application.formatted-version=v2.0.0 GA
#server port
server.port=9601
#datasource
spring.datasource.username=root
spring.datasource.password=maxkey
spring.datasource.url=jdbc:mysql://localhost/maxkey?autoReconnect=true&characterEncoding=UTF-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.kafka.bootstrap-servers=localhost:9092
###########【初始化消费者配置】###########
# 默认的消费组ID
spring.kafka.consumer.properties.group.id=test-consumer-group
# 是否自动提交offset
spring.kafka.consumer.enable-auto-commit=true
# 提交offset延时(接收到消息后多久提交offset)
spring.kafka.consumer.auto.commit.interval.ms=1000
# 当kafka中没有初始offset或offset超出范围时将自动重置offset
# earliest:重置为分区中最小的offset;
# latest:重置为分区中最新的offset(消费分区中新产生的数据);
# none:只要有一个分区不存在已提交的offset,就抛出异常;
spring.kafka.consumer.auto-offset-reset=latest
# 消费会话超时时间(超过这个时间consumer没有发送心跳,就会触发rebalance操作)
spring.kafka.consumer.properties.session.timeout.ms=120000
# 消费请求超时时间
spring.kafka.consumer.properties.request.timeout.ms=180000
# Kafka提供的序列化和反序列化类
spring.kafka.consumer.key-deserializer=org.apache.kafka.common.serialization.StringDeserializer
spring.kafka.consumer.value-deserializer=org.apache.kafka.common.serialization.StringDeserializer
# 消费端监听的topic不存在时项目启动会报错(关掉)
spring.kafka.listener.missing-topics-fatal=false
# 设置批量消费
# spring.kafka.listener.type=batch
# 批量消费每次最多消费多少条消息
# spring.kafka.consumer.max-poll-records=50
config.connector.ldap.providerUrl=ldap://
config.connector.ldap.principal=maxkey
config.connector.ldap.credentials=maxkey
config.connector.ldap.baseDN=dc=maxkey,dc=top

View File

@ -52,6 +52,9 @@ public class ApplicationConfig {
@Value("${server.port:8080}")
private int port;
@Value("${config.identity.kafkasupport:false}")
private boolean kafkaSupport;
public int getPort() {
return port;
}
@ -198,6 +201,14 @@ public class ApplicationConfig {
this.defaultUri = defaultUri;
}
public boolean isKafkaSupport() {
return kafkaSupport;
}
public void setKafkaSupport(boolean kafkaSupport) {
this.kafkaSupport = kafkaSupport;
}
/*
* public boolean isWhiteList() { return whiteList; }
*

View File

@ -1,4 +1,17 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -5,5 +5,5 @@ dependencies {
compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
compile project(":maxkey-core")
compile project(":maxkey-identitys:maxkey-identity-kafka")
}

View File

@ -3,11 +3,18 @@ package org.maxkey.dao.service;
import org.apache.mybatis.jpa.persistence.JpaBaseService;
import org.maxkey.dao.persistence.OrganizationsMapper;
import org.maxkey.domain.Organizations;
import org.maxkey.identity.kafka.KafkaIdentityAction;
import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.maxkey.identity.kafka.KafkaProvisioningService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrganizationsService extends JpaBaseService<Organizations>{
@Autowired
KafkaProvisioningService kafkaProvisioningService;
public OrganizationsService() {
super(OrganizationsMapper.class);
}
@ -21,4 +28,31 @@ public class OrganizationsService extends JpaBaseService<Organizations>{
return (OrganizationsMapper)super.getMapper();
}
public boolean insert(Organizations organization) {
if(super.insert(organization)){
kafkaProvisioningService.send(
KafkaIdentityTopic.ORG_TOPIC, organization, KafkaIdentityAction.CREATE_ACTION);
return true;
}
return false;
}
public boolean update(Organizations organization) {
if(super.update(organization)){
kafkaProvisioningService.send(
KafkaIdentityTopic.ORG_TOPIC, organization, KafkaIdentityAction.UPDATE_ACTION);
return true;
}
return false;
}
public boolean delete(Organizations organization) {
if(super.delete(organization)){
kafkaProvisioningService.send(
KafkaIdentityTopic.ORG_TOPIC, organization, KafkaIdentityAction.DELETE_ACTION);
return true;
}
return false;
}
}

View File

@ -8,6 +8,9 @@ import org.maxkey.crypto.password.PasswordReciprocal;
import org.maxkey.dao.persistence.UserInfoMapper;
import org.maxkey.domain.ChangePassword;
import org.maxkey.domain.UserInfo;
import org.maxkey.identity.kafka.KafkaIdentityAction;
import org.maxkey.identity.kafka.KafkaIdentityTopic;
import org.maxkey.identity.kafka.KafkaProvisioningService;
import org.maxkey.util.DateUtils;
import org.maxkey.util.StringUtils;
import org.maxkey.web.WebContext;
@ -29,6 +32,8 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
KafkaProvisioningService kafkaProvisioningService;
public UserInfoService() {
super(UserInfoMapper.class);
@ -46,22 +51,27 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
public boolean insert(UserInfo userInfo) {
userInfo = passwordEncoder(userInfo);
if (super.insert(userInfo)) {
kafkaProvisioningService.send(
KafkaIdentityTopic.USERINFO_TOPIC, userInfo, KafkaIdentityAction.CREATE_ACTION);
return true;
}
return false;
}
public boolean update(UserInfo userinfo) {
if(super.update(userinfo)){
public boolean update(UserInfo userInfo) {
if(super.update(userInfo)){
kafkaProvisioningService.send(
KafkaIdentityTopic.USERINFO_TOPIC, userInfo, KafkaIdentityAction.UPDATE_ACTION);
return true;
}
return false;
}
public boolean delete(UserInfo userinfo) {
if( super.delete(userinfo)){
public boolean delete(UserInfo userInfo) {
if( super.delete(userInfo)){
kafkaProvisioningService.send(
KafkaIdentityTopic.USERINFO_TOPIC, userInfo, KafkaIdentityAction.DELETE_ACTION);
return true;
}
return false;
@ -130,6 +140,8 @@ public class UserInfoService extends JpaBaseService<UserInfo> {
changePassword.setUsername(userInfo.getUsername());
changePassword.setDecipherable(userInfo.getDecipherable());
changePassword.setPassword(userInfo.getPassword());
kafkaProvisioningService.send(
KafkaIdentityTopic.PASSWORD_TOPIC, changePassword, KafkaIdentityAction.PASSWORD_ACTION);
return true;
}
return false;

View File

@ -15,6 +15,11 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="bin/main" path="src/main/java">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/main" path="src/main/resources">
<attributes>
<attribute name="gradle_scope" value="main"/>
<attribute name="gradle_used_by_scope" value="main,test"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/java">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="bin/test" path="src/test/resources">
<attributes>
<attribute name="gradle_scope" value="test"/>
<attribute name="gradle_used_by_scope" value="test"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8/"/>
<classpathentry kind="con" path="org.eclipse.buildship.core.gradleclasspathcontainer">
<attributes>
<attribute name="org.eclipse.jst.component.nondependency" value=""/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin/default"/>
</classpath>

View File

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>maxkey-identity-kafka</name>
<comment>Project maxkey-identity-kafka created by Buildship.</comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.common.project.facet.core.builder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.wst.validation.validationbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
<nature>org.eclipse.wst.common.project.facet.core.nature</nature>
<nature>org.eclipse.wst.common.modulecore.ModuleCoreNature</nature>
<nature>org.eclipse.jem.workbench.JavaEMFNature</nature>
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
</natures>
</projectDescription>

View File

@ -0,0 +1,2 @@
connection.project.dir=../..
eclipse.preferences.version=1

View File

@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@ -0,0 +1,116 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.annotation.inheritNullAnnotations=disabled
org.eclipse.jdt.core.compiler.annotation.missingNonNullByDefaultAnnotation=ignore
org.eclipse.jdt.core.compiler.annotation.nonnull=org.eclipse.jdt.annotation.NonNull
org.eclipse.jdt.core.compiler.annotation.nonnull.secondary=
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault=org.eclipse.jdt.annotation.NonNullByDefault
org.eclipse.jdt.core.compiler.annotation.nonnullbydefault.secondary=
org.eclipse.jdt.core.compiler.annotation.nullable=org.eclipse.jdt.annotation.Nullable
org.eclipse.jdt.core.compiler.annotation.nullable.secondary=
org.eclipse.jdt.core.compiler.annotation.nullanalysis=disabled
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.compiler.problem.APILeak=warning
org.eclipse.jdt.core.compiler.problem.annotatedTypeArgumentToUnannotated=info
org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
org.eclipse.jdt.core.compiler.problem.comparingIdentical=warning
org.eclipse.jdt.core.compiler.problem.deadCode=warning
org.eclipse.jdt.core.compiler.problem.deprecation=warning
org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
org.eclipse.jdt.core.compiler.problem.explicitlyClosedAutoCloseable=ignore
org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
org.eclipse.jdt.core.compiler.problem.includeNullInfoFromAsserts=disabled
org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
org.eclipse.jdt.core.compiler.problem.nonnullParameterAnnotationDropped=warning
org.eclipse.jdt.core.compiler.problem.nonnullTypeVariableFromLegacyInvocation=warning
org.eclipse.jdt.core.compiler.problem.nullAnnotationInferenceConflict=error
org.eclipse.jdt.core.compiler.problem.nullReference=warning
org.eclipse.jdt.core.compiler.problem.nullSpecViolation=error
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
org.eclipse.jdt.core.compiler.problem.pessimisticNullAnalysisForFreeTypeVariables=warning
org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=ignore
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBeStatic=ignore
org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
org.eclipse.jdt.core.compiler.problem.suppressWarningsNotFullyAnalysed=info
org.eclipse.jdt.core.compiler.problem.syntacticNullAnalysisForFields=disabled
org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
org.eclipse.jdt.core.compiler.problem.terminalDeprecation=warning
org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
org.eclipse.jdt.core.compiler.problem.unavoidableGenericTypeProblems=enabled
org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning
org.eclipse.jdt.core.compiler.problem.unclosedCloseable=warning
org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentType=warning
org.eclipse.jdt.core.compiler.problem.unlikelyCollectionMethodArgumentTypeStrict=disabled
org.eclipse.jdt.core.compiler.problem.unlikelyEqualsArgumentType=info
org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
org.eclipse.jdt.core.compiler.problem.unstableAutoModuleName=warning
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
org.eclipse.jdt.core.compiler.problem.unusedExceptionParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedImport=warning
org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
org.eclipse.jdt.core.compiler.problem.unusedTypeParameter=ignore
org.eclipse.jdt.core.compiler.problem.unusedWarningToken=warning
org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<project-modules id="moduleCoreId" project-version="1.5.0">
<wb-module deploy-name="maxkey-identity-kafka">
<wb-resource deploy-path="/" source-path="src/main/resources"/>
<wb-resource deploy-path="/" source-path="src/main/java"/>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-core/maxkey-core">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-dao/maxkey-dao">
<dependency-type>uses</dependency-type>
</dependent-module>
<dependent-module deploy-path="../" handle="module:/resource/maxkey-client-sdk/maxkey-client-sdk">
<dependency-type>uses</dependency-type>
</dependent-module>
</wb-module>
</project-modules>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<faceted-project>
<fixed facet="jst.java"/>
<installed facet="jst.utility" version="1.0"/>
<installed facet="jst.java" version="1.8"/>
</faceted-project>

View File

@ -0,0 +1,2 @@
boot.validation.initialized=true
eclipse.preferences.version=1

View File

@ -0,0 +1,15 @@
description = "maxkey-identity-kafka"
apply plugin: 'java'
apply plugin: 'eclipse-wtp'
dependencies {
//local jars
compile fileTree(dir: '../maxkey-lib/*/', include: '*.jar')
compile project(":maxkey-core")
compile project(":maxkey-dao")
compile project(":maxkey-client-sdk")
}

View File

@ -0,0 +1,10 @@
package org.maxkey.identity.kafka;
public class KafkaIdentityAction {
public static String CREATE_ACTION = "CREATE_ACTION";
public static String DELETE_ACTION = "DELETE_ACTION";
public static String UPDATE_ACTION = "UPDATE_ACTION";
public static String PASSWORD_ACTION = "PASSWORD_ACTION";
}

View File

@ -0,0 +1,11 @@
package org.maxkey.identity.kafka;
public class KafkaIdentityTopic {
public final static String USERINFO_TOPIC = "IDENTITY_USERINFO_TOPIC";
public final static String ORG_TOPIC = "IDENTITY_ORG_TOPIC";
public final static String GROUP_TOPIC = "IDENTITY_GROUP_TOPIC";
public final static String PASSWORD_TOPIC = "IDENTITY_PASSWORD_TOPIC";
}

View File

@ -0,0 +1,42 @@
package org.maxkey.identity.kafka;
public class KafkaMessage {
String topic;
String actionType;
String sendTime;
String msgId;
String content;
public String getTopic() {
return topic;
}
public void setTopic(String topic) {
this.topic = topic;
}
public String getActionType() {
return actionType;
}
public void setActionType(String actionType) {
this.actionType = actionType;
}
public String getSendTime() {
return sendTime;
}
public void setSendTime(String sendTime) {
this.sendTime = sendTime;
}
public String getMsgId() {
return msgId;
}
public void setMsgId(String msgId) {
this.msgId = msgId;
}
public Object getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public KafkaMessage() {
}
}

View File

@ -0,0 +1,48 @@
package org.maxkey.identity.kafka;
import java.util.UUID;
import org.maxkey.config.ApplicationConfig;
import org.maxkey.util.DateUtils;
import org.maxkey.util.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Component;
@Component
public class KafkaProvisioningService {
private static final Logger _logger = LoggerFactory.getLogger(KafkaProvisioningService.class);
@Autowired
protected ApplicationConfig applicationConfig;
@Autowired
protected KafkaTemplate<String, String> kafkaTemplate;
public void setApplicationConfig(ApplicationConfig applicationConfig) {
this.applicationConfig = applicationConfig;
}
public void setKafkaTemplate(KafkaTemplate<String, String> kafkaTemplate) {
this.kafkaTemplate = kafkaTemplate;
}
public void send(String topic,Object content,String actionType) {
if(applicationConfig.isKafkaSupport()) {
KafkaMessage message = new KafkaMessage();
message.setMsgId(UUID.randomUUID().toString());
message.setActionType(actionType);
message.setTopic(topic);
message.setSendTime(DateUtils.getCurrentDateTimeAsString());
message.setContent(JsonUtils.gson2Json(content));
String msg = JsonUtils.gson2Json(message);
_logger.info("send message = {}", msg);
kafkaTemplate.send(topic, msg);
}
}
}

View File

@ -0,0 +1,14 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

View File

@ -1,4 +1,17 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
org.eclipse.jdt.core.builder.duplicateResourceTask=warning
org.eclipse.jdt.core.builder.invalidClasspath=abort
org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch
org.eclipse.jdt.core.circularClasspath=warning
org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
org.eclipse.jdt.core.classpath.mainOnlyProjectHasTestOnlyDependency=error
org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
org.eclipse.jdt.core.classpath.outputOverlappingAnotherSource=error
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
org.eclipse.jdt.core.compiler.compliance=1.8
org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
org.eclipse.jdt.core.compiler.source=1.8
org.eclipse.jdt.core.incompatibleJDKLevel=ignore
org.eclipse.jdt.core.incompleteClasspath=error

View File

@ -0,0 +1,3 @@
eclipse.preferences.version=1
org.eclipse.jdt.launching.PREF_COMPILER_COMPLIANCE_DOES_NOT_MATCH_JRE=warning
org.eclipse.jdt.launching.PREF_STRICTLY_COMPATIBLE_JRE_NOT_AVAILABLE=warning

View File

@ -10,6 +10,7 @@
<project>maxkey-client-sdk</project>
<project>maxkey-protocol-oauth-2.0</project>
<project>maxkey-protocol-saml-2.0</project>
<project>maxkey-identity-scim</project>
</projects>
<buildSpec>
<buildCommand>

View File

@ -23,6 +23,7 @@ dependencies {
compile project(":maxkey-protocols:maxkey-protocol-oauth-2.0")
compile project(":maxkey-protocols:maxkey-protocol-saml-2.0")
compile project(":maxkey-identitys:maxkey-identity-scim")
compile project(":maxkey-identitys:maxkey-identity-kafka")
}

View File

@ -34,6 +34,7 @@ import org.springframework.context.annotation.ImportResource;
"org.maxkey.dao",
"org.maxkey.web",
"org.maxkey.web.tag",
"org.maxkey.identity.kafka",
"org.maxkey.identity.scim.controller"
})
@MapperScan("org.maxkey.dao.persistence,")

View File

@ -60,3 +60,25 @@ spring.messages.encoding=UTF-8
#main
spring.main.banner-mode=log
spring.main.allow-bean-definition-overriding=true
###########【Kafka集群】###########
spring.kafka.bootstrap-servers=localhost:9092
###########【初始化生产者配置】###########
# 重试次数
spring.kafka.producer.retries=0
# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
spring.kafka.producer.acks=1
# 批量大小
spring.kafka.producer.batch-size=16384
# 提交延时
spring.kafka.producer.properties.linger.ms=0
# 当生产端积累的消息达到batch-size或接收到消息linger.ms后,生产者就会将消息提交给kafka
# linger.ms为0表示每接收到一条消息就提交给kafka,这时候batch-size其实就没用了
# 生产端缓冲区大小
spring.kafka.producer.buffer-memory = 33554432
# Kafka提供的序列化和反序列化类
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
# 自定义分区器
# spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner

View File

@ -11,6 +11,8 @@ config.server.default.uri=${config.server.prefix.uri}/main
config.maxkey.uri=${config.server.name}/maxkey
#InMemory 0 , jdbc 1, Redis 2
config.server.persistence=0
#identity
config.identity.kafkasupport=true
############################################################################
# Login configuration
#enable captcha

View File

@ -68,3 +68,25 @@ spring.messages.encoding=UTF-8
#main
spring.main.banner-mode=log
spring.main.allow-bean-definition-overriding=true
###########【Kafka集群】###########
spring.kafka.bootstrap-servers=localhost:9092
###########【初始化生产者配置】###########
# 重试次数
spring.kafka.producer.retries=0
# 应答级别:多少个分区副本备份完成时向生产者发送ack确认(可选0、1、all/-1)
spring.kafka.producer.acks=1
# 批量大小
spring.kafka.producer.batch-size=16384
# 提交延时
spring.kafka.producer.properties.linger.ms=0
# 当生产端积累的消息达到batch-size或接收到消息linger.ms后,生产者就会将消息提交给kafka
# linger.ms为0表示每接收到一条消息就提交给kafka,这时候batch-size其实就没用了
# 生产端缓冲区大小
spring.kafka.producer.buffer-memory = 33554432
# Kafka提供的序列化和反序列化类
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.apache.kafka.common.serialization.StringSerializer
# 自定义分区器
# spring.kafka.producer.properties.partitioner.class=com.felix.kafka.producer.CustomizePartitioner

View File

@ -11,6 +11,9 @@ config.server.default.uri=${config.server.prefix.uri}/maxkey/appList
config.server.management.uri=${config.server.name}:9521/maxkey-mgt/login
#InMemory 0 , jdbc 1, Redis 2
config.server.persistence=0
#identity
config.identity.kafkasupport=false
config.app.issuer=CN=ConSec,CN=COM,CN=SH
############################################################################
# Login configuration

View File

@ -11,6 +11,13 @@ include 'maxkey-authentications'
//identity
include 'maxkey-identitys:maxkey-identity-scim'
include 'maxkey-identitys:maxkey-identity-kafka'
//connectors
include 'maxkey-connectors:maxkey-connector-base'
include 'maxkey-connectors:maxkey-connector-ldap'
include 'maxkey-connectors:maxkey-connector-activedirectory'
//Protocol
//include 'maxkey-protocols'