SpringSecurity_01_入门与认证

【Spring Security】入门:SecurityFilterChain、表单登录与密码加密

🔑 关键词:Java、Spring Security、认证授权、SecurityFilterChain、UserDetailsService、BCrypt


一、什么是 Spring Security?

Spring Security 是 Spring 生态中的安全框架,提供认证(Authentication)、授权(Authorization)和防护性安全机制。

📌 一句话理解:认证是"你是谁",授权是"你能干什么"。Spring Security 帮你搞定这两件事。


二、认证 vs 授权

概念 含义 举例
认证(Authentication) 验证用户身份 登录:用户名+密码
授权(Authorization) 验证用户权限 访问:只有管理员能删除用户

三、核心架构

3.1 请求处理流程

复制代码
客户端请求
    ↓
FilterChain(过滤器链)
    ↓
UsernamePasswordAuthenticationFilter(处理登录)
    ↓
AuthenticationManager(认证管理器)
    ↓
AuthenticationProvider(认证提供者)
    ↓
UserDetailsService(加载用户信息)
    ↓
认证成功 → SecurityContext(存储认证信息)
认证失败 → AuthenticationEntryPoint(返回 401)

3.2 核心组件

组件 职责
SecurityFilterChain 过滤器链,拦截请求进行安全校验
AuthenticationManager 认证管理器,协调认证流程
AuthenticationProvider 认证提供者,执行具体认证逻辑
UserDetailsService 加载用户信息(从数据库查)
SecurityContext 存储当前用户的认证信息
PasswordEncoder 密码编码器(如 BCrypt)

四、Spring Boot 整合 Spring Security

4.1 引入依赖

xml 复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

4.2 默认行为

引入依赖后,Spring Security 自动生效:

  • 所有请求都需要认证

  • 默认用户名:user

  • 默认密码:启动时控制台打印

    Using generated security password: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx


五、自定义安全配置

5.1 SecurityFilterChain 配置

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            // 放行规则
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login", "/register", "/error").permitAll()  // 放行
                .requestMatchers("/admin/**").hasRole("ADMIN")                 // 需要管理员角色
                .anyRequest().authenticated()                                  // 其他请求需要认证
            )
            // 表单登录
            .formLogin(form -> form
                .loginPage("/login")              // 自定义登录页
                .loginProcessingUrl("/doLogin")   // 登录请求路径
                .defaultSuccessUrl("/home")       // 登录成功跳转
                .failureUrl("/login?error")       // 登录失败跳转
                .permitAll()
            )
            // 退出登录
            .logout(logout -> logout
                .logoutUrl("/logout")
                .logoutSuccessUrl("/login?logout")
                .permitAll()
            )
            // CSRF(前后端分离时通常关闭)
            .csrf(csrf -> csrf.disable());

        return http.build();
    }
}

5.2 关键配置说明

方法 作用
permitAll() 无需认证即可访问
authenticated() 需要认证(登录即可)
hasRole("ADMIN") 需要 ADMIN 角色
hasAuthority("user:add") 需要 user:add 权限
anyRequest() 匹配所有其他请求

六、UserDetailsService

6.1 自定义用户DetailsService

java 复制代码
@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 从数据库查询用户
        User user = userMapper.selectByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在:" + username);
        }

        // 查询用户权限
        List<GrantedAuthority> authorities = user.getRoles().stream()
            .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getName()))
            .collect(Collectors.toList());

        // 返回 UserDetails 对象
        return new org.springframework.security.core.userdetails.User(
            user.getUsername(),
            user.getPassword(),
            authorities
        );
    }
}

6.2 UserDetails 说明

属性 说明
username 用户名
password 加密后的密码
authorities 权限列表
isAccountNonExpired() 账号是否未过期
isAccountNonLocked() 账号是否未锁定
isCredentialsNonExpired() 凭证是否未过期
isEnabled() 账号是否启用

七、BCrypt 密码加密

7.1 配置密码编码器

java 复制代码
@Configuration
public class SecurityConfig {

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

7.2 注册时加密密码

java 复制代码
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    public void register(User user) {
        // 加密密码
        String encodedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);
        userMapper.insert(user);
    }
}

7.3 BCrypt 特点

特点 说明
不可逆 单向哈希,无法反解
自带盐值 每次加密结果不同
可调强度 通过 strength 参数控制计算复杂度
安全推荐 目前业界推荐的密码加密方案
java 复制代码
// 验证密码
boolean matches = passwordEncoder.matches("123456", encodedPassword);
// true: 密码匹配, false: 不匹配

八、获取当前登录用户

java 复制代码
@RestController
public class UserController {

    @GetMapping("/current")
    public String currentUser() {
        // 方式一:通过 SecurityContextHolder
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String username = auth.getName();
        Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();

        return "当前用户:" + username + ", 权限:" + authorities;
    }

    // 方式二:通过方法参数注入
    @GetMapping("/current2")
    public String currentUser2(@AuthenticationPrincipal UserDetails userDetails) {
        return "当前用户:" + userDetails.getUsername();
    }
}

九、面试高频问题

Q1:Spring Security 的核心组件有哪些?

答 :SecurityFilterChain(过滤器链)、AuthenticationManager(认证管理器)、AuthenticationProvider(认证提供者)、UserDetailsService(加载用户信息)、SecurityContext(存储认证信息)、PasswordEncoder(密码编码器)。

Q2:Spring Security 的认证流程?

答 :请求到达 FilterChain → UsernamePasswordAuthenticationFilter 拦截登录请求 → 将用户名密码封装为 Authentication 对象 → AuthenticationManager 调用 AuthenticationProvider → AuthenticationProvider 调用 UserDetailsService 加载用户信息 → 比对密码(PasswordEncoder)→ 成功则将认证信息存入 SecurityContext。

Q3:BCrypt 的优点?

答:①不可逆单向哈希;②自动加盐,相同密码每次加密结果不同;③可调节计算强度(strength),随着硬件升级可以增加难度;④是目前业界推荐的密码存储方案。


十、总结

知识点 核心要点
认证与授权 认证=你是谁,授权=你能干什么
SecurityFilterChain 配置安全规则的核心入口
UserDetailsService 从数据库加载用户信息
BCrypt 推荐的密码加密方案
SecurityContext 存储当前用户的认证信息

📝 下一篇预告:《Spring Security 授权与高级功能》,详解 URL/方法级权限控制、CSRF、Remember-Me。

相关推荐
java_nnnn1 小时前
JavaEE进阶-CSS初识
java·前端·css·java-ee·html
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-使用Redis作为缓存产品与TTL配置
java·redis·缓存
谢亮_vipxieliang1 小时前
ValidX 在微服务架构中的验证策略
java·spring boot·spring·spring cloud·hibernate
其实防守也摸鱼1 小时前
内网安全防护实践:从攻击视角理解防御要点
java·前端·安全·架构·自动化·nps
我是小白呀2 小时前
17-企业Workflow引擎怎么选:定时、队列、n8n、Temporal与Camunda
java·开发语言·人工智能·dubbo·workflow
海宇AI2 小时前
零信任架构实战:基于海宇车型识别精准构建自动化车队评估微服务
java·人工智能·架构·自动化
xixiaoyunya2 小时前
Spring Boot 3 统一响应与全局异常处理实战
java·spring boot·后端
一条破秋裤2 小时前
Linux 线程分离与主动取消:pthread_detach、pthread_cancel
java·linux·jvm