Browse Source

spring-boot-demo-ldap 完成

pull/1/head
Yangkai.Shen 5 years ago
parent
commit
c1a74536a2
9 changed files with 147 additions and 176 deletions
  1. +69
    -104
      spring-boot-demo-ldap/README.md
  2. +1
    -1
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/api/Result.java
  3. +1
    -1
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/api/ResultCode.java
  4. +1
    -2
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/exception/ServiceException.java
  5. +0
    -23
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/repository/PersonRepository.java
  6. +10
    -6
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/service/PersonService.java
  7. +29
    -12
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/service/impl/PersonServiceImpl.java
  8. +23
    -22
      spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/util/LdapUtils.java
  9. +13
    -5
      spring-boot-demo-ldap/src/test/java/com/xkcoding/ldap/LdapDemoApplicationTests.java

+ 69
- 104
spring-boot-demo-ldap/README.md View File

@@ -1,6 +1,6 @@
# spring-boot-demo-ldap # spring-boot-demo-ldap


> 此 demo 主要演示了 Spring Boot 如何集成 `spring-boot-starter-data-ldap` 完成对 Ldap 的基本CURD操作, 并给出以登录为实战的api 示例
> 此 demo 主要演示了 Spring Boot 如何集成 `spring-boot-starter-data-ldap` 完成对 Ldap 的基本 CURD操作, 并给出以登录为实战的 API 示例


## docker openldap 安装步骤 ## docker openldap 安装步骤


@@ -18,7 +18,7 @@


## pom.xml ## pom.xml


```
```xml
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
@@ -68,25 +68,24 @@
</dependencies> </dependencies>


</project> </project>
```

## application.yml


```yaml
spring:
ldap:
urls: ldap://localhost:389
base: dc=example,dc=org
username: cn=admin,dc=example,dc=org
password: admin
``` ```


## Person.java ## Person.java


> 实体类 > 实体类
> @Entry 注解 映射ldap对象关系 > @Entry 注解 映射ldap对象关系
```
package com.xkcoding.ldap.entity;

import lombok.Data;
import org.springframework.ldap.odm.annotations.Attribute;
import org.springframework.ldap.odm.annotations.DnAttribute;
import org.springframework.ldap.odm.annotations.Entry;
import org.springframework.ldap.odm.annotations.Id;

import javax.naming.Name;
import java.io.Serializable;

```java
/** /**
* People * People
* *
@@ -158,20 +157,11 @@ public class Person implements Serializable {
*/ */
private String loginShell; private String loginShell;
} }

``` ```


## PersonRepository.java ## PersonRepository.java
> person 数据持久层 > person 数据持久层
```
package com.xkcoding.ldap.repository;

import com.xkcoding.ldap.entity.Person;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;

import javax.naming.Name;

```java
/** /**
* PersonRepository * PersonRepository
* *
@@ -189,42 +179,12 @@ public interface PersonRepository extends CrudRepository<Person, Name> {
* @return com.xkcoding.ldap.entity.Person * @return com.xkcoding.ldap.entity.Person
*/ */
Person findByUid(String uid); Person findByUid(String uid);

/**
* 查询全部
* @return
*/
@Override
Iterable<Person> findAll();

/**
* 保存
* @param s
* @param <S>
* @return
*/
@Override
<S extends Person> S save(S s);

/**
* 删除
* @param person
*/
@Override
void delete(Person person);
} }

``` ```


## PersonService.java ## PersonService.java
> 数据操作服务 > 数据操作服务
```
package com.xkcoding.ldap.service;

import com.xkcoding.ldap.entity.Person;
import com.xkcoding.ldap.entity.Result;
import com.xkcoding.ldap.request.LoginRequest;

```java
/** /**
* PersonService * PersonService
* *
@@ -236,54 +196,40 @@ public interface PersonService {


/** /**
* 登录 * 登录
* @param request com.xkcoding.ldap.request.LoginRequest
* @return com.xkcoding.ldap.entity.Result
*
* @param request {@link LoginRequest}
* @return {@link Result}
*/ */
Result login(LoginRequest request); Result login(LoginRequest request);


/** /**
* 查询全部 * 查询全部
* @return com.xkcoding.ldap.entity.Result
*
* @return {@link Result}
*/ */
Result listAllPerson(); Result listAllPerson();


/** /**
* 保存 * 保存
* @param person com.xkcoding.ldap.entity.Person
*
* @param person {@link Person}
*/ */
void save(Person person); void save(Person person);


/** /**
* 删除 * 删除
* @param person com.xkcoding.ldap.entity.Person
*
* @param person {@link Person}
*/ */
void delete(Person person); void delete(Person person);
}


}
``` ```


## PersonServiceImpl.java ## PersonServiceImpl.java
> person数据操作服务具体逻辑实现类 > person数据操作服务具体逻辑实现类


```
package com.xkcoding.ldap.service.impl;

import com.xkcoding.ldap.entity.Person;
import com.xkcoding.ldap.entity.Result;
import com.xkcoding.ldap.exception.ServiceException;
import com.xkcoding.ldap.repository.PersonRepository;
import com.xkcoding.ldap.request.LoginRequest;
import com.xkcoding.ldap.service.PersonService;
import com.xkcoding.ldap.util.LdapUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException;
import java.util.List;

```java
/** /**
* PersonServiceImpl * PersonServiceImpl
* *
@@ -293,20 +239,24 @@ import java.util.List;
*/ */
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class PersonServiceImpl implements PersonService { public class PersonServiceImpl implements PersonService {
private final PersonRepository personRepository;


@Resource
private PersonRepository personRepository;

/**
* 登录
*
* @param request {@link LoginRequest}
* @return {@link Result}
*/
@Override @Override
public Result login(LoginRequest request) { public Result login(LoginRequest request) {

log.info("IN LDAP auth"); log.info("IN LDAP auth");


Person user = personRepository.findByUid(request.getUsername()); Person user = personRepository.findByUid(request.getUsername());


try { try {
if(ObjectUtils.isEmpty(user)) {
if (ObjectUtils.isEmpty(user)) {
throw new ServiceException("用户名或密码错误,请重新尝试"); throw new ServiceException("用户名或密码错误,请重新尝试");
} else { } else {
user.setUserPassword(LdapUtils.asciiToString(user.getUserPassword())); user.setUserPassword(LdapUtils.asciiToString(user.getUserPassword()));
@@ -322,46 +272,46 @@ public class PersonServiceImpl implements PersonService {
return Result.success(user); return Result.success(user);
} }


/**
* 查询全部
*
* @return {@link Result}
*/
@Override @Override
public Result listAllPerson() { public Result listAllPerson() {
Iterable<Person> personList = personRepository.findAll(); Iterable<Person> personList = personRepository.findAll();
personList.forEach(person -> {
person.setUserPassword(LdapUtils.asciiToString(person.getUserPassword()));
});
personList.forEach(person -> person.setUserPassword(LdapUtils.asciiToString(person.getUserPassword())));
return Result.success(personList); return Result.success(personList);
} }


/**
* 保存
*
* @param person {@link Person}
*/
@Override @Override
public void save(Person person) { public void save(Person person) {
Person p = personRepository.save(person); Person p = personRepository.save(person);
log.info("用户{}保存成功", p.getUid()); log.info("用户{}保存成功", p.getUid());
} }


/**
* 删除
*
* @param person {@link Person}
*/
@Override @Override
public void delete(Person person) { public void delete(Person person) {
personRepository.delete(person); personRepository.delete(person);
log.info("删除用户{}成功", person.getUid()); log.info("删除用户{}成功", person.getUid());
} }
} }

``` ```


## LdapDemoApplicationTests.java ## LdapDemoApplicationTests.java
> 测试 > 测试
```
package com.xkcoding.ldap;

import com.xkcoding.ldap.entity.Person;
import com.xkcoding.ldap.entity.Result;
import com.xkcoding.ldap.request.LoginRequest;
import com.xkcoding.ldap.service.PersonService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;

```java
/** /**
* LdapDemoApplicationTest * LdapDemoApplicationTest
* *
@@ -380,6 +330,9 @@ public class LdapDemoApplicationTests {
public void contextLoads() { public void contextLoads() {
} }


/**
* 测试查询单个
*/
@Test @Test
public void loginTest() { public void loginTest() {
LoginRequest loginRequest = LoginRequest.builder().username("wangwu").password("123456").build(); LoginRequest loginRequest = LoginRequest.builder().username("wangwu").password("123456").build();
@@ -387,12 +340,18 @@ public class LdapDemoApplicationTests {
System.out.println(login); System.out.println(login);
} }


/**
* 测试查询列表
*/
@Test @Test
public void listAllPersonTest() { public void listAllPersonTest() {
Result result = personService.listAllPerson(); Result result = personService.listAllPerson();
System.out.println(result); System.out.println(result);
} }


/**
* 测试保存
*/
@Test @Test
public void saveTest() { public void saveTest() {
Person person = new Person(); Person person = new Person();
@@ -413,7 +372,9 @@ public class LdapDemoApplicationTests {
personService.save(person); personService.save(person);
} }



/**
* 测试删除
*/
@Test @Test
public void deleteTest() { public void deleteTest() {
Person person = new Person(); Person person = new Person();
@@ -421,8 +382,12 @@ public class LdapDemoApplicationTests {


personService.delete(person); personService.delete(person);
} }

} }
``` ```


## 其余代码参见本 demo

## 参考 ## 参考

spring-data-ldap 官方文档: https://docs.spring.io/spring-data/ldap/docs/2.1.10.RELEASE/reference/html/ spring-data-ldap 官方文档: https://docs.spring.io/spring-data/ldap/docs/2.1.10.RELEASE/reference/html/

spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/entity/Result.java → spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/api/Result.java View File

@@ -1,4 +1,4 @@
package com.xkcoding.ldap.entity;
package com.xkcoding.ldap.api;


import lombok.Data; import lombok.Data;
import org.springframework.lang.Nullable; import org.springframework.lang.Nullable;

spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/entity/ResultCode.java → spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/api/ResultCode.java View File

@@ -1,4 +1,4 @@
package com.xkcoding.ldap.entity;
package com.xkcoding.ldap.api;


import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;

+ 1
- 2
spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/exception/ServiceException.java View File

@@ -1,6 +1,6 @@
package com.xkcoding.ldap.exception; package com.xkcoding.ldap.exception;


import com.xkcoding.ldap.entity.ResultCode;
import com.xkcoding.ldap.api.ResultCode;
import lombok.Getter; import lombok.Getter;


/** /**
@@ -15,7 +15,6 @@ public class ServiceException extends RuntimeException {
@Getter @Getter
private int errcode; private int errcode;


@SuppressWarnings("NullableProblems")
@Getter @Getter
private String errmsg; private String errmsg;




+ 0
- 23
spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/repository/PersonRepository.java View File

@@ -23,27 +23,4 @@ public interface PersonRepository extends CrudRepository<Person, Name> {
* @return com.xkcoding.ldap.entity.Person * @return com.xkcoding.ldap.entity.Person
*/ */
Person findByUid(String uid); Person findByUid(String uid);

/**
* 查询全部
* @return
*/
@Override
Iterable<Person> findAll();

/**
* 保存
* @param s
* @param <S>
* @return
*/
@Override
<S extends Person> S save(S s);

/**
* 删除
* @param person
*/
@Override
void delete(Person person);
} }

+ 10
- 6
spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/service/PersonService.java View File

@@ -1,7 +1,7 @@
package com.xkcoding.ldap.service; package com.xkcoding.ldap.service;


import com.xkcoding.ldap.api.Result;
import com.xkcoding.ldap.entity.Person; import com.xkcoding.ldap.entity.Person;
import com.xkcoding.ldap.entity.Result;
import com.xkcoding.ldap.request.LoginRequest; import com.xkcoding.ldap.request.LoginRequest;


/** /**
@@ -15,26 +15,30 @@ public interface PersonService {


/** /**
* 登录 * 登录
* @param request com.xkcoding.ldap.request.LoginRequest
* @return com.xkcoding.ldap.entity.Result
*
* @param request {@link LoginRequest}
* @return {@link Result}
*/ */
Result login(LoginRequest request); Result login(LoginRequest request);


/** /**
* 查询全部 * 查询全部
* @return com.xkcoding.ldap.entity.Result
*
* @return {@link Result}
*/ */
Result listAllPerson(); Result listAllPerson();


/** /**
* 保存 * 保存
* @param person com.xkcoding.ldap.entity.Person
*
* @param person {@link Person}
*/ */
void save(Person person); void save(Person person);


/** /**
* 删除 * 删除
* @param person com.xkcoding.ldap.entity.Person
*
* @param person {@link Person}
*/ */
void delete(Person person); void delete(Person person);




+ 29
- 12
spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/service/impl/PersonServiceImpl.java View File

@@ -1,20 +1,19 @@
package com.xkcoding.ldap.service.impl; package com.xkcoding.ldap.service.impl;


import com.xkcoding.ldap.api.Result;
import com.xkcoding.ldap.entity.Person; import com.xkcoding.ldap.entity.Person;
import com.xkcoding.ldap.entity.Result;
import com.xkcoding.ldap.exception.ServiceException; import com.xkcoding.ldap.exception.ServiceException;
import com.xkcoding.ldap.repository.PersonRepository; import com.xkcoding.ldap.repository.PersonRepository;
import com.xkcoding.ldap.request.LoginRequest; import com.xkcoding.ldap.request.LoginRequest;
import com.xkcoding.ldap.service.PersonService; import com.xkcoding.ldap.service.PersonService;
import com.xkcoding.ldap.util.LdapUtils; import com.xkcoding.ldap.util.LdapUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;


import javax.annotation.Resource;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.List;


/** /**
* PersonServiceImpl * PersonServiceImpl
@@ -25,20 +24,24 @@ import java.util.List;
*/ */
@Slf4j @Slf4j
@Service @Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class PersonServiceImpl implements PersonService { public class PersonServiceImpl implements PersonService {
private final PersonRepository personRepository;


@Resource
private PersonRepository personRepository;

/**
* 登录
*
* @param request {@link LoginRequest}
* @return {@link Result}
*/
@Override @Override
public Result login(LoginRequest request) { public Result login(LoginRequest request) {

log.info("IN LDAP auth"); log.info("IN LDAP auth");


Person user = personRepository.findByUid(request.getUsername()); Person user = personRepository.findByUid(request.getUsername());


try { try {
if(ObjectUtils.isEmpty(user)) {
if (ObjectUtils.isEmpty(user)) {
throw new ServiceException("用户名或密码错误,请重新尝试"); throw new ServiceException("用户名或密码错误,请重新尝试");
} else { } else {
user.setUserPassword(LdapUtils.asciiToString(user.getUserPassword())); user.setUserPassword(LdapUtils.asciiToString(user.getUserPassword()));
@@ -54,24 +57,38 @@ public class PersonServiceImpl implements PersonService {
return Result.success(user); return Result.success(user);
} }


/**
* 查询全部
*
* @return {@link Result}
*/
@Override @Override
public Result listAllPerson() { public Result listAllPerson() {
Iterable<Person> personList = personRepository.findAll(); Iterable<Person> personList = personRepository.findAll();
personList.forEach(person -> {
person.setUserPassword(LdapUtils.asciiToString(person.getUserPassword()));
});
personList.forEach(person -> person.setUserPassword(LdapUtils.asciiToString(person.getUserPassword())));
return Result.success(personList); return Result.success(personList);
} }


/**
* 保存
*
* @param person {@link Person}
*/
@Override @Override
public void save(Person person) { public void save(Person person) {
Person p = personRepository.save(person); Person p = personRepository.save(person);
log.info("用户{}保存成功", p.getUid()); log.info("用户{}保存成功", p.getUid());
} }


/**
* 删除
*
* @param person {@link Person}
*/
@Override @Override
public void delete(Person person) { public void delete(Person person) {
personRepository.delete(person); personRepository.delete(person);
log.info("删除用户{}成功", person.getUid()); log.info("删除用户{}成功", person.getUid());
} }

} }

+ 23
- 22
spring-boot-demo-ldap/src/main/java/com/xkcoding/ldap/util/LdapUtils.java View File

@@ -16,54 +16,55 @@ public class LdapUtils {


/** /**
* 校验密码 * 校验密码
* @param ldappw ldap 加密密码
* @param inputpw 用户输入
*
* @param ldapPassword ldap 加密密码
* @param inputPassword 用户输入
* @return boolean * @return boolean
* @throws NoSuchAlgorithmException
* @throws NoSuchAlgorithmException 加解密异常
*/ */
public static boolean verify(String ldappw, String inputpw)
throws NoSuchAlgorithmException {
public static boolean verify(String ldapPassword, String inputPassword) throws NoSuchAlgorithmException {


// MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能,这里LDAP使用的是SHA-1 // MessageDigest 提供了消息摘要算法,如 MD5 或 SHA,的功能,这里LDAP使用的是SHA-1
MessageDigest md = MessageDigest.getInstance("SHA-1"); MessageDigest md = MessageDigest.getInstance("SHA-1");


// 取出加密字符 // 取出加密字符
if (ldappw.startsWith("{SSHA}")) {
ldappw = ldappw.substring(6);
} else if (ldappw.startsWith("{SHA}")) {
ldappw = ldappw.substring(5);
if (ldapPassword.startsWith("{SSHA}")) {
ldapPassword = ldapPassword.substring(6);
} else if (ldapPassword.startsWith("{SHA}")) {
ldapPassword = ldapPassword.substring(5);
} }
// 解码BASE64 // 解码BASE64
byte[] ldappwbyte = Base64.decode(ldappw);
byte[] shacode;
byte[] ldapPasswordByte = Base64.decode(ldapPassword);
byte[] shaCode;
byte[] salt; byte[] salt;


// 前20位是SHA-1加密段,20位后是最初加密时的随机明文 // 前20位是SHA-1加密段,20位后是最初加密时的随机明文
if (ldappwbyte.length <= 20) {
shacode = ldappwbyte;
if (ldapPasswordByte.length <= 20) {
shaCode = ldapPasswordByte;
salt = new byte[0]; salt = new byte[0];
} else { } else {
shacode = new byte[20];
salt = new byte[ldappwbyte.length - 20];
System.arraycopy(ldappwbyte, 0, shacode, 0, 20);
System.arraycopy(ldappwbyte, 20, salt, 0, salt.length);
shaCode = new byte[20];
salt = new byte[ldapPasswordByte.length - 20];
System.arraycopy(ldapPasswordByte, 0, shaCode, 0, 20);
System.arraycopy(ldapPasswordByte, 20, salt, 0, salt.length);
} }
// 把用户输入的密码添加到摘要计算信息 // 把用户输入的密码添加到摘要计算信息
md.update(inputpw.getBytes());
md.update(inputPassword.getBytes());
// 把随机明文添加到摘要计算信息 // 把随机明文添加到摘要计算信息
md.update(salt); md.update(salt);


// 按SSHA把当前用户密码进行计算 // 按SSHA把当前用户密码进行计算
byte[] inputpwbyte = md.digest();
byte[] inputPasswordByte = md.digest();


// 返回校验结果 // 返回校验结果
return MessageDigest.isEqual(shacode, inputpwbyte);
return MessageDigest.isEqual(shaCode, inputPasswordByte);
} }


/** /**
* Ascii转换为字符串 * Ascii转换为字符串
* @param value
* @return
*
* @param value Ascii串
* @return 字符串
*/ */
public static String asciiToString(String value) { public static String asciiToString(String value) {
StringBuilder sbu = new StringBuilder(); StringBuilder sbu = new StringBuilder();


+ 13
- 5
spring-boot-demo-ldap/src/test/java/com/xkcoding/ldap/LdapDemoApplicationTests.java View File

@@ -1,7 +1,7 @@
package com.xkcoding.ldap; package com.xkcoding.ldap;


import com.xkcoding.ldap.api.Result;
import com.xkcoding.ldap.entity.Person; import com.xkcoding.ldap.entity.Person;
import com.xkcoding.ldap.entity.Result;
import com.xkcoding.ldap.request.LoginRequest; import com.xkcoding.ldap.request.LoginRequest;
import com.xkcoding.ldap.service.PersonService; import com.xkcoding.ldap.service.PersonService;
import org.junit.Test; import org.junit.Test;
@@ -29,6 +29,9 @@ public class LdapDemoApplicationTests {
public void contextLoads() { public void contextLoads() {
} }


/**
* 测试查询单个
*/
@Test @Test
public void loginTest() { public void loginTest() {
LoginRequest loginRequest = LoginRequest.builder().username("wangwu").password("123456").build(); LoginRequest loginRequest = LoginRequest.builder().username("wangwu").password("123456").build();
@@ -36,12 +39,18 @@ public class LdapDemoApplicationTests {
System.out.println(login); System.out.println(login);
} }


/**
* 测试查询列表
*/
@Test @Test
public void listAllPersonTest() { public void listAllPersonTest() {
Result result = personService.listAllPerson(); Result result = personService.listAllPerson();
System.out.println(result); System.out.println(result);
} }


/**
* 测试保存
*/
@Test @Test
public void saveTest() { public void saveTest() {
Person person = new Person(); Person person = new Person();
@@ -62,7 +71,9 @@ public class LdapDemoApplicationTests {
personService.save(person); personService.save(person);
} }



/**
* 测试删除
*/
@Test @Test
public void deleteTest() { public void deleteTest() {
Person person = new Person(); Person person = new Person();
@@ -71,7 +82,4 @@ public class LdapDemoApplicationTests {
personService.delete(person); personService.delete(person);
} }





} }

Loading…
Cancel
Save