Spring security switch to Ldap authentication and database authorities(Spring 安全切换到 Ldap 身份验证和数据库权限)
问题描述
我为我的网页和 Web 服务实现了数据库身份验证.它对两者都有效,现在我必须添加 Ldap 身份验证.我必须通过远程 Ldap 服务器进行身份验证(使用用户名和密码),如果用户存在,我必须使用我的数据库作为用户角色(在我的数据库中,用户名与 Ldap 的用户名相同).所以我必须从我的实际代码切换到如上所述的 Ldap 和数据库身份验证.我的代码是:安全配置类
I implemented database authentication for my web page and web service. It work well for both, now I have to add Ldap authentication. I have to authenticate through remote Ldap server (using username and password) and if the user exists I have to use my database for user roles (in my database username is the same username of Ldap). So I have to switch from my actual code to the Ldap and database authentication as above explained. My code is: SecurityConfig class
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("userDetailsService")
UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
public PasswordEncoder passwordEncoder(){
PasswordEncoder encoder = new BCryptPasswordEncoder();
return encoder;
}
@Configuration
@Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/client/**")
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
@Configuration
@Order(2)
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
public void configure(WebSecurity web) throws Exception {
web
//Spring Security ignores request to static resources such as CSS or JS files.
.ignoring()
.antMatchers("/static/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() //Authorize Request Configuration
//the / and /register path are accepted without login
//.antMatchers("/", "/register").permitAll()
//the /acquisition/** need admin role
//.antMatchers("/acquisition/**").hasRole("ADMIN")
//.and().exceptionHandling().accessDeniedPage("/Access_Denied");
//all the path need authentication
.anyRequest().authenticated()
.and() //Login Form configuration for all others
.formLogin()
.loginPage("/login")
//important because otherwise it goes in a loop because login page require authentication and authentication require login page
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
// CSRF tokens handling
}
}
MyUserDetailsService 类
MyUserDetailsService class
@Service("userDetailsService")
public class MyUserDetailsService implements UserDetailsService {
@Autowired
private UserServices userServices;
static final Logger LOG = LoggerFactory.getLogger(MyUserDetailsService.class);
@Transactional(readOnly=true)
@Override
public UserDetails loadUserByUsername(final String username){
try{
com.domain.User user = userServices.findById(username);
if (user==null)
LOG.error("Threw exception in MyUserDetailsService::loadUserByUsername : User doesn't exist" );
else{
List<GrantedAuthority> authorities = buildUserAuthority(user.getUserRole());
return buildUserForAuthentication(user, authorities);
}
}catch(Exception e){
LOG.error("Threw exception in MyUserDetailsService::loadUserByUsername : " + ErrorExceptionBuilder.buildErrorResponse(e)); }
return null;
}
// Converts com.users.model.User user to
// org.springframework.security.core.userdetails.User
private User buildUserForAuthentication(com.domain.User user, List<GrantedAuthority> authorities) {
return new User(user.getUsername(), user.getPassword(), user.isEnabled(), true, true, true, authorities);
}
private List<GrantedAuthority> buildUserAuthority(Set<UserRole> userRoles) {
Set<GrantedAuthority> setAuths = new HashSet<GrantedAuthority>();
// Build user's authorities
for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getUserRoleKeys().getRole()));
}
List<GrantedAuthority> Result = new ArrayList<GrantedAuthority>(setAuths);
return Result;
}
所以我必须:
1) 用户从网页的登录页面和网络服务的用户名和密码访问.这必须通过 Ldap 完成.
1)access of user from login page for web pages and username and password for web services. This has to be done through Ldap.
2) 数据库查询需要用户的用户名来认证用户.你知道我该如何实现吗?谢谢
2)the username of user needs for database query to authenticate user. Do you have any idea how I can implement this? Thanks
使用正确的代码更新:在@M 之后.Deinum 建议我创建 MyAuthoritiesPopulator
类而不是 MyUserDetailsService
并使用数据库和 Ldap 进行身份验证:
UPDATE WITH RIGHT CODE: Following the @M. Deinum advice I create MyAuthoritiesPopulator
class instead of MyUserDetailsService
and authentication with database and Ldap works:
@Service("myAuthPopulator")
public class MyAuthoritiesPopulator implements LdapAuthoritiesPopulator {
@Autowired
private UserServices userServices;
static final Logger LOG = LoggerFactory.getLogger(MyAuthoritiesPopulator.class);
@Transactional(readOnly=true)
@Override
public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {
Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
try{
com.domain.User user = userServices.findById(username);
if (user==null)
LOG.error("Threw exception in MyAuthoritiesPopulator::getGrantedAuthorities : User doesn't exist into ATS database" );
else{
for(UserRole userRole : user.getUserRole()) {
authorities.add(new SimpleGrantedAuthority(userRole.getUserRoleKeys().getRole()));
}
return authorities;
}
}catch(Exception e){
LOG.error("Threw exception in MyAuthoritiesPopulator::getGrantedAuthorities : " + ErrorExceptionBuilder.buildErrorResponse(e)); }
return authorities;
}
}
我将 SecurityConfig 更改如下:
and I changed SecurityConfig as below:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
@Qualifier("myAuthPopulator")
LdapAuthoritiesPopulator myAuthPopulator;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource()
.url("ldap://127.0.0.1:10389/dc=example,dc=com")
// .managerDn("")
// .managerPassword("")
.and()
.userSearchBase("ou=people")
.userSearchFilter("(uid={0})")
.ldapAuthoritiesPopulator(myAuthPopulator);
}
@Configuration
@Order(1)
public static class ApiWebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.antMatcher("/client/**")
.authorizeRequests()
//Excluede send file from authentication because it doesn't work with spring authentication
//TODO add java authentication to send method
.antMatchers(HttpMethod.POST, "/client/file").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
}
@Configuration
@Order(2)
public static class FormWebSecurityConfig extends WebSecurityConfigurerAdapter{
@Override
public void configure(WebSecurity web) throws Exception {
web
//Spring Security ignores request to static resources such as CSS or JS files.
.ignoring()
.antMatchers("/static/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests() //Authorize Request Configuration
//the "/" and "/register" path are accepted without login
//.antMatchers("/", "/register").permitAll()
//the /acquisition/** need admin role
//.antMatchers("/acquisition/**").hasRole("ADMIN")
//.and().exceptionHandling().accessDeniedPage("/Access_Denied");
//all the path need authentication
.anyRequest().authenticated()
.and() //Login Form configuration for all others
.formLogin()
.loginPage("/login")
//important because otherwise it goes in a loop because login page require authentication and authentication require login page
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
}
}
}
我在 Apache directory studio 中创建的 LDAP 开发环境
My LDAP development environment created in Apache directory studio
推荐答案
Spring Security 已经支持开箱即用的 LDAP.它实际上有一个关于此的整章.
Spring Security already supports LDAP out-of-the-box. It actually has a whole chapter on this.
要使用和配置 LDAP,请添加 spring-security-ldap
依赖项,然后使用 AuthenticationManagerBuilder.ldapAuthentication
来配置它.LdapAuthenticationProviderConfigurer
允许您设置所需的东西.
To use and configure LDAP add the spring-security-ldap
dependency and next use the AuthenticationManagerBuilder.ldapAuthentication
to configure it. The LdapAuthenticationProviderConfigurer
allows you to set the needed things up.
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.contextSource()
.url(...)
.port(...)
.managerDn(...)
.managerPassword(...)
.and()
.passwordEncoder(passwordEncoder())
.userSearchBase(...)
.ldapAuthoritiesPopulator(new UserServiceLdapAuthoritiesPopulater(this.userService));
}
类似的东西(它至少应该让您了解什么/如何配置东西)还有更多选项,但请查看 javadocs.如果你不能使用 UserService
来检索角色(因为只有角色在数据库中)然后实现你自己的 LdapAuthoritiesPopulator
.
Something like that (it should give you at least an idea on what/how to configure things) there are more options but check the javadocs for that. If you cannot use the UserService
as is to retrieve the roles (because only the roles are in the database) then implement your own LdapAuthoritiesPopulator
for that.
这篇关于Spring 安全切换到 Ldap 身份验证和数据库权限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:Spring 安全切换到 Ldap 身份验证和数据库权限
基础教程推荐
- FirebaseListAdapter 不推送聊天应用程序的单个项目 - Firebase-Ui 3.1 2022-01-01
- 减少 JVM 暂停时间 >1 秒使用 UseConcMarkSweepGC 2022-01-01
- 如何使用 Java 创建 X509 证书? 2022-01-01
- 无法使用修饰符“public final"访问 java.util.Ha 2022-01-01
- 在 Libgdx 中处理屏幕的正确方法 2022-01-01
- Java Keytool 导入证书后出错,"keytool error: java.io.FileNotFoundException &拒绝访问" 2022-01-01
- “未找到匹配项"使用 matcher 的 group 方法时 2022-01-01
- Java:带有char数组的println给出乱码 2022-01-01
- 设置 bean 时出现 Nullpointerexception 2022-01-01
- 降序排序:Java Map 2022-01-01