SpringBoot生態(tài)中的LDAP認(rèn)證

前言

本文主要講述如何利用Spring的JdbcTemplate訪問關(guān)系型數(shù)據(jù)庫忍啸。

本機(jī)環(huán)境

  • Java:1.8.0

  • maven:apache maven 3.6.0

  • IDE :IDEA

通過maven搭建系統(tǒng)

  • pom文件:
<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 http://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.1.6.RELEASE</version>
 <relativePath/> <!-- lookup parent from repository -->
 </parent>
 <groupId>com.example</groupId>
 <artifactId>authenticating_ldap</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>demo</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>
 </dependency>
?
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-security</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.ldap</groupId>
 <artifactId>spring-ldap-core</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.security</groupId>
 <artifactId>spring-security-ldap</artifactId>
 </dependency>
 <dependency>
 <groupId>com.unboundid</groupId>
 <artifactId>unboundid-ldapsdk</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.security</groupId>
 <artifactId>spring-security-test</artifactId>
 <scope>test</scope>
 </dependency>
 </dependencies>
?
 <build>
 <plugins>
 <plugin>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-maven-plugin</artifactId>
 </plugin>
 </plugins>
 </build>
</project>
?</pre>

注意到魁索,Spring的ldap認(rèn)證是在spring.security包下的,說明這是Security模塊下的一個(gè)功能炬灭。

控制器

下面我們來簡(jiǎn)單地建立一個(gè)控制器,以控制HTTP的request和response靡菇。

package com.example.demo.controller;
?
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
?
/**
 * @ClassName HomeController
 * @Description TODO
 * @Author wonderQin
 * @Date 2019-07-06 16:27
 **/
@Controller
public class HomeController {
 @GetMapping("/")
 public String index(){
 return "Hello, welcome to home page!";
 }
}

以上重归,我們通過返回一條簡(jiǎn)單的message來處理"/"的GET請(qǐng)求。

我們來復(fù)習(xí)下在個(gè)類中出現(xiàn)的注解的功能:

  • @Controller: 被該注解作用的整個(gè)類厦凤,Spring MVC可以使用它的內(nèi)置掃描功能自動(dòng)檢測(cè)控制器并自動(dòng)配置Web路由(通俗地說就是標(biāo)志該類為控制器類鼻吮,但這種說法沒解釋到點(diǎn)子上)。

  • @GetMapping:該注解則標(biāo)明被該注解標(biāo)記的類為HTTP的處理類较鼓,與@RequestMapping類似椎木,它主要有兩個(gè)功能:一是標(biāo)記路徑,標(biāo)記瀏覽器的訪問路徑博烂;二是說明REST操作香椎。這里的@GetMapping則顯式地說明該HTTP請(qǐng)求只能是”GET“請(qǐng)求。

Springboot入口類

?
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
?
@SpringBootApplication
public class DemoApplication {
?
 public static void main(String[] args) {
 SpringApplication.run(DemoApplication.class, args);
 }
?
}

該類的相關(guān)知識(shí)點(diǎn)在我之前的文章中有所描述禽篱,在這里復(fù)習(xí)下:

  • @Configuration將類標(biāo)記為應(yīng)用程序上下文的bean定義源士鸥。

  • @EnableAutoConfiguration告訴Spring Boot根據(jù)類路徑設(shè)置,其他bean和各種屬性設(shè)置開始添加bean谆级。

  • 通常我們?cè)谑褂胹pring的mvc時(shí)烤礁,會(huì)為Spring MVC應(yīng)用程序添加@EnableWebMvc注解,但Spring Boot會(huì)在類路徑上看到spring-webmvc時(shí)自動(dòng)添加它肥照。 這會(huì)將應(yīng)用程序標(biāo)記為Web應(yīng)用程序并激活關(guān)鍵行為脚仔,例如設(shè)置DispatcherServlet。

  • @ComponentScan告訴Spring在當(dāng)前目錄下(包括當(dāng)前目錄)的包中尋找其他組件舆绎,配置和服務(wù)鲤脏,允許它找到控制器。

配置LDAP的安全策略

?
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.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.LdapShaPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import sun.nio.cs.ext.GBK;
?
/**
 * @ClassName WebSecurityConfig
 * @Description TODO
 * @Author wonderQin
 * @Date 2019-07-06 16:29
 **/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
 protected void configure(HttpSecurity httpSecurity) throws Exception{
 httpSecurity.authorizeRequests()
 .anyRequest().fullyAuthenticated()
 .and()
 .formLogin();
 }
?
 @Override
 public void configure(AuthenticationManagerBuilder builder) throws Exception{
 builder
 .ldapAuthentication()
 .userDnPatterns("uid={0},ou=people")
 .groupSearchBase("ou=groups")
 .contextSource()
 .url("ldap://localhost:8080/dc=springframework,dc=org")
 .and()
 .passwordCompare()
 .passwordEncoder(new PasswordEncoder() {
 @Override
 public String encode(CharSequence charSequence) {
 return "gbk";
 }
?
 @Override
 public boolean matches(CharSequence charSequence, String s) {
 return false;
 }
 })
 .passwordAttribute("usePassword");
 }
}

這里其實(shí)就是重寫了WebSecurityConfigurerAdapter中的配置策略:

  • configure(HttpSecurity httpSecurity)方法是對(duì)LDAP登錄模式的配置吕朵;

  • configure(AuthenticationManagerBuilder builder):則是對(duì)Security LDAP上下文的配置猎醇,比如:LDAP服務(wù)器、編碼方式等努溃。

  • 在我們看到:.url("ldap://localhost:8080/dc=springframework,dc=org")的時(shí)候硫嘶,就明白我們這里還需要一個(gè)ldap服務(wù)器,該服務(wù)器可以自己搭建梧税,這里可以參考LDAP服務(wù)器的搭建

  • ldapAuthentication()方法配置登錄表單中的用戶名插入{0}的內(nèi)容沦疾,以便在LDAP服務(wù)器中搜索uid = {0}称近,ou = people,dc = springframework哮塞,dc = org刨秆。 此外,passwordCompare()方法配置編碼器和密碼屬性的名稱忆畅。

使用LDIF交換用戶數(shù)據(jù)

LDAP服務(wù)器可以使用LDIF(LDAP數(shù)據(jù)交換格式)文件來交換用戶數(shù)據(jù)衡未。 application.properties中的spring.ldap.embedded.ldif屬性允許Spring Boot拉入LDIF數(shù)據(jù)文件。 這樣可以輕松預(yù)加載演示數(shù)據(jù)家凯。

  • 在resources文件夾下新建test-server.ldif文件
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: {SHA}nFCebWjxfaLbHHG1Qk5UU4trbvQ=
?
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
  • application.properties文件配置
spring.ldap.embedded.base-dn=dc=springframework,dc=org
spring.ldap.embedded.port=8389

運(yùn)行

同樣地

你可以選擇以下方式運(yùn)行:

  • IDE直接啟動(dòng)

  • 打jar包用命令行啟動(dòng)

java -jar
  • 打war包到tomcat上啟動(dòng)

運(yùn)行結(jié)果:

再次訪問:localhost:8080/時(shí)則需要通過LDAP登錄了:

image

這時(shí)候輸入用戶名:ben 密碼:benspassword就可以通過驗(yàn)證

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末缓醋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子肆饶,更是在濱河造成了極大的恐慌改衩,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件驯镊,死亡現(xiàn)場(chǎng)離奇詭異葫督,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)板惑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門橄镜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冯乘,你說我怎么就攤上這事洽胶。” “怎么了裆馒?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵姊氓,是天一觀的道長。 經(jīng)常有香客問我喷好,道長翔横,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任梗搅,我火速辦了婚禮禾唁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘无切。我一直安慰自己荡短,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布哆键。 她就那樣靜靜地躺著掘托,像睡著了一般。 火紅的嫁衣襯著肌膚如雪洼哎。 梳的紋絲不亂的頭發(fā)上烫映,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天沼本,我揣著相機(jī)與錄音噩峦,去河邊找鬼锭沟。 笑死,一個(gè)胖子當(dāng)著我的面吹牛识补,可吹牛的內(nèi)容都是我干的族淮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼凭涂,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼祝辣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起切油,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤蝙斜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后澎胡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體孕荠,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年攻谁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了稚伍。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡戚宦,死狀恐怖个曙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情受楼,我是刑警寧澤垦搬,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站艳汽,受9級(jí)特大地震影響猴贰,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜骚灸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一糟趾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甚牲,春花似錦义郑、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至雏赦,卻和暖如春劫笙,著一層夾襖步出監(jiān)牢的瞬間芙扎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來泰國打工填大, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留戒洼,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓允华,卻偏偏與公主長得像圈浇,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子靴寂,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容