在同一项目中使用内存中身份验证和数据库身份验证

时间:2018-12-20 05:44:05

标签: java spring spring-boot spring-security

我有一个现有项目,该项目正在使用带有Spring Security的InMemory身份验证,现在有一个新要求。现在,我们还需要将基于数据库的身份验证与InMemory身份验证一起使用,因为将有两种类型的用户:一种是静态的,另一种是动态添加的;另一种是动态添加。对于动态添加,我们需要使用基于数据库的身份验证。我在不同的项目中都使用了InMemory和基于数据库的身份验证,但在同一项目中没有都使用过。 请提出在同一项目上同时使用两者的一些解决方案。我使用的是Spring Boot 2.0.2Release,欢迎使用基于Java的解决方案。

@Configuration
@EnableWebSecurity
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Value("${admin.username}")
    String user;

    @Value("${admin.password}")
    String password;

    @Value("${superadmin.username}")
    String admin;

    @Value("${superadmin.password}")
    String adminPassword;

    /* (non-Javadoc)
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
        .antMatchers("/","/blogs","/support","/index","/pricing","/step-guide","/sales-info","/sales-info/**","/step-guide/**","/blogs/**","/productdetail","/25-point-checklist-for-networking","/thanks-for-downloading-checklist","/events-&-conference",,"/share_profile","/share","/share/**").permitAll()
        .antMatchers("/swagger-ui.html").hasAnyAuthority("ROLE_SUPER_ADMIN")
        .antMatchers("/admin").hasAnyAuthority("ROLE_SUPER_ADMIN","ROLE_ADMIN")
        .antMatchers("/api/**").permitAll()
        .anyRequest().authenticated()       
        .and()
        .formLogin()
        .loginPage("/login").permitAll()
        .successHandler(new AuthenticationSuccessHandler() {

            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                    Authentication authentication) throws IOException, ServletException {
                String currentUsername = authentication.getName();
                if(currentUsername.equals(admin)) {
                    response.sendRedirect(request.getContextPath()+"/admin");
                }
                else if(currentUsername.equals(user))
                {
                    response.sendRedirect(request.getContextPath()+"/swagger-ui.html");
                }
            }

        })
        .and()
        .logout()
        .permitAll()
        .and().csrf().disable();


    }

    /* (non-Javadoc)
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder)
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        auth.inMemoryAuthentication()       
        .withUser(user)
        .password(PasswordUtil.encryptPassword(password))
        .credentialsExpired(false)
        .accountExpired(false)
        .accountLocked(false)       
        .roles("SUPER_ADMIN");

        auth.inMemoryAuthentication()
        .withUser(admin)
        .password(PasswordUtil.encryptPassword(adminPassword))
        .credentialsExpired(false)
        .accountExpired(false)
        .accountLocked(false)
        .roles("ADMIN");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**","/webjars/**","/static/**","/css/**","/js/**","/fonts/**","/images/**","/favicon.ico","/swagger-resources/**","/bucket/**");
    }

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

}

具有数据库身份验证和自定义身份验证处理程序的代码是:

@Configuration
@EnableWebSecurity
@Order(Ordered.HIGHEST_PRECEDENCE)
public class SecurityConfig extends WebSecurityConfigurerAdapter{

    @Autowired
    PasswordEncoder passwordEncoder;

    @Autowired
    AppUserDetailsService appUserDetailsService;

    @Autowired
    CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;

    /* (non-Javadoc)
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder)
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(appUserDetailsService).passwordEncoder(passwordEncoder);
    }

    /* (non-Javadoc)
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.WebSecurity)
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/resources/**","/webjars/**","/static/**","/css/**","/js/**","/fonts/**","/images/**","/favicon.ico");
    }

    /* (non-Javadoc)
     * @see org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter#configure(org.springframework.security.config.annotation.web.builders.HttpSecurity)
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
        .antMatchers("/").permitAll()
        .antMatchers("/swagger-ui.html").hasAnyAuthority("ROLE_SUPER_ADMIN")
        .antMatchers("/api/user/sign_up").permitAll()
        .antMatchers("/api/user/forgot_password").permitAll()
        .antMatchers("/api/**").authenticated()
        .anyRequest().authenticated()
        .and()
        .formLogin()
        .loginPage("/login").successHandler(customAuthenticationSuccessHandler).permitAll()     
        .and()
        .logout()
        .permitAll()
        .and().csrf().disable().exceptionHandling().accessDeniedPage("/403");
    }

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

}

所以我想将两者结合起来,根据情况,它可以有一个登录页面或多个登录页面。

3 个答案:

答案 0 :(得分:1)

如果实现WebSecurityConfigurerAdapter,则具有以下功能:

 @Override
 protected void configure(AuthenticationManagerBuilder auth) {

         //   auth.ldapAuthentication()...
        auth.apply(new LdapAuthenticationProviderConfigurer());
        auth.apply(new JdbcUserDetailsManagerConfigurer<>());
        auth.apply(new InMemoryUserDetailsManagerConfigurer<>());
 }

方法ldapAuthentication()除了将LdapAuthenticationProvider添加到AbstractConfiguredSecurityBuilder的配置列表之外,什么也不做。 只需尝试将另一个配置器添加到AuthenticationManagerBuilder。

示例:

InMemoryUserDetailsManagerConfigurer memprovider = 
    new InMemoryUserDetailsManagerConfigurer();

    memprovider.withUser("admin")
            .credentialsExpired(false)
            .accountExpired(false)
            .accountLocked(false)
            .roles("SUPER_ADMIN");
    auth.apply(memprovider);

这将应用新的提供者。而不是简单地应用第二个:

JdbcUserDetailsManagerConfigurer jdpbProvider = 
    new JdbcUserDetailsManagerConfigurer();
    jdpbProvider.withUser("user").password() ...
    auth.apply(jdpbProvider);

使用UserDetailService:

 @Autowired
 UserDetailsService appUserDetailsService;

 DaoAuthenticationConfigurer daoAC = 
     new DaoAuthenticationConfigurer(appUserDetailsService);
 daoAC.passwordEncoder(passwordEncoder);
 auth.apply(daoAC);

答案 1 :(得分:0)

您可以在Spring安全性中使用org.springframework.security.authentication.ProviderManager,并将数据库和InMemory用作providers

答案 2 :(得分:0)

以下设置适用于您的情况:

@Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        DaoAuthenticationProvider daoAuth = new DaoAuthenticationProvider();
        daoAuth.setUserDetailsService(appUserDetailsService);
        daoAuth.setPasswordEncoder(passwordEncoder);

        auth.authenticationProvider(daoAuth);

        auth.inMemoryAuthentication()       
        .withUser(user)
        .password(PasswordUtil.encryptPassword(password))
        .credentialsExpired(false)
        .accountExpired(false)
        .accountLocked(false)       
        .roles("SUPER_ADMIN");

        auth.inMemoryAuthentication()
        .withUser(admin)
        .password(PasswordUtil.encryptPassword(adminPassword))
        .credentialsExpired(false)
        .accountExpired(false)
        .accountLocked(false)
        .roles("ADMIN");
    }