gpt4 book ai didi

spring - 自定义 WebSecurityConfigurerAdapter

转载 作者:行者123 更新时间:2023-12-03 16:54:15 26 4
gpt4 key购买 nike

我有这个问题使用 SpringBoot 和 SpringBoot-Security 实现自定义登录身份验证。我做了一个Bitbucket repository作为该线程的引用(在 CustomSecuringWeb branch 内)。首先,这里的大部分评论都遵循Securing a Web Application。教程。

问题是,我很好奇身份验证数据现在如何来自数据库,而不仅仅是内存数据(这在生产线应用程序中很常见)。

在整个过程中,我进行了两次尝试(尽管两次尝试都位于同一个分支上——这对我不利)。

  • 创建了一个自定义 UserDetailsService实现
  • 创建了一个自定义 AbstractUserDetailsAuthentictionProvider实现

  • 我不知道问题出在哪里,但是在检查控制台日志时,两者都返回每个自定义类上的持久性(甚至存储库)DI 为空。

    问题是我怎样才能使这两种尝试都起作用。并且(可能)这两种尝试中的哪一种比另一种更好。

    最佳答案

    首先,这两种方法用于不同的目的,不可互换。

    情况1:
    UserDetailsService纯粹用作 DAO,通过您的身份验证来定位用户信息,并基于该信息验证用户,不应该在 UserDetailsService 内进行身份验证,只是数据访问。
    规范清楚地提到了这一点。这就是你要找的。

    案例2:
    AuthentictionProvider另一方面,用于提供自定义的身份验证方法,例如,如果您想对登录名和密码以外的字段进行自定义身份验证,您可以通过实现 AuthentictionProvider 来实现。并将此对象提供给您的AuthenticationManagerBuilder .我不认为这是你想在你的项目中做的。您只是希望使用默认方式的登录名和密码基于存储在数据库中的用户来实现您的身份验证。
    在上面的案例 1 中,您只实现了 UserDetailsServiceAuthentictionProvider 的实例在 AuthenticationManager 中为您创建通过容器,它是 DaoAuthenticationProvider因为您提供了 UserDetailsS​​ervice,它只不过是系统中用于检索用户进行身份验证的 DAO。

    现在到你的实现,
    在您的配置中,而不是:

      @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    // auth.userDetailsService(new AdminSecurityService());
    auth.authenticationProvider(new AdminSecurityAuthenticationProvider());
    }

    做这样的事情
    @Autowired
    private CustomUserDetailsService userDetailsService;

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

    }

    和你的 CustomUserDetailsService必须执行 org.springframework.security.core.userdetails.UserDetailsService
    @Service
    public class CustomUserDetailsService implements UserDetailsService {

    private final AdminRepository userRepository;

    @Autowired
    public CustomUserDetailsService(AdminRepository userRepository) {
    this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    Admin user = userRepository.findByLogin(username);
    if (user == null) {
    throw new UsernameNotFoundException(String.format("User %s does not exist!", username));
    }
    return new UserRepositoryUserDetails(user);
    }

    private final static class UserRepositoryUserDetails extends Admin implements UserDetails {

    private static final long serialVersionUID = 1L;

    private UserRepositoryUserDetails(User user) {
    super(user);
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
    return AuthorityUtils.createAuthorityList("ROLE_USER");
    }

    @Override
    public String getUsername() {
    return getLogin();//inherited from user
    }

    @Override
    public boolean isAccountNonExpired() {
    return true;//not for production just to show concept
    }

    @Override
    public boolean isAccountNonLocked() {
    return true;//not for production just to show concept
    }

    @Override
    public boolean isCredentialsNonExpired() {
    return true;//not for production just to show concept
    }

    @Override
    public boolean isEnabled() {
    return true;//not for production just to show concept
    }
    //getPassword() is already implemented in User.class
    }

    }

    当然实现取决于您,但您必须能够根据检索到的用户(在您的情况下为 Admin.class)提供用户密码以及该接口(interface)中的其余方法。希望能帮助到你。我没有运行这个例子,所以如果我有一些错别字,请继续询问是否有问题。如果您不需要它,我也会从您的项目中删除“AuthentictionProvider”。

    这里有文档: http://docs.spring.io/spring-security/site/docs/4.0.0.RC1/reference/htmlsingle/#tech-userdetailsservice

    评论后:
    您可以设置 PasswordEncoder在您的配置方法中没有太多麻烦,只需执行以下操作:
     @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);

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

    您可以这样做,因为您可以访问 AbstractDaoAuthenticationConfigurerauth.userDetailsService(userDetailsService) 返回它允许您配置 DaoAuthenticationProvider ,这是您选择使用 UserDetailsService 时的首选提供商.
    你是对的 PasswordEncoder设置在 AuthenticationProvider但你不必
    实现 AuthenticationProvider只需使用从 auth.userDetailsService(userDetailsService) 返回的 convineince 对象并将您的编码器设置在该对象上,该对象将其传递给 AuthenticationPriovider在你的情况下 DaoAuthenticationProvider已经为您创建了。
    就像评论中提到的 roadrunner 一样,您很少需要实现自己的 AuthenticationProvider通常大多数身份验证配置调整都可以使用 AbstractDaoAuthenticationConfigurer 来完成。如上所述,它是从 auth.userDetailsService(userDetailsService) 返回的.

    “如果我想添加密码加密。如果我想进行其他身份验证(例如检查用户是否被锁定、事件、用户是否仍在登录等 [不包括密码哈希])将使用身份验证提供者。”

    不,这是作为标准身份验证机制的一部分为您完成的
    http://docs.spring.io/autorepo/docs/spring-security/3.2.0.RELEASE/apidocs/org/springframework/security/core/userdetails/UserDetails.html
    如果你看界面 UserDetails您将看到,如果上述任何方法返回错误的身份验证将失败。
    实现 AuthenticationProvider在非常非标准的情况下确实需要。框架几乎涵盖了所有标准的东西。

    关于spring - 自定义 WebSecurityConfigurerAdapter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27939020/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com