12
Spring Security 入门:登录与放行
Spring Security · Filter Chain · JWT
Web 应用谁都能访问?接口裸奔?引入 spring-boot-starter-security 后,默认所有接口都要登录才能访问,还自动给你生成一个登录页和初始密码。它的核心是一条过滤器链:每个请求经过一串过滤器,挨个判断"你是谁、你有权限吗"。
第一个安全应用:加依赖就全拦了
<!-- pom 里加这个,Spring Security 自动生效 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
启动后访问任意接口,会跳到自带登录页。默认用户名 user,密码在启动日志里打出来(一串 UUID)。这只是演示,下面自己配。
配置放行规则与内存用户(Spring Security 6 写法)
// SecurityFilterChain:用 @Configuration 配一条过滤器链
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/login", "/public/**").permitAll() // 这些放行
.anyRequest().authenticated() "> 其余都要登录
)
.formLogin(form -> form.defaultSuccessUrl("/"))
.csrf(csrf -> csrf.disable()); // 纯后端 API 先关了,前后端分离另说
return http.build();
}
@Bean
public UserDetailsService users(PasswordEncoder encoder) {
// 演示用内存用户;生产换成从数据库读
var admin = User.withUsername("admin")
.password(encoder.encode("123456"))
.roles("ADMIN").build();
return new InMemoryUserDetailsManager(admin);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(); // 密码必须加密存,不能明文
}
}
前后端分离:JWT 无状态认证
上面是表单登录(有 Session)。前后端分离 + 微服务,普遍用 JWT:登录成功后端发一个 token,前端以后每个请求带在 Authorization: Bearer xxx 头里,后端过滤器验签,不存 Session。Spring Cloud 那章会在网关统一做这事。
论记住三个坑
① 密码永不明文:用 BCrypt 之类加密存储,登录时比对哈希。② CSRF:纯 JSON API 可以关,带 Cookie 的表单必须开。③ 默认拦截一切:忘了 permitAll 登录页就打不开,别慌,是配错了。
章末面试 · Spring Security(3 题)
1.(概念题)Spring Security 的核心机制是什么?
查看答案
答案:一条 Servlet 过滤器链(SecurityFilterChain),每个请求经过一串过滤器,依次完成认证(你是谁)和授权(你能干啥)。
2.(实践题)为什么数据库里不能存明文密码?
查看答案
答案:数据库一泄露所有账号就裸奔。用 BCryptPasswordEncoder 加盐哈希,即使泄露也不可逆。
3.(概念题)JWT 方案为什么不用 Session?
查看答案
答案:JWT 是无状态的,认证信息自包含在 token 里,服务端不存会话,方便水平扩展和网关统一鉴权;代价是 token 一旦签发,想主动失效要配合黑名单/短过期。