简体   繁体   English

如何使用Spring Security验证两种不同类型的用户?

[英]How to use spring security to authenticate two different types of users?

In my spring boot application, I will have two different types of users ie 在我的spring boot应用程序中,我将有两种不同类型的用户,即

  1. Admin users 管理员用户
  2. customers 顾客

These users will be stored in two different tables. 这些用户将存储在两个不同的表中。 These two tables will have only email id in common. 这两个表仅具有共同的电子邮件ID。 Everything else will be different. 其他一切都会有所不同。

Also, the no. 另外,没有。 of customers will be huge like 1 to 5 Millions customers. 的客户将是巨大的,如1-5百万客户。 While on the other hand, admin users will be very few like less than 10. Hence the two different tables. 另一方面,管理员用户很少,少于10个。因此,存在两个不同的表。

I want to have two different login pages. 我想要两个不同的登录页面。 One at /customer/login for all the customer and another at /admin/login for all the admins. 对于所有客户,一个在/ customer / login上,对于所有管理员,一个在/ admin / login上。 Login details should be authenticated using their respective tables. 登录详细信息应使用其各自的表进行身份验证。 On login customers should go to /customer/home and admins should go to /admin/home. 登录时,客户应转到/ customer / home,管理员应转到/ admin / home。

On logout customer should be redirected to /customer/login and admin to /admin/login 注销时,应将客户重定向到/ customer / login,将admin重定向到/ admin / login

I am using java config for Spring security. 我正在为春季安全使用Java配置。 How can this be done in spring security? 在Spring Security中如何做到这一点?

Below is my configuration for single user which works properly. 以下是我的单用户配置,可以正常工作。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AccessDecisionManager accessDecisionManager;

    @Autowired
    private ApplicationProperties applicationProperties;

    @Bean
    public Integer applicationSessionTimeout(){
        return applicationProperties.getSecurity().getSessionTimeout();
    }

    @Bean
    @Autowired
    public AccessDecisionManager accessDecisionManager(AccessDecisionVoterImpl accessDecisionVoter) {
        List<AccessDecisionVoter<?>> accessDecisionVoters = new ArrayList<AccessDecisionVoter<?>>();
        accessDecisionVoters.add(new WebExpressionVoter());
        accessDecisionVoters.add(new AuthenticatedVoter());
        accessDecisionVoters.add(accessDecisionVoter);
        UnanimousBased accessDecisionManager = new UnanimousBased(accessDecisionVoters);
        return accessDecisionManager;
    }

    @Override
    @Autowired
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        PasswordEncoder passwordEncoder = new PasswordEncoder();
        passwordEncoder.setStringDigester(stringDigester());
        return passwordEncoder;
    }

    @Bean
    public PooledStringDigester stringDigester() {
        PooledStringDigester psd = new PooledStringDigester();

        psd.setPoolSize(2);
        psd.setAlgorithm("SHA-256");
        psd.setIterations(1000);
        psd.setSaltSizeBytes(16);
        psd.setSaltGenerator(randomSaltGenerator());

        return psd;
    }

    @Bean
    public RandomSaltGenerator randomSaltGenerator() {
        RandomSaltGenerator randomSaltGenerator = new RandomSaltGenerator();
        return randomSaltGenerator;
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring()
                .antMatchers("/static/**")
                .antMatchers("/i18n/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .exceptionHandling().
                accessDeniedPage("/accessDenied")
                .and()
            .authorizeRequests()
                .accessDecisionManager(accessDecisionManager)
                .antMatchers("/login**").permitAll()
                .antMatchers("/error**").permitAll()
                .antMatchers("/checkLogin**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .loginProcessingUrl("/checkLogin")
                .defaultSuccessUrl("/home?menu=homeMenuOption")
                .failureUrl("/login?login_error=1")
                .usernameParameter("username")
                .passwordParameter("password")
                .permitAll()
                .and()
            .logout()
                .logoutUrl("/logout")
                .logoutSuccessHandler(new LogoutSuccessHandlerImpl())
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true)
                .permitAll()
                .and()
            .headers()
                .frameOptions()
                .disable()
            .and()
                .sessionManagement()
                .maximumSessions(1);
    }

}

Below is my UserDetailsService which checks in db for proper authentication. 下面是我的UserDetailsS​​ervice,它在db中检查正确的身份验证。

@Service("userDetailsService")
public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {

    private static final Logger log = LoggerFactory.getLogger(UserDetailsService.class);

    @Autowired
    private UserService userService;

    @Autowired
    private ModuleService moduleService;

    @Override
    public UserDetails loadUserByUsername(final String userName) throws UsernameNotFoundException, DataAccessException {
        log.debug("Authenticating : {}", userName);

        SecurityUser securityUser = null;

        try {

            User user = userService.findUserByEmail(userName);

            if (user != null) {
                log.debug("User with the username {} FOUND ", userName);
                securityUser = new SecurityUser(user.getEmail(), user.getPassword(), true, true, true, true, getGrantedAuthorities(user.getRole().getId()));
                securityUser.setUser(user);
            } else {
                log.debug("User with the username {}  NOT FOUND", userName);
                throw new UsernameNotFoundException("Username not found.");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return securityUser;
    }

    private List<GrantedAuthority> getGrantedAuthorities(Long roleId) {
        log.debug("Populating user authorities");

        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        List<Module> allModules = moduleService.findAllModules();
        Map<Long, Module> moduleMap = new HashMap<Long, Module>();

        for(Module module : allModules){
            moduleMap.put(module.getModuleId(), module);
        }

        List<ModuleOperation> moduleOperationList = moduleService.findModuleOperationsByRoleId(roleId);

        for (ModuleOperation moduleOperation : moduleOperationList) {
            moduleOperation.setModuleName(moduleMap.get(moduleOperation.getModuleId()).getModuleName());
            authorities.add(moduleOperation);
        }

        return authorities;
    }
}

It is really a bad idea to have different login pages for Spring security, because it is not the way it is designed for. 对于Spring安全性,拥有不同的登录页面确实是一个坏主意,因为这不是它设计的目的。 You are going to fall into trouble to define the authentication entry point to use and will need a lot of boiling plate. 您将难以定义要使用的身份验证入口点,并且将需要很多沸腾的盘子。 According to your other requirements, I would propose you the following way: 根据您的其他要求,我建议您采取以下方式:

  • use one single login page with one single AuthenticationManager (the default ProviderManager will be fine) 使用一个登录页面和一个AuthenticationManager (默认的ProviderManager会很好)
  • configure it with two different AuthenticationProvider s, both being DaoAuthenticationProvider , each pointing on one of you 2 user tables 使用两个不同的AuthenticationProvider对其进行配置,这两个都是DaoAuthenticationProvider ,每个都指向您2个用户表之一
  • configure those provider to automatically set different roles, ROLE_ADMIN for the former that will process admins, ROLE_USER for the latter 配置这些提供程序以自动设置不同的角色,ROLE_ADMIN为前者处理管理员,ROLE_USER为后者

That way you fully rely on SpringSecurity infrastructure with as little modifications as possible to meet your requirements. 这样,您就可以完全依靠SpringSecurity基础结构,并进行尽可能少的修改以满足您的需求。

But you should also wonder whether you really need different databases. 但是您还应该怀疑您是否真的需要其他数据库。 At least for the major providers (Oracle, PostgreSQL, MariaDB, ...) there is no harm in having many null columns in a record. 至少对于主要提供程序(Oracle,PostgreSQL,MariaDB等)而言,在记录中包含许多空列没有什么害处。 IMHO you should do a serious analysis to compare both ways, either one single table (much simpler to setup for Spring Security) or two tables. 恕我直言,您应该进行认真的分析以比较这两种方式,一个表(对于Spring Security而言,它更容易设置)或两个表。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用Spring Security OAuth2验证不同的用户类型 - Authenticate different user types with Spring Security OAuth2 在Spring Security中,如何使用jdbc从Oracle数据库认证用户? - How to authenticate users from an oracle database using jdbc in spring security? Spring Security-如何通过不同的用户列出对象 - Spring Security - how to list objects by different Users 如何在Spring Security中实现不同类型的用户 - How to implement different type of users in Spring Security 如何在 spring security 中为来自两个不同表的不同用户配置身份验证? - How to configure authentication in spring security for different users from two different tables? 如何使用Spring Security以编程方式验证`User`并使用我的`UserDetailsS​​ervie`实现? - How to programmatically authenticate `User` with spring security and use my `UserDetailsServie` implementation? 如何使用spring安全性和spring boot来验证Google用户,将mongoDB作为存储库? - How to authenticate Google users by using spring security and spring boot, having mongoDB as repository? 如何使用带有Spring Security 5.1+的Google OIDC对用户进行身份验证 - How can I authenticate users using google OIDC with Spring Security 5.1+ Spring Security Token身份验证如何进行身份验证? - Spring Security Token Authentication How to Authenticate? 如何使用 Spring Security + Angular 登录/验证 - How to login/authenticate with Spring Security + Angular
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM