使用SpringBoot(SpringSecurity)和LDAP自动登录站点
我正在从事一个SpringBoot项目,该项目在SpringSecurity中使用LDAP进行身份验证 我需要根据SpringSecurity中提供的LDAP组中的角色,在用户点击登录页面后自动登录 如果用户在LDAP中提到的组中有任何角色,则必须在登录后重定向到相应的页面。(即我的示例中的第1页) 我已经连续两天在此搜索任何在线文档或示例,但都是徒劳的。我所能找到的就是使用jdbcDataSource,或者在Controller中硬编码用户名和密码,然后在登录时或通过Spring使用web.xml对其进行验证。但不是通过LDAP。任何帮助都会大有帮助 这就是我的Spring安全XML的外观:使用SpringBoot(SpringSecurity)和LDAP自动登录站点,spring,spring-boot,spring-security,ldap,Spring,Spring Boot,Spring Security,Ldap,我正在从事一个SpringBoot项目,该项目在SpringSecurity中使用LDAP进行身份验证 我需要根据SpringSecurity中提供的LDAP组中的角色,在用户点击登录页面后自动登录 如果用户在LDAP中提到的组中有任何角色,则必须在登录后重定向到相应的页面。(即我的示例中的第1页) 我已经连续两天在此搜索任何在线文档或示例,但都是徒劳的。我所能找到的就是使用jdbcDataSource,或者在Controller中硬编码用户名和密码,然后在登录时或通过Spring使用web.x
<?xml version="1.0" encoding="UTF-8" ?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/login" access="permitAll" />
<intercept-url pattern="/logout" access="permitAll" />
<intercept-url pattern="/webjars/**" access="permitAll" />
<intercept-url pattern="/page1" access="hasAnyRole('GP1','GP2')" />
<intercept-url pattern="/page2" access="hasAnyRole('GP1','GP2')" />
<intercept-url pattern="/page3" access="hasAnyRole('GP1','GP2')" />
<intercept-url pattern="/**" access="permitAll" />
<form-login default-target-url="/page1" login-page="/login"
always-use-default-target="true" />
<access-denied-handler error-page="/403.html" />
<csrf disabled="true" />
<logout logout-url="/logout" />
</http>
<authentication-manager alias="authenticationManager"
erase-credentials="false">
<authentication-provider ref="ldapAuthProvider" />
</authentication-manager>
<ldap-server id="contextSource" url="ldap://url"
manager-dn="mymanagerdn" manager-password="mymanagerpswd" />
<beans:bean id="ldapAuthProvider"
class="org.springframework.security.ldap.authentication.LdapAuthenticationProvider">
<beans:constructor-arg>
<beans:bean id="bindAuthenticator"
class="org.springframework.security.ldap.authentication.BindAuthenticator">
<beans:constructor-arg ref="contextSource" />
<beans:property name="userSearch" ref="userSearch" />
</beans:bean>
</beans:constructor-arg>
<beans:constructor-arg>
<beans:bean
class="org.springframework.security.ldap.userdetails.DefaultLdapAuthoritiesPopulator">
<beans:constructor-arg ref="contextSource" />
<beans:constructor-arg value="myDCvalues" />
<beans:property name="searchSubtree" value="true" />
<beans:property name="ignorePartialResultException"
value="true" />
<beans:property name="groupSearchFilter" value="(member={0})" />
</beans:bean>
</beans:constructor-arg>
</beans:bean>
<beans:bean id="userSearch"
class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<beans:constructor-arg index="0"
value="myDCvalues" />
<beans:constructor-arg index="1"
value="(sAMAccountName={0})" />
<beans:constructor-arg index="2" ref="contextSource" />
<beans:property name="searchSubtree" value="true" />
</beans:bean>
</beans:beans>
package com.myPackage;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Controller
public class WebController extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/page1").setViewName("page1");
registry.addViewController("/page2").setViewName("page2");
registry.addViewController("/page3").setViewName("page3");
registry.addViewController("/login").setViewName("login");
registry.addViewController("/403").setViewName("error/403");
}
@GetMapping("/page1")
public String page1(HttpSession session) {
return "page1";
}
@GetMapping("/page2")
public String page2(HttpSession session) {
return "page2";
}
@GetMapping("/page3")
public String page3(HttpSession session) {
return "page3";
}
@GetMapping("/login")
public String login() {
return "login";
}
@GetMapping("/403")
public String error403() {
return "error/403";
}
@Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("templates/");
return resolver;
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
private String getCredentials() {
String credential = null;
UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
credential = userDetails.getUsername().toString();
return credential;
}
}
为了方便起见,这个答案附带了一个测试,包括一个LDAP服务器,其中填充了用户和组以及一个集成测试,这样您就可以自己运行这些测试了 假设LDAP中有以下用户
dn: cn=marissa,ou=Users,dc=test,dc=com
changetype: add
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: marissa
userPassword: koala
uid: 20f459e0-e30b-4d1f-998c-3ded7f769db1
mail: marissa@test.com
sn: Marissa
用户名是marissa,密码是koala
让我们从测试用例开始:
@测试
@DisplayName(“ldap登录工作”)
void doLogin()引发异常{
mvc.perform(
MockMvcRequestBuilders.post(“/login”)
.param(“用户名”、“marissa”)
.param(“密码”、“考拉”)
.with(csrf())
)
.andExpect(状态().is3xx重定向())
.andExpect(已验证()
;
}
从这个测试中,我们可以推断
SecurityConfig.java
@EnableWebSecurity
公共类SecurityConfig扩展了WebSecurity配置适配器{
安全配置不会更改
@覆盖
受保护的无效配置(HttpSecurity http)引发异常{
http
.授权请求()
.anyRequest()
.fullyaauthenticated()
.及()
.formLogin()
;
}
就这样,接下来我们配置LDAP,同样在SecurityConfig.java
中,我们通过调用AuthenticationManagerBuilder
来实现。这是Spring Security配置的bean。因此,我们可以使用@Autowired
访问它
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)引发异常{
认证
.lda身份验证()
.contextSource()
.url(“ldap://localhost:389")
.managerDn(“cn=admin,dc=test,dc=com”)
.managerPassword(“密码”)
.及()
.userSearchBase(“ou=Users,dc=test,dc=com”)
.userSearchFilter(“cn={0}”)
.groupSearchBase(“dc=test,dc=com”)
.groupSearchFilter(“成员={0}”)
;
}
就是这样。现在,我使用我从CloudFoundry UAA项目中编写的一些代码为我的集成测试创建了一个in
因此,当模拟MVC集成测试启动时,它会启动一个LDAP服务器来运行
其实很简单,现在可以扩展这个示例,将LDAP组映射到Spring安全机构
LDAP示例在my community repo中提供:为方便起见,此答案附带了一个示例,包括一个LDAP服务器,由用户和组填充,以及一个集成测试,以便您可以自己运行这些测试 假设LDAP中有以下用户
dn: cn=marissa,ou=Users,dc=test,dc=com
changetype: add
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
cn: marissa
userPassword: koala
uid: 20f459e0-e30b-4d1f-998c-3ded7f769db1
mail: marissa@test.com
sn: Marissa
用户名是marissa,密码是koala
让我们从测试用例开始:
@测试
@DisplayName(“ldap登录工作”)
void doLogin()引发异常{
mvc.perform(
MockMvcRequestBuilders.post(“/login”)
.param(“用户名”、“marissa”)
.param(“密码”、“考拉”)
.with(csrf())
)
.andExpect(状态().is3xx重定向())
.andExpect(已验证()
;
}
从这个测试中,我们可以推断
SecurityConfig.java
@EnableWebSecurity
公共类SecurityConfig扩展了WebSecurity配置适配器{
安全配置不会更改
@覆盖
受保护的无效配置(HttpSecurity http)引发异常{
http
.授权请求()
.anyRequest()
.fullyaauthenticated()
.及()
.formLogin()
;
}
就这样,接下来我们配置LDAP,同样在SecurityConfig.java
中,我们通过调用AuthenticationManagerBuilder
来实现。这是Spring Security配置的bean。因此,我们可以使用@Autowired
访问它
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth)引发异常{
认证
.lda身份验证()
.contextSource()
.url(“ldap://localhost:389")
.managerDn(“cn=admin,dc=test,dc=com”)
.managerPassword(“密码”)
.及()
.userSearchBase(“ou=Users,dc=test,dc=com”)
.userSearchFilter(“cn={0}”)
.groupSearchBase(“dc=test,dc=com”)
.groupSearchFilter(“成员={0}”)
;
}
就这样,现在,我用