Spring Security 入门与实战指南(第一版)


注:完整笔记可在 https://github.com/WuSangui571/SpringSecurity 中的 README.md 文件浏览,此处发表的是经由 GPT 润色过的精简版。

第 1 章 Spring Security 基础

1.1 默认登录流程

  1. 引入依赖:Spring Boot、Spring Security。

  2. 在 Controller 中定义一个 /hello 的映射方法。

  3. 启动后访问 /hello,框架会自动重定向到 /login 页面,默认用户名为 user,密码为启动日志中输出的临时密码。

  4. 登录成功后,未关闭浏览器再次访问 /hello 时即可直接访问。

1.2 核心机制简介

  • 过滤器链(Filter Chain):Spring Security 默认包含多达 16 个过滤器,负责拦截和处理请求。

  • Session 机制:基于内嵌 Tomcat 的 Session 与浏览器 SESSIONID 绑定,开发者工具中可查看 SESSIONID,框架据此判断登录状态。

  • 默认登录/退出页面:由 DefaultLoginPageGeneratingFilterDefaultLogoutPageGeneratingFilter 自动生成,登录 URI 为 /login,退出 URI 为 /logout

  • 配置文件自定义账号:在 application.yml 中添加:

    spring:
    security:
      user:
        name: sangui
        password: your-password

但生产环境常用从数据库获取用户信息。

第 2 章 基于数据库的身份认证

Spring Security 结合 MySQL,通过数据库表实现自定义账号密码登录。

2.1 数据库表设计

创建 t_user 表,至少包含:

  • login_act:账户名

  • login_pwd:密码(存储加密后密文)

CREATE TABLE t_user (
id INT AUTO_INCREMENT PRIMARY KEY,
login_act VARCHAR(50) NOT NULL UNIQUE,
login_pwd VARCHAR(100) NOT NULL
);

2.2 MyBatis 持久层配置

  1. 实体类TUser,对应表字段。

  2. Mapper 接口TUserMapper,定义 TUser selectByLoginAct(String loginAct);

  3. XML 映射:在 src/main/resources/mappers/TUserMapper.xml 中编写 SQL。

  4. 配置:在 application.yml 中添加:

    spring:
    datasource:
      url: jdbc:mysql://localhost:3306/your-db
      username: your-user
      password: your-pwd
      driver-class-name: com.mysql.cj.jdbc.Driver
    mybatis:
    mapper-locations: classpath:/mappers/*.xml

2.3 UserDetailsService 实现

  1. 接口继承public interface UserService extends UserDetailsService

  2. 实现类UserServiceImpl

    @Service
    public class UserServiceImpl implements UserService {
       @Autowired
       private TUserMapper tUserMapper;

       @Override
       public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
           TUser tUser = tUserMapper.selectByLoginAct(username);
           if (tUser == null) {
               throw new UsernameNotFoundException("用户不存在");
          }
           return User.builder()
                  .username(tUser.getLoginAct())
                  .password(tUser.getLoginPwd())
                  .authorities(AuthorityUtils.NO_AUTHORITIES)
                  .build();
      }
    }

2.4 密码加密与配置

登录时报错:

Given that there is no default password encoder configured...

解决:在配置类中注入 BCryptPasswordEncoder

@Configuration
public class SecurityConfig {
   @Bean
   public PasswordEncoder passwordEncoder() {
       return new BCryptPasswordEncoder();
  }
}

数据库中存储的 login_pwd 应使用 passwordEncoder.encode(rawPassword) 加密后值。

2.5 登录流程分析

  1. 访问 /hello,被过滤器链拦截。

  2. 未登录时跳转 /login

  3. 输入数据库中账号密码,提交表单。

  4. UsernamePasswordAuthenticationFilter 调用 loadUserByUsername 查询并返回 UserDetails

  5. 框架依次执行状态检查、密码匹配(BCryptPasswordEncoder.matches)。

  6. 匹配成功后保存 AuthenticationSecurityContext,登录完成。

第 3 章 自定义登录页

Spring Security 默认登录页不满足定制需求,可使用 Thymeleaf 自定义登录页面。

3.1 Thymeleaf 登录页

src/main/resources/templates/login.html 编写:


<html xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>登录title>head>
<body>
<form th:action="@{/user/login}" method="post">
 <label>账号:<input type="text" name="username"/>label><br/>
 <label>密码:<input type="password" name="password"/>label><br/>
 <input type="hidden" name="_csrf" th:value="${_csrf.token}"/>
 <button type="submit">登录button>
form>
body>
html>

3.2 SecurityFilterChain 配置

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
   return http
      .formLogin(form -> form
          .loginPage("/toLogin")
          .loginProcessingUrl("/user/login")
      )
      .authorizeHttpRequests(auth -> auth
          .requestMatchers("/toLogin", "/user/login").permitAll()
          .anyRequest().authenticated()
      )
      .csrf().and()
      .build();
}

3.3 CSRF 与登录处理路径

  • 必须添加隐藏域 _csrf,否则 CsrfFilter 会拒绝请求。

  • .loginProcessingUrl("/user/login") 用于指定位于前端表单的提交路径。

至此,访问 /hello 时,未登录跳转自定义登录页,登录后可正常访问。


  • 微信
  • 赶快加我聊天吧
  • QQ
  • 赶快加我聊天吧
  • weinxin
三桂

发表评论 取消回复 您未登录,登录后才能评论,前往登录