ldap 인증
다음은 정확하고 통용되는 절차입니다. 1.클라이언트로부터 로그인 이름과 비밀번호를 얻습니다.이곳의 로그인 이름과 비밀번호는 처음에는 사용되지 않았음을 주의하십시오.
2.먼저 익명으로 LDAP 서버에 연결합니다. 만약 LDAP 서버가 익명 연결을 사용하지 않았다면, 보통 기본 사용자를 제공할 것입니다. 이 사용자로 연결을 하면 됩니다.
3.이전에 입력한 로그인 이름은 여기에서 유용합니다. 마지막 귀속이 성공한 후에 검색을 실행해야 합니다. 필터는 로그인 이름으로 구성됩니다. 예를 들어 "(| (uid=$login) (mail=$login)"는 로그인 이름입니다.검색이 끝난 후에 결과에 대한 판단이 필요합니다. 만약에 하나의 entry만 되돌려준다면 이것은 이 사용자 정보를 포함하는 entry입니다. 이 entry의 DN을 얻어 다음에 사용할 수 있습니다.만약 되돌아오는 것이 한 개가 아니거나 돌아오지 않았다면 사용자 이름 입력이 틀렸다는 것을 설명할 수 있습니다. 검증을 끝내고 오류 정보를 되돌려야 합니다.
4.이 단계까지 진행할 수 있다면 상응하는 사용자를 사용하고 이전 단계에서 사용자 정보가 있는 entry의 DN을 얻었다는 것을 설명합니다. 이 DN과 첫 번째 단계에서 얻은 패스워드로 LDAP 서버를 다시 연결해야 합니다.
5.이전 단계를 실행하면 검증의 주요 과정이 끝납니다. 만약에 연결에 성공할 수 있다면 검증에 성공했고 안 되면 비밀번호 오류 정보를 되돌려야 합니다.
이 5가지 단계는 LDAP 기반의 "2회 바인딩"검증 방법입니다.
왜 LDAP를 기반으로 검증을 하려면'두 번'귀속이 필요합니까? 왜 password를 꺼내서 입력과 비교할 수 없습니까? 생각해 보세요. 비밀번호를 읽으려면 서버에 있는 비밀번호가 암호화되지 않거나 바로 읽을 수 있습니다. 고객이 서버에서 사용하는 암호화 방식을 알아야 합니다. 이것은 안전하지 않고 좋지 않습니다. 서버가 암호화 방식을 클라이언트에게 알려주기를 원하지 않습니다.클라이언트도 이렇게 많은 것을 알 필요가 없다.실제적으로 볼 때 LDAP 서버는password 속성에 대해 기본적으로 읽을 수 없습니다. 심지어 어떤 서버는password 속성을 읽을 수 있는 것을 지원하지 않습니다. 이런 상황에 부닥치면 비밀번호를 얻을 수 없습니다.
또 하나의 문제는 왜 우리가 첫 번째 귀속을 필요로 하는가 하는 것이다.왜 DN을 직접 사용하지 않습니까? 우선 이 DN에 관해서는 일반적인 클라이언트 프로그램에 대해 구체적인 DN이 무엇인지 알 수 없습니다.게다가 사용자가 DN을 입력하게 하는 것은 사용자에게 불편을 주는 동시에 검증도 문제를 가져온다. 만약에 입력한 것이 원하는 DN이 아니라 디렉터리 트리라면 귀속을 할 때 서버에 예측할 수 없는 오류가 발생할 수 있기 때문이다.
위에서 볼 때 LDAP를 기반으로 인증을 하는 가장 좋은 방법과 가장 일반적인 방법은 바로'두 번 귀속'이다.이른바 귀속은authentication(신분 검증)의 과정이다. 이를'귀속'이라고 생각하지 마라. 인증이라면 사용자 이름과 비밀번호가 필요하다. 오픈맵에서 제시한 사용자 이름과 비밀번호가 틀리면 서버는 익명 인증을 시도한다. 익명 ftp와 같다.물론 현실 설정에서 인증이 성공하지 않으면 조회 작업을 할 수 없습니다. 이것들은 slapd입니다.conf 파일에서 ACL 설정을 통해 이루어집니다.인증에 사용되는 사용자 이름과 비밀번호는 디렉터리 트리의 한 노드의 두 가지 속성 (사용자와 비밀번호) 이며, 일반적인 경우, 프로그램은 기본적으로 uid와userPassword 속성을 사용합니다.프로그램을 써서 인증할 때 이 노드의 두 가지 속성만 제공하면 된다.
ldap에서 흔히 볼 수 있는 명사 설명:
CN:commonname
객체의 속성은 CN입니다. 예를 들어 한 사용자의 이름이 장삼이라면 장삼은 하나의 CN입니다.
O:organizationName 조직명
OU: OrganizationUnit 조직 단위
o와 ou는 모두ldap 디렉터리 구조의 속성으로 디렉터리를 만들 때 새 o, ou 등을 선택할 수 있습니다.당사 교환 장치ldap를 설정할 때 구체적으로ou,o,cn 등을 설정할 때ldap 서버의 상응하는 디렉터리가 어떤 속성인지 구체적으로 보아야 합니다.
UID: userid
대상의 속성은 uid입니다. 예를 들어 우리 회사의 한 직원의 이름은:zsq이고 그의 UID는:z02691입니다.ldap에서 조회할 때cn에 따라도 되고 uid에 따라도 됩니다.ldap 검색을 설정할 때 어떤 검색 방식을 사용할지 고려해야 합니다.구체적인 장치 설정은ldap 서버의 관련 설정에 따라 조회됩니다.
DC:Domain Component
DC는 dns의 모든 요소, 예를 들어 h3c와 유사하다.com,“.”기호가 분리된 두 단어는 두 개의 DC로 볼 수 있습니다.
DN:Distinguished Name
DNS와 유사하게 DN과 DNS의 차이점은 DN을 구성하는 각 값에는 다음과 같은 속성 유형이 있습니다.
H3c.com은 dns입니다. 그러면 dn으로:dc=h3c,dc=com의 등급이 높을수록 뒤에 있습니다.H3c와com의 속성은 모두 DC입니다.
DN은ldap의 어떤 디렉터리를 표시할 수도 있고, 디렉터리의 어떤 대상을 표시할 수도 있으며, 이 대상은 사용자 등이 될 수도 있다.
다음은 간단한ldap 인증 프로세스 코드입니다.
import org.junit.Before;
import org.junit.Test;
import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.Control;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import javax.xml.bind.PropertyException;
import java.util.*;
public class LdapTest {
private final String PROPERTIES_SCOPE = "ldap";
private final String FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
private String url = "ldap://192.168.30.254:389";
private String base = "1";
private LdapContext ctx = null;
private Control[] connCtls = null;
public static LdapContext ctx = null;
private final Control[] connCtls = null;
@Test
public void testUser() {
connLDAP();
List list = getUser("users");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
System.out.println("ending");
}
@Test
public void test() {
connLDAP();
}
public boolean connLDAP() {
Hashtable env = new Hashtable<>();
env.put(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
env.put(Context.PROVIDER_URL, url);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, ldapUserDn);
env.put(Context.SECURITY_CREDENTIALS, ldapPassword);
try {
ctx = new InitialLdapContext(env, connCtls);
System.out.println(" !");
return Boolean.TRUE;
} catch (javax.naming.AuthenticationException e) {
System.out.println(" :");
e.printStackTrace();
return Boolean.FALSE;
} catch (Exception e) {
System.out.println(" : ");
e.printStackTrace();
return Boolean.FALSE;
} finally {
close();
}
}
public void close() {
if (ctx != null) {
try {
ctx.close();
System.out.println(" ");
} catch (NamingException e) {
e.printStackTrace();
}
}
}
public List getUser(String uname) {
List users = new ArrayList<>();
HashMap map = new HashMap<>();
SearchControls searchCtls = new SearchControls();
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// ,
String searchFilter = "(&(cn=" + uname + ")(objectClass=person))";
String searchBase = "DC=maxcrc,DC=com";
//
String[] returnedAtts = {"mail", "cn", "userPassword", "sn", "uid"};
searchCtls.setReturningAttributes(returnedAtts);
NamingEnumeration answer;
Map mmap = new HashMap<>();
try {
answer = ctx.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
String name = sr.getName();
User user = new User();
if (name.contains("cn") || name.contains("uid")) {
String[] s = name.split(",");
String[] cns = s[0].split("=");
String cn = cns[cns.length - 1];
mmap.put(cn, sr.getNameInNamespace());
NamingEnumeration extends Attribute> attrs = sr.getAttributes().getAll();
while (attrs.hasMore()) {
Attribute attr = attrs.next();
switch (attr.getID()) {
case "cn":
user.setCn(attr.get().toString());
break;
case "sn":
user.setSn(attr.get().toString());
break;
case "mail":
user.setMail(attr.get().toString());
break;
case "uid":
user.setUid(attr.get().toString());
break;
case "userPassword":
user.setPassword(attr.get().toString());
break;
}
}
users.add(user);
}
}
} catch (NamingException e) {
e.printStackTrace();
}
mmap.forEach((k, v) -> System.out.println("key : value = " + k + ":" + v));
return users;
}
}
public class User {
private String cn;
private String sn;
private String mail;
private String uid;
private String password;
public String getCn() {
return cn;
}
public void setCn(String cn) {
this.cn = cn;
}
public String getSn() {
return sn;
}
public void setSn(String sn) {
this.sn = sn;
}
public String getMail() {
return mail;
}
public void setMail(String mail) {
this.mail = mail;
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"cn='" + cn + '\'' +
", sn='" + sn + '\'' +
", mail='" + mail + '\'' +
", uid='" + uid + '\'' +
", password='" + password + '\'' +
'}';
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.