java – Spring安全切换到Ldap认证和数据库权限
我为我的网页和Web服务实现了数据库身份验证.
它对两者都很好,现在我必须添加Ldap身份验证. 我必须通过远程Ldap服务器进行身份验证(使用用户名和密码),如果用户存在我必须使用我的数据库为用户角色(在我的数据库用户名是相同的用户名Ldap). 所以我必须从我的实际代码切换到Ldap和数据库认证,如上所述.我的代码是: SecurityConfig类 @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 } } MyUserDetailsS??ervice类 @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,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)用户从网页的登录页面以及Web服务的用户名和密码访问用户.这必须通过Ldap完成. 2)用户需要用户名进行数据库查询来认证用户. 使用正确的代码更新:遵循@M. Deinum建议我创建MyAuthoritiesPopulator类而不是MyUserDetailsS??ervice,并使用数据库和Ldap进行身份验证: @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如下: @Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(securedEnabled = 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(); } } } 我的LDAP开发环境在Apache目录工作室中创建 解决方法
Spring Security已经支持LDAP开箱即用.它实际上有一个
whole chapter这个.
要使用和配置LDAP,请添加spring-security-ldap依赖项,接下来使用 @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来检索角色(因为只有角色在数据库中),那么可以实现自己的 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |