【Spring Security系列】Spring Security 过滤器详解与基于JDBC的认证实现

前言

上文说到,Spring Security它是一个强大的和高度可定制的身份验证和访问控制框架。它提供了一套丰富的功能,用于保护基于Spring的应用程序。

上文又说到,在Spring Security中,过滤器(Filter)是一个重要的组件,用于处理身份验证、授权和其他安全相关的任务。

Spring Security 过滤器概述

Spring Security 的过滤器链由多个过滤器组成,每个过滤器负责处理特定的安全任务。当请求到达应用程序时,它会依次通过过滤器链中的每个过滤器,直到到达目标资源。

在过滤器链中,每个过滤器都可以对请求进行拦截、修改或执行其他操作,以确保应用程序的安全性。

Spring Security 主要过滤器介绍

这里先列举一些Spring Security中常用的过滤器:

  • SecurityContextPersistenceFilter:负责将安全上下文存储在HttpSession中,以便在后续请求中访问。
  • UsernamePasswordAuthenticationFilter:处理基于表单的身份验证。它拦截包含用户名和密码的请求,并执行身份验证过程。
  • LogoutFilter:处理注销请求,清除安全上下文和会话数据。
  • ExceptionTranslationFilter:捕获并处理认证和授权过程中发生的异常。
  • FilterSecurityInterceptor:根据安全配置决定是否允许访问特定的资源。

更详细的请看下图:

基于JDBC的认证实现

基于JDBC的认证是指使用关系型数据库(如MySQL、Oracle等)存储用户凭据(用户名和密码),并通过JDBC进行身份验证的过程。

如何实现基于JDBC的认证呢,接下来我们以一个课设作栗子来学习一下!

首先,我们需要在Spring配置中配置数据源,以便能够连接到我们的数据库。

复制代码
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>  
    <property name="url" value="jdbc:mysql://localhost:3306/xiaowei"/>  
    <property name="username" value="xiaoweiya"/>  
    <property name="password" value="123456"/>  
</bean>

我们的数据库表,也列到这里吧,虽然语句短小精悍:

复制代码
CREATE TABLE users (  
    id INT AUTO_INCREMENT PRIMARY KEY,  
    username VARCHAR(50) NOT NULL,  
    password VARCHAR(50) NOT NULL  
);

实现UserDetailsService接口,以便Spring Security能够查询数据库以获取用户详细信息。在这个实现中,我们需要使用JDBC来查询用户表。

复制代码
@Service  
public class JdbcUserDetailsService implements UserDetailsService {  
    @Autowired  
    private JdbcTemplate jdbcTemplate;  
  
    @Override  
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {  
        String sql = "SELECT id, username, password FROM users WHERE username = ?";  
        User user = jdbcTemplate.queryForObject(sql, new Object[]{username}, new BeanPropertyRowMapper<>(User.class));  
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), new ArrayList<>());  
    }  
}

最后,配置Spring Security使用我们的UserDetailsService实现和JDBC数据源。在配置中,我们需要启用基于表单的身份验证,并设置安全约束。

复制代码
@Configuration  
@EnableWebSecurity  
public class SecurityConfig extends WebSecurityConfigurerAdapter {  
    @Autowired  
    private JdbcUserDetailsService userDetailsService;  
  
    @Override  
    protected void configure(HttpSecurity http) throws Exception {  
        http  
            .authorizeRequests()  
                .antMatchers("/login").permitAll()  
                .anyRequest().authenticated()  
                .and()  
            .formLogin()  
                .loginPage("/login")  
                .permitAll()  
                .and()  
            .logout()  
                .permitAll();  
    }  
  
    @Override  
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {  
        auth.userDetailsService(userDetailsService);  
        auth.passwordEncoder(passwordEncoder());  
    }  
  
    @Bean  
    public PasswordEncoder passwordEncoder() {  
        return new BCryptPasswordEncoder();  
    }  
}

在最后的代码中,我们用到了BCrypt,它是一款加密工具,可以比较方便地实现数据的加密工作。也可以简单理解为它内部自己实现了随机加盐处理。那它和MD5加密有什么区别呢?

使用MD5加密,每次加密后的密文其实都是一样的,这样就方便了MD5通过大数据的方式进行破解。

BCrypt生成的密文长度是60,而MD5的长度是32。

现在,我们启动项目,当用户尝试登录时,Spring Security将调用我们提供的JdbcUserDetailsService实现来验证用户凭据。这个实现使用JDBC从数据库中查询用户信息,并且返回给Spring Security进行验证。如果用户名和密码匹配,用户将被成功认证,并获得访问应用程序的权限。

文章到这里就先结束了,后续会继续分享相关的知识点。

相关推荐
tyn1884 分钟前
记录本地安装nacos服务的方法及异常
java·开发语言
步行cgn38 分钟前
Spring MVC 视图机制的核心接口与类
java·开发语言·后端·spring·mvc
y1su1 小时前
Leetcode 字符串模板
java·数据结构·算法·leetcode·职场和发展·动态规划
码事漫谈1 小时前
AI 读你的提示词,其实很没耐心
后端
用户8356290780512 小时前
如何使用 Python 格式化 Excel 单元格中的长文本
后端·python
我命由我123452 小时前
Python 开发 - Python 的 pathlib
java·开发语言·后端·python·学习·java-ee·学习方法
IT_陈寒2 小时前
Java性能优化完全指南
前端·人工智能·后端
电子IT笔记2 小时前
对接群晖NAS,上传和删除踩坑记录
前端·后端
Mk598782 小时前
P4:把 Agent 的记忆搬进 Redis —— AgentScope-Java 工程化实战
后端
雨中飘荡的记忆2 小时前
Claude Code 入门必会:@、!、Slash Commands,一篇讲清楚
人工智能·后端