ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SpringBoot LDAP 用户鉴权操作

2020-01-26 17:43:56  阅读:330  来源: 互联网

标签:SpringBoot objectclass Spring dc springframework LDAP org ou 鉴权


开篇词

该指南将引导你完成创建受 Spring Security LDAP 模块保护的应用。
 

你将创建的应用

我们将创建一个简单的 Web 应用,该应用由 Spring Security 的嵌入式 Java LDAP 服务器保护。我们将使用包含一组用户的数据文件加载 LDAP 服务器。
 

你将需要的工具

如何完成这个指南

像大多数的 Spring 入门指南一样,你可以从头开始并完成每个步骤,也可以绕过你已经熟悉的基本设置步骤。如论哪种方式,你最终都有可以工作的代码。

  • 要从头开始,移步至从 Spring Initializr 开始
  • 要跳过基础,执行以下操作:
    • 下载并解压缩该指南将用到的源代码,或借助 Git 来对其进行克隆操作:git clone https://github.com/spring-guides/gs-authenticating-ldap.git
    • 切换至 gs-authenticating-ldap/initial 目录;
    • 跳转至该指南的创建简单的 Web 控制器

待一切就绪后,可以检查一下 gs-authenticating-ldap/complete 目录中的代码。
 

从 Spring Initializr 开始

对于所有的 Spring 应用来说,你应该从 Spring Initializr 开始。Initializr 提供了一种快速的方法来提取应用程序所需的依赖,并为你完成许多设置。该示例仅需要 Spring Web 依赖。

因为该指南的重点是安全和不安全的 Web 应用,所以我们将首先构建不安全的 Web 应用,然后加入 Spring Security 以及 LDAP 功能的依赖。

下图显示了此示例项目的 Initializr 设置:
Spring Initializr 界面

上图显示了选择 Maven 作为构建工具的 Initializr。你也可以使用 Gradle。它还将 com.exampleauthenticating-ldap 的值分别显示为 Group 和 Artifact。在本示例的其余部分,将用到这些值。

以下清单显示了选择 Maven 时创建的 pom.xml 文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.2.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>authenticating-ldap</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>authenticating-ldap</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
			<exclusions>
				<exclusion>
					<groupId>org.junit.vintage</groupId>
					<artifactId>junit-vintage-engine</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

以下清单显示了在选择 Gradle 时创建的 build.gradle 文件:

plugins {
	id 'org.springframework.boot' version '2.2.2.RELEASE'
	id 'io.spring.dependency-management' version '1.0.8.RELEASE'
	id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
	mavenCentral()
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation('org.springframework.boot:spring-boot-starter-test') {
		exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
	}
}

test {
	useJUnitPlatform()
}

 

创建简单的 Web 控制器

在 Spring 中,REST 端点是 Spring MVC 控制器。以下 Spring MVC 控制器(来自 src/main/java/com/example/authenticatingldap/HomeController.java)通过返回一条简单消息来处理 GET / 请求:

package com.example.authenticatingldap;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HomeController {

  @GetMapping("/")
  public String index() {
    return "Welcome to the home page!";
  }

}

整个类都使用 @RestController 进行了标记,以便 Spring MVC可以自动检测控制器(通过使用其内置的扫描功能)并自动配置必要的 Web 路由。

@RestController 还告诉 Spring MVC 将文本直接写到 HTTP 响应主体中,因为没有视图。相反,当我们访问页面时,我们会在浏览器中收到一条简单的消息(因为该指南的重点是使用 LDAP 保护页面)。
 

构建不安全的 Web 应用

在保护 Web 应用之前,应验证其是否正常运行。为此,我们需要定义一些钥 bean,可以通过创建 Application 类来完成。以下清单(来自 src/main/java/com/example/authenticatingldap/AuthenticatingLdapApplication.java)显示了该类:

package com.example.authenticatingldap;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AuthenticatingLdapApplication {

  public static void main(String[] args) {
    SpringApplication.run(AuthenticatingLdapApplication.class, args);
  }

}

@SpringBootApplication 是一个便利的注解,它添加了以下所有内容:

  • @Configuration:将类标记为应用上下文 Bean 定义的源;
  • @EnableAutoConfiguration:告诉 Spring Boot 根据类路径配置、其他 bean 以及各种属性的配置来添加 bean。
  • @ComponentScan:告知 Spring 在 com/example.xxxxxx 包中寻找他组件、配置以及服务。

main() 方法使用 Spring Boot 的 SpringApplication.run() 方法启动应用。
 

运行应用

我们可以结合 Gradle 或 Maven 来从命令行运行该应用。我们还可以构建一个包含所有必须依赖项、类以及资源的可执行 JAR 文件,然后运行该文件。在整个开发生命周期中,跨环境等等情况下,构建可执行 JAR 可以轻松地将服务作为应用进行发布、版本化以及部署。

如果使用 Gradle,则可以借助 ./gradlew bootRun 来运行应用。或通过借助 ./gradlew build 来构建 JAR 文件,然后运行 JAR 文件,如下所示:

java -jar build/libs/gs-authenticating-ldap-0.1.0.jar

如果使用 Maven,则可以借助 ./mvnw spring-boot:run 来运行该用。或可以借助 ./mvnw clean package 来构建 JAR 文件,然后运行 JAR 文件,如下所示:

java -jar target/gs-authenticating-ldap-0.1.0.jar

我们还可以构建一个经典的 WAR 文件

当通过浏览器访问 http://localhost:8080 时,我们应该看到以下纯文本输出:

Welcome to the home page!

 

配置 Spring Security

要配置 Spring Security,首先需要向构建中添加一些额外的依赖。
对于基于 Gradle 的构建,请将以下依赖项添加至 build.gradle 文件:

implementation 'org.springframework.boot:spring-boot-starter-security:2.2.2.RELEASE'
implementation 'org.springframework.boot:spring-boot-starter-data-ldap:2.2.2.RELEASE'
implementation 'org.springframework.security:spring-security-ldap:5.2.1.RELEASE'
implementation 'com.unboundid:unboundid-ldapsdk:4.0.14'

由于 Gradle 的工件分辨率问题,必须将 spring-tx 插入。否则,Gradle 会获取不起作用的旧版本。

对于基于 Maven 的构建,请将以下依赖项添加至 pom.xml 文件:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-security</artifactId>
	<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-ldap</artifactId>
	<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-ldap</artifactId>
	<version>5.2.1.RELEASE</version>
</dependency>
<dependency>
	<groupId>com.unboundid</groupId>
	<artifactId>unboundid-ldapsdk</artifactId>
    <version>4.0.14</version>
</dependency>

这些依赖添加了 Spring Security 以及一个开源 LDAP 服务器 UnboundId。有了这些依赖关系之后,我们就可以使用纯 Java 来配置安全策略,如以下示例(来自 src/main/java/com/example/authenticatingldap/WebSecurityConfig.java)所示:

package com.example.authenticatingldap;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http
      .authorizeRequests()
        .anyRequest().fullyAuthenticated()
        .and()
      .formLogin();
  }

  @Override
  public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
      .ldapAuthentication()
        .userDnPatterns("uid={0},ou=people")
        .groupSearchBase("ou=groups")
        .contextSource()
          .url("ldap://localhost:8389/dc=springframework,dc=org")
          .and()
        .passwordCompare()
          .passwordEncoder(new BCryptPasswordEncoder())
          .passwordAttribute("userPassword");
  }

}

@EnableWebSecurity 注释激活了使用 Spring Security 时所需的 bean。
我们来需要一个 LDAP 服务器。Spring Boot 为使用纯 Java 编写的嵌入式服务器提供了自动配置,该指南将使用它。LdapAuthentication() 方法进行配置,以便将登录表单上的用户名插入 {0} 中,以便它在 LDAP 服务器中搜索 uid = {0},ou = people,dc = springframework,dc = org。另外,passwordCompare() 方法配置编码器以及密码属性的名称。
 

设置用户数据

LDAP 服务器可以使用 LDIF(LDAP 数据交换格式)文件来交换用户数据。通过 application.properties 中的 spring.ldap.embedded.ldif 属性,Spring Boot 可以拉入 LDIF 数据文件。这样可以很容易地预加载演示数据。以下清单(来自 src/main/resources/test-server.ldif)显示了适用于此示例的 LDIF 文件:

dn: dc=springframework,dc=org
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: springframework

dn: ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: groups

dn: ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: subgroups

dn: ou=people,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: people

dn: ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: space cadets

dn: ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: "quoted people"

dn: ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: organizationalUnit
ou: otherpeople

dn: uid=ben,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Ben Alex
sn: Alex
uid: ben
userPassword: $2a$10$c6bSeWPhg06xB1lvmaWNNe4NROmZiSpYhlocU/98HNr2MhIOiSt36

dn: uid=bob,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Bob Hamilton
sn: Hamilton
uid: bob
userPassword: bobspassword

dn: uid=joe,ou=otherpeople,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Joe Smeth
sn: Smeth
uid: joe
userPassword: joespassword

dn: cn=mouse\, jerry,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Mouse, Jerry
sn: Mouse
uid: jerry
userPassword: jerryspassword

dn: cn=slash/guy,ou=people,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: slash/guy
sn: Slash
uid: slashguy
userPassword: slashguyspassword

dn: cn=quote\"guy,ou=\"quoted people\",dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: quote\"guy
sn: Quote
uid: quoteguy
userPassword: quoteguyspassword

dn: uid=space cadet,ou=space cadets,dc=springframework,dc=org
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: Space Cadet
sn: Cadet
uid: space cadet
userPassword: spacecadetspassword



dn: cn=developers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: developers
ou: developer
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
uniqueMember: uid=bob,ou=people,dc=springframework,dc=org

dn: cn=managers,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: managers
ou: manager
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org
uniqueMember: cn=mouse\, jerry,ou=people,dc=springframework,dc=org

dn: cn=submanagers,ou=subgroups,ou=groups,dc=springframework,dc=org
objectclass: top
objectclass: groupOfUniqueNames
cn: submanagers
ou: submanager
uniqueMember: uid=ben,ou=people,dc=springframework,dc=org

对于生产系统,使用 LDIF 文件不是标准配置。不过,它对于测试目的或指导则很有用。

当我们再次访问 http://localhost:8080 时,则应将我们重定向至 Spring Security 提供的登录页。

输入用户名 ben 和密码 benspassword。我们应该在浏览器中看到以下消息:

Welcome to the home page!

 

概述

恭喜你!我们已经编写了一个 Web 应用,并已经通过 Spring Security 对其进行了保护。在这种情况下,我们使用了基于 LDAP 的用户存储
 

参见

以下指南也可能会有所帮助:

想看指南的其他内容?请访问该指南的所属专栏:《Spring 官方指南

Snow Hide 发布了87 篇原创文章 · 获赞 6 · 访问量 4130 私信 关注

标签:SpringBoot,objectclass,Spring,dc,springframework,LDAP,org,ou,鉴权
来源: https://blog.csdn.net/stevenchen1989/article/details/104087271

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有