網頁

2019/9/24

Spring Boot + Spring Security + Spring LDAP + Gradle 驗證範例

本範例為Spring官方教學Authenticating a User with LDAP的實作。

範例環境如下:

  • macOS High Sierra
  • Java 1.8
  • Eclipse for Java EE 2019-06 (4.12.0)
  • Spring Boot 2.1.8.RELEASE
  • Eclipse Gradle Buildship plug-in

建立一個Spring Boot Gradle專案,專案進入點的SprinBootApplication類如下。

SpringSecurityLdapDemoApplication

package com.abc.demo;

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

@SpringBootApplication
public class SpringSecurityLdapDemoApplication {

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

}

在專案的Gradle配置檔build.bradle加入以下dependencies。

implementation 'org.springframework.boot:spring-boot-starter-web'       // Spring Web
implementation 'org.springframework.boot:spring-boot-starter-security'  // Spring Security
implementation 'org.springframework.security:spring-security-ldap'      // Spring Security LDAP
implementation 'org.springframework.boot:spring-boot-starter-data-ldap' // Spring Data LDAP
implementation 'com.unboundid:unboundid-ldapsdk'                        // In-Memory Directory Server 

設定好後專案的build.gralde內容如下:

build.gradle

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

group = 'com.abc.demo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.security:spring-security-ldap'
    implementation 'org.springframework.boot:spring-boot-starter-data-ldap'
    implementation 'com.unboundid:unboundid-ldapsdk'
    
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.security:spring-security-test'
}

在Spring Boot配置檔application.properties新增以下embedded LDAP Server參數(EmbeddedLdapProperties)的配置。

application.properties

#LDAP人員資料來源位置
spring.ldap.embedded.ldif=classpath:test-server.ldif
#LDAP base dn
spring.ldap.embedded.base-dn=dc=springframework,dc=org
#LDAP Server port
spring.ldap.embedded.port=8389

在專案的用來擺放靜態資源的src/main/resources路徑下新增存放embedded LDAP Server的人員資料的test-server.ldif檔。

test-server.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: {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

在專案新增Spring Security的配置類別WebSecurityConfig如下。

LdapWebSecurityConfig

package com.abc.demo.config;

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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.LdapShaPasswordEncoder;

@EnableWebSecurity
public class LdapWebSecurityConfig 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 LdapShaPasswordEncoder())
            .passwordAttribute("userPassword");
    }
}

新增通過驗證後導向的DemoController

package com.abc.demo.controller;

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

@RestController
public class DemoController {

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

範例的專案目錄結構如下。



設定完後啟動專案,然後在瀏覽器輸入http://localhost:8080便會進入Spring Security的登入畫面。



輸入test-server.ldif中的人員帳號密碼,例如bob/bobspassword登入。

如果通過驗證便會導向DemoController並返回結果如下。



只能説Spring官方教學通常都寫得太簡單,有些設定都沒寫清楚常跑不起來,還要去官方範例的github連結看一下是否少了東西。

參考:

沒有留言:

張貼留言