基于 Spring Security 数据库的身份验证

在上一篇文章中,我们学习了 Spring Security 的实现,使用 In-Memory 配置对用户进行身份验证。在此示例中,我们将学习根据数据库表对用户和角色进行身份验证。

如果您是 Spring Security 的新手,我强烈建议您阅读 Spring Security 的基础知识

执行

为了实现 Spring Security,我们将借助WebSecurityConfigurerAdapter. 要启用 Spring 安全性,我们需要使用@EnableSpringSecurity和注释我们的配置类@Configuration

在此示例中,我们将使用H2 内存数据库来存储我们的用户凭据并获取这些凭据以进行身份​​验证。我们将在应用程序启动期间使用@PostConstruct注释将我们的用户凭据添加到数据库中。

复制
复制
COPY
COPY
@PostConstruct
    public void setup() {
        userRepositoty.save(new UserEntity(1, "shail@mail.com", passwordEncoder.encode("shail@123"), "ROLE_ADMIN"));
        userRepositoty.save(new UserEntity(2, "john@mail.com", passwordEncoder.encode("john@123"), "ROLE_USER"));
    }

为了根据数据库表对我们的用户进行身份验证,我们将使用DaoAuthenticationProvider类和UserDetailsService接口。

  • DaoAuthenticationProvider是其中一种实现,AuthenticationProvider它借助UserDetailsService检索用户名和密码来对用户进行身份验证。
  • UserDetailsService接口有一个只读方法 loadUserByUsername()。我们重写这个方法来编写我们的逻辑来从数据库中获取数据。

    复制
    复制
    COPY
    COPY
    @Component
    public class UserDetailsServiceImpl implements UserDetailsService {
      @Autowired
      private UserRepository userRepository;
    
      @Override
      public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
          UserEntity user = userRepository
                                          .findByUsername(username)
                                          .orElseThrow(() -> new UsernameNotFoundException("INVALID USERNAME"));
    
          UserDetails userDetails = new User(username, user.getPassword(), AuthorityUtils.createAuthorityList(user.getRole()));
    
          return userDetails;
      }
    }
    

我们需要重写作为参数的configure()方法。有一个将 AuthenticationProvider 作为参数的方法;我们将把我们的对象作为参数传递给这个方法。我们还需要告诉我们的 ``DaoAuthenticationProvider我们将使用的密码编码器。WebSecurityConfigurerAdapterAuthenticationManagerBuilderAuthenticationManagerBuilder`authenticationProvider()DaoAuthenticationProviderUserDetailsServiceImpl

复制
复制
COPY
COPY
@Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {

        DaoAuthenticationProvider daoAuthProvider = new DaoAuthenticationProvider();
        daoAuthProvider.setPasswordEncoder(passwordEncoder());
        daoAuthProvider.setUserDetailsService(userDetailsServiceImpl);

        auth.authenticationProvider(daoAuthProvider);

    }

我们还需要覆盖另一个作为参数的configure()方法。在这里,我们将为不同的 URI 模式和这些 URI 模式上允许的角色配置我们的基本安全参数。WebSecurityConfigurerAdapterHttpSecurity

复制
复制
COPY
COPY
@Override
    public void configure(HttpSecurity http) throws Exception {
        // @formatter:off

        http
            .httpBasic().and()
            .authorizeRequests()
            .antMatchers("/h2-console/**").permitAll()
            .antMatchers("/api/admin/**").hasRole("ADMIN")
            .antMatchers("/api/user/**").hasRole("USER")
            .antMatchers("/api/any/**").hasAnyRole("ADMIN", "USER")
            .anyRequest()
            .authenticated()
            .and().formLogin().disable();

        http.csrf().ignoringAntMatchers("/h2-console/**");

        http.headers().frameOptions().sameOrigin();

        // @formatter:on

    }

测试

为了测试我们的实现,让我们创建一个简单的控制器,其中包含一些返回不同消息的 GetMapping。

复制
复制
COPY
COPY
@RestController
@RequestMapping(value = "api")
public class MessageController {

    @GetMapping(value = "/admin/message")
    public String adminMessage(Authentication auth) {
        String role = "";
        for (GrantedAuthority gauth: auth.getAuthorities()) {
                role = gauth.getAuthority();
        }
        return "<h1>Hello, "+ auth.getName()+ " you are "+ role+"</h1>";
    }

    @GetMapping(value = "/user/message")
    public String userMessage(Authentication auth) {
        String role = "";
        for (GrantedAuthority gauth: auth.getAuthorities()) {
                role = gauth.getAuthority();
        }
        return "<h1>Hello, "+ auth.getName()+ " you are "+ role+"</h1>";
    }

    @GetMapping(value = "/any/message")
    public String anyMessage(Authentication auth) {
        String role = "";
        for (GrantedAuthority gauth: auth.getAuthorities()) {
                role = gauth.getAuthority();
        }
        return "<h1>Hello, "+ auth.getName()+ " you are "+ role+"</h1>";
    }
}

现在让我们尝试使用 Postman 来使用这些 API。

输入请求 URL 作为localhost:8080/api/admin/message并在 Authorization 选项卡下,选择 Basic Auth 并提供用户名和密码,然后单击发送。

身份验证成功后,您将能够访问 URL 并将获得输出为 -

如果您尝试通过上述 URL 上的凭据登录,您将收到一条错误消息Forbidden ,因为这仅适用于 ADMIN 角色。

我建议您尝试将其他组合凭据与 URL 资源一起使用,请参阅输出。

概括

在本文中,我们学习了如何实现 Spring Security 并针对数据库对用户进行身份验证,以及如何根据用户角色限制 URL 或资源。

在该系列的后续文章中,我们将继续学习 Spring Security 并查看使用 JWT 和 Spring Security 的身份验证。

最后但并非最不重要的一点是,您总能找到实现的完整源代码 @Github

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值