当前位置: 首页 > 知识库问答 >
问题:

spring security,UserDetailsService,authenticationProvider,pass word我迷路了

唐法
2023-03-14

例如,下面的代码试图处理一个简单的登录,使用密码编码器对db表进行身份验证。表单post包括一个“客户端”,一个持久化的IP地址和一些url路径信息,以便在登录后进行深度链接。(对于今天的单页web应用程序来说,这些都是非常基本的东西)我最初使用xml config工作,但是javaConfig让我陷入了困境。

我不知道userDetailsService,AuthenticationManagerBuilder和PasswordEncoder在SecurityConfiguration中是如何交互的。我获取服务的登录数据,但不确定spring authenticationProvider在何处或何时应用,或者我是否需要一个。

我的用户实现UserDetails并保存必需的字段。我在CustomUserDetailsService中填充这些和授予的权限。如果我在服务中使用登录/密码检查db,我如何/何时/为什么需要auth.authenticationProvider(authenticationProvider())?

我的UserDetailsService现在似乎html" target="_blank">执行了两次。

为什么我的大脑那么小,我无法理解这些?:)

@Service
public class CustomUserDetailsService implements UserDetailsService {

@Autowired
private ClientDAO clientDAO;
@Autowired
private UserDAO userDAO;


public UserDetails loadUserByUsername(String multipartLogon) throws UsernameNotFoundException, DataAccessException {

    Boolean canAccess = false;
    Long clientId = null;
    String userLogon = null;
    String password = null;
    String id = null;
    String entryUrl = null;
    String ipAddress = null;
    String urlParam = null;
    String[] strParts = multipartLogon.split(":");
    try {
        userLogon = strParts[0];
        password = strParts[1];
        id = strParts[2];
        entryUrl = strParts[3];
        ipAddress = strParts[4];
        urlParam = strParts[5];
    } catch(IndexOutOfBoundsException ioob) { }
    Client client = new Client();
    if (!"".equals(id)) {
        clientId = IdUtil.toLong(id);
        client = clientDAO.getClient(clientId);
    }

    //BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    //String encodedPassword = passwordEncoder.encode(password);

    //String encodedPassword = "$2a$22$6UiVlDEOv6IQWjKkLm.04uN1yZEtkepVqYQ00JxaqPCtjzwIkXDjy";


    User user = userDAO.getUserByUserLogonPassword(userLogon, password); //encodedPassword?
    user.isCredentialsNonExpired = false;
    Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
    for (UserRole userRole : userDAO.getUserRolesForUser(user)) {
        if (userRole.getRole().getActiveStatus()) {
            authorities.add(new SimpleGrantedAuthority(userRole.getRole().getRoleName()));
            user.isCredentialsNonExpired = true;
        }
    }       
    user.setAuthorities(authorities);
    user.setPassword(password); //encodedPassword?
    user.setUsername(user.getUserLogon());
    user.isAccountNonExpired = false;
    user.isAccountNonLocked = false;

    List<ClientUser> clientUsers = clientDAO.getClientUsersForUser(user);
    for (ClientUser clientUser : clientUsers) {
        if (clientUser.getClient().getClientId().equals(client.getClientId())) {
            canAccess = true;
            break;
        }
    }

    user.isEnabled = false;
    if (user.getActiveStatus() && canAccess) {
        user.isAccountNonExpired = true;
        user.isAccountNonLocked = true;
        user.isEnabled = true;

        Session session = userDAO.getSessionForUser(user);
        if (session == null) { session = new Session(); }
        session.setUser(user);
        session.setDateLogon(Calendar.getInstance().getTime());
        session.setClient(client);
        session.setEntryUrl(entryUrl);
        session.setUrlParam(urlParam);
        session.setIPAddress(ipAddress);
        session.setActive(true);
        userDAO.persistOrMergeSession(session);
    }
    return user;
}

}
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
CustomUserDetailsService customUserDetailsService;


@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(customUserDetailsService);
    auth.authenticationProvider(authenticationProvider());
}


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


@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
    authenticationProvider.setUserDetailsService(customUserDetailsService);
    authenticationProvider.setPasswordEncoder(passwordEncoder());
    return authenticationProvider;
}


@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .csrf().disable()

        .authorizeRequests()
            .antMatchers("/conv/a/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_COURT_ADMIN')")
            .antMatchers("/conv/u/**").access("hasRole('ROLE_USER') or hasRole('ROLE_ADMIN') or hasRole('ROLE_COURT_ADMIN')")
            .antMatchers("/**").permitAll()
            .and()

        .formLogin()
            .loginPage("/conv/common/logon")
            .usernameParameter("multipartLogon")
            .loginProcessingUrl("/conv/common/logon")
            .defaultSuccessUrl("/conv/")
            .failureUrl("/conv/common/logon?error=1")
            .and()

        .logout()
            .logoutUrl("/conv/common/logout")
            .logoutSuccessUrl("/conv/")
            .permitAll()
            .and()

        .rememberMe()
            .key("conv_key")
            .rememberMeServices(rememberMeServices())
            .useSecureCookie(true);
}


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


@Bean
public RememberMeServices rememberMeServices() {
    TokenBasedRememberMeServices rememberMeServices = new TokenBasedRememberMeServices("conv_key", customUserDetailsService);
    rememberMeServices.setCookieName("remember_me_cookie");
    rememberMeServices.setParameter("remember_me_checkbox");
    rememberMeServices.setTokenValiditySeconds(2678400); //1month
    return rememberMeServices;
}

}

共有1个答案

容磊
2023-03-14

我的用户实现UserDetails并保存必需的字段。我在CustomUserDetailsService中填充这些和授予的权限。如果我在服务中使用登录/密码检查db,我如何/何时/为什么需要auth.authenticationProvider(authenticationProvider())?

我想你想要的是:

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

userDetailsService方法是创建DAOAuthenticationProviderbean的快捷方式!您不应该同时需要这两种,它只是两种不同的方式来配置相同的东西。authenticationProvider方法用于更多自定义设置。

spring如何接受提交的密码,对其进行编码,并与存储在DB中的密码进行比较?它如何知道使用与创建P/W时使用的盐相同的盐/在创建用户时持久化的盐?

如果您使用的是BCrypt,salt将存储在编码的密码值中。salt是第三个$(美元)符号后的前22个字符。matches方法负责检查密码。

为什么configureGlobal()同时定义Auth.UserDetailsService和Auth.authenticationProvider()同时设置UserDetailsService?

见上文。这可能是用户详细信息加载两次的原因。

更新:奇怪的是,你将密码和其他细节放入你的UserDetailsService。这应该只根据用户名加载user,如下所示:

User user = userDAO.getUserByUserLogonPassword(userLogon);

返回的用户对象应该包含编码的(存储的)密码,而不是输入的密码。Spring Security为您执行密码检查。不应修改UserDetailsService中的User对象。

 类似资料:
  • function getCarData() { return [ {id: 1, name: {first: "Chris", last: "Right"}, password: "plainTextPassword"}, {id: 2, name: {first: "John", last: "Honest"}, password: "txt"}, {id: 3, name: {fi

  • 以下示例描述了如何使用Spring Web MVC框架在表单中使用Password。 首先,让我们使用一个可用的Eclipse IDE,并遵循以下步骤使用Spring Web Framework开发基于动态表单的Web应用程序。 步 描述 1 在Spring MVC - Hello World章节中解释,在com.wenjiangs包下创建一个名为HelloWeb的项目。 2 在com.wenji

  • 主要内容:1.入门,2.设置用户名和密码1.入门 1.启动一个SpringBoot项目 2.导入SpringSecurity相关依赖 3.编写Controller TestController.java 用户是user 密码是刚刚的 2.设置用户名和密码 1.在配置文件中设置 2.在配置类中设置 3.自定义实现类 2.1 配置文件中设置 2.2 在配置类中设置 设置用户名为zZZ,密码为root 2.3 自定义实现类 配置类: 业务类:

  • 试图了解使用Spring Security实现OpenID身份验证的正确方法。 我正在考虑用户尚未在我的应用程序中注册的情况。要注册用户,我需要知道它的OpenID和电子邮件。 当OpenID提供者将用户重定向回我的应用程序时,将调用,但在这种情况下,我只知道用户的OpenID。因此,我抛出,然后,因此无法注册用户。 这里常见的解决办法是什么?如果从返回类似,然后在调用时注册用户,然后返回真正的呢

  • 我是Spring Security的新手,我试图实现自定义的身份验证。令我困扰的是,这个接口只包含一个方法,它只将用户名作为参数并返回。 我想知道为什么这个方法不接受任何密码作为参数。 Spring是如何只根据用户名对用户进行身份验证的?

  • WinSCP can protect stored passwords by strong AES cipher. In order to protect such sensitive information you need to set a master password. When a master password is not set, stored passwords can be e