【问题标题】:JHipster ldap AuthenticationJHipster ldap 身份验证
【发布时间】:2015-01-20 02:09:05
【问题描述】:

嘿,Overfloweens 和 JHipsters, 我最近得出的结论是,我想尝试将我的 JHipster 安全协议链接到一个 ldap 服务器,以验证我已经拥有所有员工密码和用户名的工作目录中的身份验证。但是,我想继续使用 JHipster 使用 Spring-mvc 的内置令牌系统。我知道除了 JHipster 之外如何做 ldap 服务器,但我不清楚如何修改 SecurityConfiguration.java 文件以使其成为现实。任何建议将不胜感激。

安全配置文件:

package com.comcast.castit.config;

import javax.inject.Inject;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.StandardPasswordEncoder;
import org.springframework.security.web.authentication.RememberMeServices;

import com.comcast.castit.security.AjaxAuthenticationFailureHandler;
import com.comcast.castit.security.AjaxAuthenticationSuccessHandler;
import com.comcast.castit.security.AjaxLogoutSuccessHandler;
import com.comcast.castit.security.AuthoritiesConstants;
import com.comcast.castit.security.Http401UnauthorizedEntryPoint;

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Inject
    private Environment env;

    @Inject
    private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;

    @Inject
    private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;

    @Inject
    private AjaxLogoutSuccessHandler ajaxLogoutSuccessHandler;

    @Inject
    private Http401UnauthorizedEntryPoint authenticationEntryPoint;

    @Inject
    private UserDetailsService userDetailsService;

    @Inject
    private RememberMeServices rememberMeServices;

    @Bean
    public PasswordEncoder passwordEncoder() {
    return new StandardPasswordEncoder();
    }

    @Inject
    public void configureGlobal(AuthenticationManagerBuilder auth)
        throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(
        passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
    web.ignoring().antMatchers("/bower_components/**")
        .antMatchers("/fonts/**").antMatchers("/images/**")
        .antMatchers("/scripts/**").antMatchers("/styles/**")
        .antMatchers("/views/**").antMatchers("/i18n/**")
        .antMatchers("/swagger-ui/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
    http.exceptionHandling()
        .authenticationEntryPoint(authenticationEntryPoint).and()
        .rememberMe().rememberMeServices(rememberMeServices)
        .key(env.getProperty("jhipster.security.rememberme.key")).and()
        .formLogin().loginProcessingUrl("/app/authentication")
        .successHandler(ajaxAuthenticationSuccessHandler)
        .failureHandler(ajaxAuthenticationFailureHandler)
        .usernameParameter("j_username")
        .passwordParameter("j_password").permitAll().and().logout()
        .logoutUrl("/app/logout")
        .logoutSuccessHandler(ajaxLogoutSuccessHandler)
        .deleteCookies("JSESSIONID").permitAll().and().csrf().disable()
        .headers().frameOptions().disable().authorizeRequests()
        .antMatchers("/app/rest/register").permitAll()
        .antMatchers("/app/rest/activate").permitAll()
        .antMatchers("/app/rest/authenticate").permitAll()
        .antMatchers("/app/rest/logs/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/app/**").authenticated()
        .antMatchers("/metrics/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/health/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/trace/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/dump/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/shutdown/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/beans/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/info/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/autoconfig/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/env/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/trace/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/api-docs/**")
        .hasAuthority(AuthoritiesConstants.ADMIN)
        .antMatchers("/protected/**").authenticated();

    }

    @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
    private static class GlobalSecurityConfiguration extends
        GlobalMethodSecurityConfiguration {
    }
}

【问题讨论】:

    标签: java spring-mvc authentication ldap jhipster


    【解决方案1】:

    默认身份验证机制使用“UserDetailsS​​ervice”实现,在您的项目中应将其称为“com.comcast.castit.security.UserDetailsS​​ervice”。

    此代码有一个简单的“loadUserByUsername”,它根据用户的登录名获取用户并获取他的权限。

    根据您的需要,您应该更改这部分 -> 这不会影响应用程序的其余部分,这很好(Spring Security 就是为此而设计的)

    有一个使用 LDAP 和 Spring Security / Spring Boot 的教程,你可以在这里查看:https://spring.io/guides/gs/authenticating-ldap/

    当然,如果我们有 JHipster 的特定文档会更好,所以如果您成功并有时间,我们将非常欢迎您的反馈!

    【讨论】:

      【解决方案2】:

      从 SecurityConfig.java 中删除以下代码片段

      @Override
      @Bean
      public AuthenticationManager authenticationManagerBean() throws Exception {
      return (AuthenticationManager) ldapAuthenticationManager;
      }
      

      然后创建一个 LDAPAuthenticationManager 类

      package com.digitronic.isda.security;
      
      import org.springframework.ldap.core.AuthenticationSource;
      import org.springframework.ldap.core.support.LdapContextSource;
      import org.springframework.security.authentication.AuthenticationManager;
      import org.springframework.security.core.Authentication;
      import org.springframework.security.core.AuthenticationException;
      import org.springframework.security.ldap.DefaultSpringSecurityContextSource;
      import org.springframework.security.ldap.authentication.BindAuthenticator;
      import org.springframework.security.ldap.authentication.LdapAuthenticationProvider;
      import org.springframework.security.ldap.search.FilterBasedLdapUserSearch;
      import org.springframework.stereotype.Component;
      
      @Component("authenticationManagerBean")
      public class LDAPAuthenticationManager implements AuthenticationManager {
      
      
          LdapAuthenticationProvider provider = null;
      
          @Override
          public Authentication authenticate(Authentication arg0)
                  throws AuthenticationException {
      
              return provider.authenticate(arg0);
          }
      
          LDAPAuthenticationManager() {
      
              DefaultSpringSecurityContextSource contextSource = new DefaultSpringSecurityContextSource(
                      "ldap://127.0.0.1:389");
              contextSource.setUserDn("test.com\\Administrator");
              contextSource.setCacheEnvironmentProperties(true);
              try {
                  contextSource.afterPropertiesSet();
              } catch (Exception e) {
      
                  e.printStackTrace();
              }
              contextSource.setPassword("asdasdasdjBj,K");
      
              LdapContextSource ldapSrc = new LdapContextSource();
              ldapSrc.setUrl("ldap://127.0.0.1:389");
              ldapSrc.setUserDn("test.com\\Administrator");
              ldapSrc.setPassword("asdasdasdjBj,K");
              ldapSrc.setAnonymousReadOnly(false);
              ldapSrc.setCacheEnvironmentProperties(true);
      
              try {
                  ldapSrc.afterPropertiesSet();
              } catch (Exception e) {
                  e.printStackTrace();
              }
      
              ldapSrc.setAuthenticationSource(new AuthenticationSource() {
      
                  @Override
                  public String getPrincipal() {
                      // TODO Auto-generated method stub
                      return "test.com\\Administrator";
                  }
      
                  @Override
                  public String getCredentials() {
                      // TODO Auto-generated method stub
                      return "asdasdasdjBj,K";
                  }
              });
      
              FilterBasedLdapUserSearch userSearch = new FilterBasedLdapUserSearch(
                      "cn=Users,dc=digitronic,dc=lan", "(sAMAccountName={0})",
                      ldapSrc);
      
              BindAuthenticator bindAuth = new BindAuthenticator(contextSource);
              bindAuth.setUserSearch(userSearch);
              provider = new LdapAuthenticationProvider(bindAuth);
          }
      }
      

      【讨论】:

      • @Component("authenticationManagerBean") 也将是必需的,因为 jhibster 代码中没有提到它。
      【解决方案3】:

      如果你需要一个 UserDetailsContextMapper (For Authorities) 添加这个:

      provider.setUserDetailsContextMapper(new UserDetailsContextMapper() {
      
              @Override
              public void mapUserToContext(UserDetails user, DirContextAdapter ctx) {
                  // TODO Auto-generated method stub
      
              }
      
              @Override
              public UserDetails mapUserFromContext(DirContextOperations ctx,
                      String username,
                      Collection<? extends GrantedAuthority> authorities) {
      
                  User anwender = userRepository.findOneByAnwender(username);
      
                  Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>();
                  GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(
                          "ROLE_ADMIN");
                  grantedAuthorities.add(grantedAuthority);
      
                  return new org.springframework.security.core.userdetails.User(
                          username, "1", grantedAuthorities);
              }
          });
      

      【讨论】:

        【解决方案4】:

        SecurityConfiguration.java 中将configureGlobal 函数更改为:

        @Inject
        public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
            /*auth
                .userDetailsService(userDetailsService)
                    .passwordEncoder(passwordEncoder());*/
        
            auth.ldapAuthentication()
            .userSearchBase("ou=Users")
            .userSearchFilter("(uid={0})")
            .groupSearchBase("ou=Groups")
            .groupSearchFilter("member={0}")
            .contextSource()
            .url("ldap://127.0.0.1:10389/o=myorganisation");
        }
        

        前面的代码我已经注释掉了。 然后您的应用程序将通过您的 ldap 服务器进行身份验证。它仍会检查数据库中的用户详细信息,如果用户表中不存在该用户,您将遇到以下问题: userRepository.findOneByLogin(login) 使用现有用户名在数据库中搜索用户。

        但身份验证将使用您的 ldap 凭据进行。

        【讨论】:

          【解决方案5】:

          为了使用 LDAP 维护 JHipster 的内置令牌系统,我采用了不同的方法。 每当用户尝试登录时,我都会在 LDAP 服务器中搜索他的凭据,如果存在,则会在本地数据库中使用其 LDAP 属性创建一个新用户,然后所有功能都可以正常工作。

          以下类仅用于获取 LDAP 服务器的上下文和用户属性。

          public class LDAPHelper {
          
          private static LDAPHelper instance = null;
          
          protected LDAPHelper() {
              // Exists only to defeat instantiation
          }
          
          public static LDAPHelper getInstance() {
              if (instance == null) {
                  instance = new LDAPHelper();
              }
              return instance;
          }
          
          public boolean validateLogin(String username, String password) {
              return (getLdapContext(username, password) != null);
          }
          
          private LdapContext getLdapContext(String username, String password) {
              Hashtable<String, String> env = new Hashtable<String, String>();
          
              env.put(Context.INITIAL_CONTEXT_FACTORY,
                      "com.sun.jndi.ldap.LdapCtxFactory");
              env.put("com.sun.jndi.ldap.read.timeout", "120000");
              env.put(Context.SECURITY_AUTHENTICATION, "Simple");
              env.put(Context.SECURITY_PRINCIPAL, "VF-ROOT\\" + username);
              env.put(Context.SECURITY_CREDENTIALS, password);
              env.put(Context.PROVIDER_URL, "*ldap url*");
              System.out.println(username);
              try {
                  return new InitialLdapContext(env, null);
              } catch (NamingException e) {
                  return null;
              }
          }
          
          public User getUserAttributes(String username, String password)
                  throws NamingException { ... }
          

          在 AccountResource 中,我更改了 register 方法以在 LDAP 服务器中搜索用户,如果用户存在,我将他添加到本地数据库(如果尚未添加)。 您在登录之前调用此方法以确保只有 LDAP 服务器中的用户才能登录您的应用程序。

               @RequestMapping(value = "/register", method = RequestMethod.POST, produces = { MediaType.APPLICATION_JSON_VALUE,
                  MediaType.TEXT_PLAIN_VALUE })
          @Timed
          public ResponseEntity<?> registerAccount(@Valid @RequestBody ManagedUserDTO managedUserDTO,
                  HttpServletRequest request) {
          
              HttpHeaders textPlainHeaders = new HttpHeaders();
              textPlainHeaders.setContentType(MediaType.TEXT_PLAIN);
          
              // user exists in LDAP server
              if (LDAPHelper.getInstance().validateLogin(managedUserDTO.getLogin(), managedUserDTO.getPassword())) {
          
                  // user was already created in the local database
                  if (userRepository.findOneByLogin(managedUserDTO.getLogin().toLowerCase()).isPresent()) {
          
                      return new ResponseEntity<>("user exists in database", textPlainHeaders, HttpStatus.OK);
          
                  } else {
          
                      try {
                          User userAux = LDAPHelper.getInstance().getUserAttributes(managedUserDTO.getLogin(), managedUserDTO.getPassword());                             
          
                          User user = userService.createUserInformation(managedUserDTO.getLogin(), managedUserDTO.getPassword(), userAux.getFirstName(),
                                  userAux.getLastName(), userAux.getEmail(), managedUserDTO.getLangKey());                                        
          
                          } catch (NamingException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                          }
          
                          return new ResponseEntity<>("user created in database", textPlainHeaders, HttpStatus.OK);
                      }
                  } else {
                      return new ResponseEntity<>("user does not exist in ldap", textPlainHeaders, HttpStatus.UNAUTHORIZED);
                  }
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2015-03-07
            • 2017-06-03
            • 2011-09-23
            • 2017-01-09
            • 2015-05-06
            • 2018-05-31
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多