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

Spring Security 过滤器概述

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

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

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

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

Spring Security 主要过滤器介绍

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

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

更详细的请看下图:

基于JDBC的认证实现

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

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

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

csharp 复制代码
<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>

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

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

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

java 复制代码
@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数据源。在配置中,我们需要启用基于表单的身份验证,并设置安全约束。

java 复制代码
@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进行验证。如果用户名和密码匹配,用户将被成功认证,并获得访问应用程序的权限。

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

相关推荐
一只爱撸猫的程序猿2 小时前
我看着一个 AI 引擎在 14 天里,从"记忆"走进了"搜索"
人工智能·后端·架构
陈随易5 小时前
纯 Go 写的 JS 引擎,跑分超过了 C 语言的 QuickJS
前端·后端·程序员
卷无止境5 小时前
RAGFlow 项目全景报告:从文档解析引擎到 Agent 原生数据库
后端·python
小Z先生6 小时前
我用 Go + 系统 WebView 写了个纯本地 Postman:不装 Electron、不连云端
后端·github
IT_陈寒6 小时前
Redis连接池泄漏那次,我差点把生产环境搞崩了
前端·人工智能·后端
灿飞屋7 小时前
Kotlin与Java虚拟机三:控制流
android·java·开发语言·后端·python·kotlin·安卓
石小石Orz7 小时前
AI 正在蚕食我们的编码能力
前端·后端·算法
陈随易7 小时前
专注飞机 FocusFlight,两个人把番茄钟做成了一趟航班
前端·后端·程序员
量化分析码农7 小时前
【Python量化波动率实战 04】低波动异象:低波组真的跑赢高波组吗
后端
风上猫8 小时前
MySQL多值索引:让 JSON 数组也能走索引(以及 6 个容易踩的坑)
后端