Merge pull request #442 from Huyueeer/devLookUserName

LDAP忽略大小写 & 认证携带必要元信息(姓名、部门、邮箱)
This commit is contained in:
EricZeng
2022-01-18 15:26:32 +08:00
committed by GitHub
9 changed files with 142 additions and 21 deletions

View File

@@ -16,6 +16,9 @@ CREATE TABLE `account` (
`status` int(16) NOT NULL DEFAULT '0' COMMENT '0标识使用中-1标识已废弃', `status` int(16) NOT NULL DEFAULT '0' COMMENT '0标识使用中-1标识已废弃',
`gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', `gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`gmt_modify` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间', `gmt_modify` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`department` varchar(128) DEFAULT '' COMMENT '部门名',
`display_name` varchar(128) DEFAULT '' COMMENT '用户姓名',
`mail` varchar(128) DEFAULT '' COMMENT '邮箱',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `uniq_username` (`username`) UNIQUE KEY `uniq_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='账号表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='账号表';

View File

@@ -21,6 +21,15 @@ public class AccountDTO {
@ApiModelProperty(value = "角色") @ApiModelProperty(value = "角色")
private Integer role; private Integer role;
@ApiModelProperty(value = "用户姓名")
private String displayName;
@ApiModelProperty(value = "部门")
private String department;
@ApiModelProperty(value = "邮箱")
private String mail;
public String getUsername() { public String getUsername() {
return username; return username;
} }
@@ -45,12 +54,39 @@ public class AccountDTO {
this.role = role; this.role = role;
} }
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
@Override @Override
public String toString() { public String toString() {
return "AccountDTO{" + return "AccountDTO{" +
"username='" + username + '\'' + "username='" + username + '\'' +
", password='" + password + '\'' + ", password='" + password + '\'' +
", role=" + role + ", role=" + role +
", displayName='" + displayName + '\'' +
", department='" + department + '\'' +
", mail='" + mail + '\'' +
'}'; '}';
} }

View File

@@ -21,6 +21,12 @@ public class AccountDO {
private Integer role; private Integer role;
private String displayName;
private String department;
private String mail;
public String getUsername() { public String getUsername() {
return username; return username;
} }
@@ -45,16 +51,43 @@ public class AccountDO {
this.role = role; this.role = role;
} }
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
@Override @Override
public String toString() { public String toString() {
return "AccountDO{" + return "AccountDO{" +
"username='" + username + '\'' + "id=" + id +
", password='" + password + '\'' +
", role=" + role +
", id=" + id +
", status=" + status + ", status=" + status +
", gmtCreate=" + gmtCreate + ", gmtCreate=" + gmtCreate +
", gmtModify=" + gmtModify + ", gmtModify=" + gmtModify +
", username='" + username + '\'' +
", password='" + password + '\'' +
", role=" + role +
", displayName='" + displayName + '\'' +
", department='" + department + '\'' +
", mail='" + mail + '\'' +
'}'; '}';
} }
} }

View File

@@ -0,0 +1,14 @@
package com.xiaojukeji.kafka.manager.common.utils;
/**
* @className: SplitUtils
* @description: Split string of type keyValue
* @author: Hu.Yue
* @date: 2021/8/4
**/
public class SplitUtils {
public static String keyValueSplit(String keyValue){
return keyValue.split(":\\s+")[1];
}
}

View File

@@ -10,14 +10,17 @@
<result property="role" column="role" /> <result property="role" column="role" />
<result property="gmtCreate" column="gmt_create" /> <result property="gmtCreate" column="gmt_create" />
<result property="gmtModify" column="gmt_modify" /> <result property="gmtModify" column="gmt_modify" />
<result property="displayName" column="display_name" />
<result property="department" column="department" />
<result property="mail" column="mail" />
</resultMap> </resultMap>
<insert id="insert" parameterType="com.xiaojukeji.kafka.manager.common.entity.pojo.AccountDO"> <insert id="insert" parameterType="com.xiaojukeji.kafka.manager.common.entity.pojo.AccountDO">
<![CDATA[ <![CDATA[
REPLACE account REPLACE account
(username, password, role) (username, password, role, display_name, department, mail)
VALUES VALUES
(#{username}, #{password}, #{role}) (#{username}, #{password}, #{role}, #{displayName}, #{department}, #{mail})
]]> ]]>
</insert> </insert>

View File

@@ -54,7 +54,8 @@ public class BaseEnterpriseStaffService extends AbstractEnterpriseStaffService {
} }
List<EnterpriseStaff> staffList = new ArrayList<>(); List<EnterpriseStaff> staffList = new ArrayList<>();
for (AccountDO accountDO: doList) { for (AccountDO accountDO: doList) {
staffList.add(new EnterpriseStaff(accountDO.getUsername(), accountDO.getUsername(), "")); //这里对chineseName填充共识的displayNameDepartment则获取Department信息
staffList.add(new EnterpriseStaff(accountDO.getUsername(), accountDO.getDisplayName(), accountDO.getDepartment()));
} }
return staffList; return staffList;
} catch (Exception e) { } catch (Exception e) {

View File

@@ -1,5 +1,6 @@
package com.xiaojukeji.kafka.manager.account.component.ldap; package com.xiaojukeji.kafka.manager.account.component.ldap;
import com.xiaojukeji.kafka.manager.common.utils.SplitUtils;
import com.xiaojukeji.kafka.manager.common.utils.ValidateUtils; import com.xiaojukeji.kafka.manager.common.utils.ValidateUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -14,7 +15,9 @@ import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult; import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext; import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext; import javax.naming.ldap.LdapContext;
import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.Map;
@Component @Component
public class LdapAuthentication { public class LdapAuthentication {
@@ -60,8 +63,11 @@ public class LdapAuthentication {
return null; return null;
} }
private String getUserDN(String account, LdapContext ctx) { private Map<String, Object> getLdapAttrsInfo(String account, LdapContext ctx) {
//存储更多的LDAP元信息
Map<String, Object> ldapAttrsInfo = new HashMap<>();
String userDN = ""; String userDN = "";
ldapAttrsInfo.clear();
try { try {
SearchControls constraints = new SearchControls(); SearchControls constraints = new SearchControls();
constraints.setSearchScope(SearchControls.SUBTREE_SCOPE); constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
@@ -69,7 +75,7 @@ public class LdapAuthentication {
NamingEnumeration<SearchResult> en = ctx.search("", filter, constraints); NamingEnumeration<SearchResult> en = ctx.search("", filter, constraints);
if (en == null || !en.hasMoreElements()) { if (en == null || !en.hasMoreElements()) {
return ""; return null;
} }
// maybe more than one element // maybe more than one element
while (en.hasMoreElements()) { while (en.hasMoreElements()) {
@@ -78,13 +84,25 @@ public class LdapAuthentication {
SearchResult si = (SearchResult) obj; SearchResult si = (SearchResult) obj;
userDN += si.getName(); userDN += si.getName();
userDN += "," + ldapBasedn; userDN += "," + ldapBasedn;
//携带LDAP更多元信息以填充用户元信息
ldapAttrsInfo.put("userDN", userDN);
ldapAttrsInfo.put("sAMAccountName",
SplitUtils.keyValueSplit(si.getAttributes().get("samaccountname").toString()));
ldapAttrsInfo.put("department",
SplitUtils.keyValueSplit(si.getAttributes().get("department").toString()));
ldapAttrsInfo.put("company",
SplitUtils.keyValueSplit(si.getAttributes().get("company").toString()));
ldapAttrsInfo.put("displayName",
SplitUtils.keyValueSplit(si.getAttributes().get("displayname").toString()));
ldapAttrsInfo.put("mail",
SplitUtils.keyValueSplit(si.getAttributes().get("mail").toString()));
break; break;
} }
} }
} catch (Exception e) { } catch (Exception e) {
LOGGER.error("class=LdapAuthentication||method=getUserDN||account={}||errMsg={}", account, e); LOGGER.error("class=LdapAuthentication||method=getUserDN||account={}||errMsg={}", account, e);
} }
return userDN; return ldapAttrsInfo;
} }
/** /**
@@ -93,23 +111,23 @@ public class LdapAuthentication {
* @param password * @param password
* @return * @return
*/ */
public boolean authenticate(String account, String password) { public Map<String, Object> authenticate(String account, String password) {
LdapContext ctx = getLdapContext(); LdapContext ctx = getLdapContext();
if (ValidateUtils.isNull(ctx)) { if (ValidateUtils.isNull(ctx)) {
return false; return null;
} }
try { try {
String userDN = getUserDN(account, ctx); Map<String, Object> ldapAttrsInfo = getLdapAttrsInfo(account, ctx);
if(ValidateUtils.isBlank(userDN)){ if(ValidateUtils.isNull(ldapAttrsInfo)){
return false; return null;
} }
ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, userDN); ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, ldapAttrsInfo.get("userDN").toString());
ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password); ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, password);
ctx.reconnect(null); ctx.reconnect(null);
return true; return ldapAttrsInfo;
} catch (AuthenticationException e) { } catch (AuthenticationException e) {
LOGGER.warn("class=LdapAuthentication||method=authenticate||account={}||errMsg={}", account, e); LOGGER.warn("class=LdapAuthentication||method=authenticate||account={}||errMsg={}", account, e);
} catch (NamingException e) { } catch (NamingException e) {
@@ -125,6 +143,6 @@ public class LdapAuthentication {
} }
} }
} }
return false; return null;
} }
} }

View File

@@ -17,6 +17,7 @@ import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.util.Map;
/** /**
* @author zengqiao * @author zengqiao
@@ -47,15 +48,19 @@ public class BaseSessionSignOn extends AbstractSingleSignOn {
if (ValidateUtils.isBlank(dto.getUsername()) || ValidateUtils.isNull(dto.getPassword())) { if (ValidateUtils.isBlank(dto.getUsername()) || ValidateUtils.isNull(dto.getPassword())) {
return Result.buildFailure("Missing parameters"); return Result.buildFailure("Missing parameters");
} }
//先创建空对象看是在LDAP去做填充还是直接查表填充
Result<AccountDO> accountResult = accountService.getAccountDO(dto.getUsername()); Result<AccountDO> accountResult;
//判断是否激活了LDAP验证, 若激活则也可使用ldap进行认证 //判断是否激活了LDAP验证, 若激活则也可使用ldap进行认证
if(!ValidateUtils.isNull(accountLdapEnabled) && accountLdapEnabled){ if(!ValidateUtils.isNull(accountLdapEnabled) && accountLdapEnabled){
//去LDAP验证账密 //去LDAP验证账密
if(!ldapAuthentication.authenticate(dto.getUsername(),dto.getPassword())){ Map<String, Object> ldapAttrsInfo = ldapAuthentication.authenticate(dto.getUsername(),dto.getPassword());;
if(ValidateUtils.isNull(ldapAttrsInfo)){
return Result.buildFrom(ResultStatus.LDAP_AUTHENTICATION_FAILED); return Result.buildFrom(ResultStatus.LDAP_AUTHENTICATION_FAILED);
} }
//LDAP验证通过拿LDAP的sAMAccountName替换dto对象的值便于第一次自动注册采用LDAP值并且第二次也避免REPLACE
dto.setUsername(ldapAttrsInfo.get("sAMAccountName").toString());
accountResult = accountService.getAccountDO(dto.getUsername());
if((ValidateUtils.isNull(accountResult) || ValidateUtils.isNull(accountResult.getData())) && authUserRegistration){ if((ValidateUtils.isNull(accountResult) || ValidateUtils.isNull(accountResult.getData())) && authUserRegistration){
//自动注册 //自动注册
@@ -63,11 +68,16 @@ public class BaseSessionSignOn extends AbstractSingleSignOn {
accountDO.setUsername(dto.getUsername()); accountDO.setUsername(dto.getUsername());
accountDO.setRole(AccountRoleEnum.getUserRoleEnum(authUserRegistrationRole).getRole()); accountDO.setRole(AccountRoleEnum.getUserRoleEnum(authUserRegistrationRole).getRole());
accountDO.setPassword(dto.getPassword()); accountDO.setPassword(dto.getPassword());
accountDO.setDisplayName(ldapAttrsInfo.get("displayName").toString());
accountDO.setDepartment(ldapAttrsInfo.get("department").toString());
accountDO.setMail(ldapAttrsInfo.get("mail").toString());
accountService.createAccount(accountDO); accountService.createAccount(accountDO);
} }
return Result.buildSuc(dto.getUsername()); return Result.buildSuc(dto.getUsername());
} }
//不走LDAP认证直接查表填充
accountResult = accountService.getAccountDO(dto.getUsername());
if (ValidateUtils.isNull(accountResult) || accountResult.failed()) { if (ValidateUtils.isNull(accountResult) || accountResult.failed()) {
return new Result<>(accountResult.getCode(), accountResult.getMessage()); return new Result<>(accountResult.getCode(), accountResult.getMessage());

View File

@@ -18,6 +18,9 @@ public class AccountConverter {
accountDO.setUsername(dto.getUsername()); accountDO.setUsername(dto.getUsername());
accountDO.setPassword(dto.getPassword()); accountDO.setPassword(dto.getPassword());
accountDO.setRole(dto.getRole()); accountDO.setRole(dto.getRole());
accountDO.setDepartment(dto.getDepartment());
accountDO.setMail(dto.getMail());
accountDO.setDisplayName(dto.getDisplayName());
return accountDO; return accountDO;
} }