Spring Security 实战:从认证授权到 JWT 令牌机制

Spring Security 实战:从认证授权到 JWT 令牌机制

一、前言

安全性是任何后端系统的核心。Spring Security 是 Spring 生态中专门用于提供身份认证与访问控制的强大框架,适用于 Web、微服务、REST 接口等场景。

本篇将带你了解 Spring Security 的认证授权机制,掌握常见的使用方式,并结合 JWT 实现前后端分离的登录方案。


二、Spring Security 能做什么?

Spring Security 提供以下功能:

  • 用户认证(Authentication)
  • 权限授权(Authorization)
  • 密码加密(BCrypt)
  • 会话管理、记住我
  • 防止 CSRF、Session Fixation
  • 与 OAuth2、JWT 等机制集成

三、核心概念

名称说明
SecurityContext安全上下文,存储当前登录用户信息
Authentication用户的认证信息(用户名、密码、角色)
UserDetails自定义用户信息类
UserDetailsService获取用户信息的数据来源(如数据库)
GrantedAuthority用户的权限集合

四、Spring Security 入门示例

引入依赖:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

默认开启 Basic 登录页面,访问任何接口都需要登录。


五、自定义用户名密码登录逻辑

1. 自定义用户详情类

public class MyUserDetails implements UserDetails {
    private User user; // 用户对象可来自数据库

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return AuthorityUtils.createAuthorityList("ROLE_USER");
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    // 其他 isAccountNonExpired 等返回 true
}

2. 实现 UserDetailsService

@Service
public class MyUserDetailsService implements UserDetailsService {
    @Override
    public UserDetails loadUserByUsername(String username) {
        // 查询数据库
        User user = userRepository.findByUsername(username);
        return new MyUserDetails(user);
    }
}

3. 配置 Security

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .formLogin().permitAll()
            .and()
            .authorizeRequests()
            .antMatchers("/admin/**").hasRole("ADMIN")
            .anyRequest().authenticated();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
            .passwordEncoder(new BCryptPasswordEncoder());
    }
}

六、密码加密:BCrypt

Spring Security 推荐使用 BCryptPasswordEncoder 进行密码加密。

String hash = new BCryptPasswordEncoder().encode("123456");

认证时自动对比密码哈希值,无需手动验证。


七、基于 JWT 的前后端分离登录方案

1. 用户登录成功后生成 JWT

String token = Jwts.builder()
    .setSubject(user.getUsername())
    .setExpiration(new Date(System.currentTimeMillis() + 3600000))
    .signWith(SignatureAlgorithm.HS512, secretKey)
    .compact();

2. 客户端保存并在每次请求中发送

Authorization: Bearer <token>

3. 自定义过滤器解析 Token

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) {
        String header = req.getHeader("Authorization");
        if (header != null && header.startsWith("Bearer ")) {
            String token = header.substring(7);
            String username = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody().getSubject();
            // 设置到上下文
        }
        chain.doFilter(req, res);
    }
}

4. 注入过滤器

http.addFilterBefore(new JwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);

八、角色与权限控制

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/admin/dashboard")
public String dashboard() {
    return "管理员页面";
}

在控制层注解权限控制,适配前后端分离应用。


九、安全防护机制

  • CSRF 防护:默认启用,可关闭(适用于 API 项目)
  • Session 管理:支持最大登录数、并发踢人
  • Remember Me:记住我功能
  • Logout 清除:安全退出,清空上下文

十、总结

Spring Security 是企业级安全的基础设施:

  • 基于过滤器链进行身份验证与访问控制
  • 支持多种认证方式(表单登录、JWT、OAuth2)
  • 可扩展性强,适用于 Web、微服务、API 等多种场景

下一篇将聚焦于异步任务和调度:

《Spring 定时任务与异步编程:@Scheduled 与 @Async 实战》

是否继续生成第 7 篇?

Comments

No comments yet. Why don’t you start the discussion?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注