消除迷宫:异境入侵官方中文版
· 2025-11-02
spring-boot-starter-security是Spring Boot提供的用于安全性集成的依赖库,它简化了在Spring Boot应用程序中添加安全性功能的过程。
这个starter基于Spring Security构建,用于处理应用程序的身份验证和授权。
以下是关于spring-boot-starter-security的详细介绍:
身份验证和授权:spring-boot-starter-security为你的Spring Boot应用程序提供了全面的身份验证和授权支持。你可以轻松地配置和管理用户的身份验证,以及用户对应用程序的访问权限。
自定义认证方式:Spring Security允许你使用各种身份验证方式,如基本身份验证、表单登录、OAuth等。你可以根据你的需求选择适当的认证方式,并进行定制化配置。
用户存储:你可以将用户存储在内存、数据库或其他用户存储后端中。Spring Security提供了多种选项,包括使用JDBC、LDAP、OAuth等方式进行用户管理。
注解支持:spring-boot-starter-security提供了注解支持,允许你在方法级别或类级别进行安全性控制。通过@PreAuthorize和@PostAuthorize等注解,你可以定义谁可以访问特定的方法或资源。
CSRF保护:默认情况下,Spring Security提供了跨站请求伪造(CSRF)保护,以增加应用程序的安全性。
会话管理:你可以配置和管理用户会话,包括会话过期时间和并发会话数。
集成第三方身份验证:Spring Security允许你集成第三方身份验证提供者,如OAuth 2.0、OpenID Connect等,以支持单点登录和安全的API访问。
定制化配置:你可以使用Java配置或XML配置来定制Spring Security的行为,以满足你的应用程序需求。
默认安全性配置:spring-boot-starter-security提供了默认的安全性配置,包括基本的HTTP基本认证和禁用了CSRF保护。你可以根据需要进行自定义配置,或者完全禁用它并从头开始构建自己的安全性配置。
自动配置:Spring Boot自动配置了许多常见的安全性设置,使得在Spring Boot应用程序中启用安全性非常容易。
加入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security </artifactId>
</dependency>
启动项目,控制台会输出生成的登录密码(如果控制台没有看到,看配置的spring的日志级别,info级别可以输出),默认的账号是user
生成的密码是调用的uuid随机生成的,所以每次启动都会生成不同的密码

访问项目,会跳转到security自带的一个登录页面

我们创建了一个SecurityConfig类,它继承自WebSecurityConfigurerAdapter,并使用@EnableWebSecurity注解启用Spring Security。
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll() // 允许所有用户访问公开的URL
.antMatchers("/admin/**").hasRole("ADMIN") // 需要ADMIN角色才能访问
.anyRequest().authenticated() // 所有其他请求需要认证
.and()
.formLogin()
.loginPage("/login") // 自定义登录页面
.permitAll()
.and()
.logout()
.logoutUrl("/logout") // 自定义登出URL
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 配置使用内存身份验证方式
auth
.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER");
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
配置的关键部分是configure(HttpSecurity http)方法,它定义了URL的访问规则和认证方式。在示例中:
/public/**路径的URL是公开的,所有用户都可以访问。/admin/**路径的URL需要用户具有ADMIN角色才能访问。此外,我们定义了自定义的登录页面和登出URL
内存身份验证方式:
配置类中:
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// 配置使用内存身份验证方式
auth
.inMemoryAuthentication()
.withUser("user")
.password(passwordEncoder().encode("password"))
.roles("USER");
}
UserDetailsService身份认证
配置类中:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll() // 允许所有用户访问公开的URL
.antMatchers("/secured/**").authenticated() // 需要身份验证的URL
.and()
.formLogin()
.loginPage("/login") // 自定义登录页面的URL
.permitAll()
.and()
.logout()
.logoutUrl("/logout") // 自定义登出URL
.permitAll();
}
}
创建一个实现UserDetailsService接口的自定义类
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Service
public class CustomUserDetailsService implements UserDetailsService {
// 实现loadUserByUsername方法来检索用户信息
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if ("user".equals(username)) {
return User.builder()
.username("user")
.password(passwordEncoder().encode("password"))
.roles("USER")
.build();
} else if ("admin".equals(username)) {
return User.builder()
.username("admin")
.password(passwordEncoder().encode("adminpassword"))
.roles("ADMIN")
.build();
} else {
throw new UsernameNotFoundException("User not found.");
}
}
}
}
上面是使用的Spring Security提供的User类。也可以自定义用户实体类,这个类通常需要实现UserDetails接口。
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
public class CustomUserDetails implements UserDetails {
private String username;
private String password;
private Collection<? extends GrantedAuthority> authorities;
// 构造函数、getter和setter方法
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return password;
}
@Override
public String getUsername() {
return username;
}
// 其他UserDetails接口方法的实现
}
WebSecurity用于配置Spring Security的静态资源访问策略,如CSS、JavaScript、图片等静态资源的访问。
在WebSecurityConfigurerAdapter的实现类中添加如下
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**","/fonts/**","/images/**","/js/**");
}
web.ignoring() 表示你要忽略某些路径的访问策略。.antMatchers("/css/**","/fonts/**","/images/**","/js/**") 指定了要忽略的路径模式,/**通配符表示匹配任何深度的路径。告诉Spring Security不要对这些静态资源路径应用任何安全性控制,因此它们可以被所有用户直接访问,而不需要登录或授权。
URL权限控制:
.authorizeRequests(): 用于配置URL的访问权限规则。
.antMatchers("/public/**").permitAll(): 允许所有用户访问/public/**路径的URL。.antMatchers("/secured/**").authenticated(): 需要用户进行身份验证才能访问/secured/**路径的URL。.antMatchers("/admin/**").hasRole("ADMIN"): 需要用户具有ADMIN角色才能访问/admin/**路径的URL。.anyRequest().authenticated(): 所有其他请求都需要进行身份验证。登录配置:
.formLogin(): 配置表单登录。
.loginPage("/login"): 自定义登录页面的URL。.permitAll(): 允许所有用户访问登录页面。.loginProcessingUrl("/login"): 指定登录请求的URL。.defaultSuccessUrl("/home"): 登录成功后的默认重定向URL。.failureUrl("/login?error=true"): 登录失败后的重定向URL。注销配置:
.logout(): 配置注销功能。
.logoutUrl("/logout"): 自定义注销URL。.permitAll(): 允许所有用户注销。.logoutSuccessUrl("/login?logout=true"): 注销成功后的重定向URL。记住我功能配置:
.rememberMe(): 配置"记住我"功能。
.rememberMeParameter("remember-me"): 指定"记住我"的参数名称。.rememberMeCookieName("remember-me-cookie"): 指定"记住我"的cookie名称。.tokenValiditySeconds(604800): 指定记住我token的有效期(秒)。CSRF保护:
.csrf(): 配置CSRF(Cross-Site Request Forgery)保护。
.disable(): 禁用CSRF保护。.csrfTokenRepository(csrfTokenRepository): 配置自定义的CSRF Token仓库。HTTP Basic认证配置:
.httpBasic(): 配置HTTP Basic认证。
.realmName("My Realm"): 指定HTTP Basic认证的Realm名称。会话管理:
.sessionManagement(): 配置会话管理。
.sessionCreationPolicy(SessionCreationPolicy.STATELESS): 使用无状态会话。.maximumSessions(1).maxSessionsPreventsLogin(true): 同时只允许一个用户登录,阻止其他用户登录。安全头部配置:
.headers(): 配置HTTP响应头部的安全性。
.contentSecurityPolicy("default-src 'self'"): 配置内容安全策略。异常处理:
.exceptionHandling(): 配置异常处理。
.accessDeniedPage("/access-denied"): 指定访问被拒绝时的错误页面。自定义过滤器和拦截器:
.addFilterBefore(filter, beforeFilter): 在指定的过滤器之前添加自定义过滤器。.addFilterAfter(filter, afterFilter): 在指定的过滤器之后添加自定义过滤器。.addFilterAt(filter, atFilter): 在指定位置添加自定义过滤器。.addFilterBefore(filter, beforeFilter): 在指定的拦截器之前添加自定义拦截器。以上是一些常见的HttpSecurity配置选项,你可以根据你的应用程序的具体需求来组合和配置这些选项。
默认情况下,它使用了内存中的用户存储来简化开发和测试。这意味着你可以轻松地在你的Spring Boot应用程序中配置一些用户,而不需要连接到数据库或其他持久化存储。
允许你在配置文件或Java代码中定义用户、密码和角色。这些用户数据仅在应用程序运行时存在,不会持久化到任何数据库或文件中。
你也可以轻松地切换到其他用户存储方式,如数据库
@EnableWebSecurity:这个注解通常在一个配置类上使用,用于启用Spring Security的Web安全性功能。在配置类上使用该注解后,你可以自定义身份验证和授权规则。
@Secured:@Secured注解用于在方法级别进行授权。你可以在希望受保护的方法上添加@Secured注解,并指定允许访问的角色或权限。例如:
@Secured("ROLE_ADMIN")
public void adminMethod() {
// 只有具有ROLE_ADMIN角色的用户才能访问此方法
}
@PreAuthorize 和 @PostAuthorize:这两个注解允许你在方法执行前和执行后进行访问控制。@PreAuthorize用于在方法执行前进行授权检查,而@PostAuthorize用于在方法执行后进行授权检查。你可以使用SpEL表达式定义授权规则。例如:
@PreAuthorize("hasRole('ROLE_ADMIN')")
public void adminMethod() {
// 只有具有ROLE_ADMIN角色的用户才能访问此方法
}
@RolesAllowed:@RolesAllowed注解是Java EE的标准注解,可以在方法级别指定允许访问的角色。它与@Secured类似,但不支持SpEL表达式。
@AuthenticationPrincipal:@AuthenticationPrincipal注解允许你在方法参数中获取当前认证用户的Principal(主体)。你可以使用它来方便地获取已认证用户的信息。例如:
@GetMapping("/profile")
public String userProfile(@AuthenticationPrincipal CustomUserDetails userDetails) {
// 使用@AuthenticationPrincipal注解获取已认证用户的信息
String username = userDetails.getUsername();
// ...
}
@EnableGlobalMethodSecurity:通过在配置类上使用@EnableGlobalMethodSecurity注解,你可以启用全局方法级别的安全性注解,例如@Secured、@PreAuthorize、@PostAuthorize等。这样你可以在多个方法中共享相同的安全性规则。、
可以帮助你控制和管理用户的会话,包括会话的创建、并发控制、会话过期等。以下是spring-boot-starter-security提供的会话管理功能的主要方面:
会话创建策略:
SessionCreationPolicy.ALWAYS(默认):始终创建会话,无论用户是否经过身份验证。SessionCreationPolicy.IF_REQUIRED:仅在需要时创建会话,即用户进行身份验证后。SessionCreationPolicy.NEVER:从不创建会话。SessionCreationPolicy.STATELESS:会话是无状态的,不会创建或使用HTTP会话。并发控制:
maximumSessions(int maxSessions)方法用于配置允许的最大会话数量。maxSessionsPreventsLogin(boolean maxSessionsPreventsLogin)方法用于确定当会话达到最大数量时是否阻止新的登录。会话过期策略:
invalidSessionUrl(String invalidSessionUrl)方法用于指定会话过期后的重定向URL。sessionFixation()方法用于配置会话固定保护策略,以防止会话固定攻击。会话注册:
sessionRegistry()方法用于配置会话注册表,以跟踪活动会话和已过期的会话。会话保护:
invalidSessionUrl(String invalidSessionUrl)方法用于指定在会话无效(例如,过期或无效)时的重定向URL。HttpSessionEventPublisher来启用会话事件发布,以便Spring Security可以检测到会话过期等事件。记住我功能:
rememberMe()方法用于配置"记住我"功能,允许用户在会话过期后继续保持登录状态。tokenValiditySeconds(int seconds)方法用于指定"记住我"令牌的有效期。自定义会话管理:
下面是一个示例配置,演示了如何在Spring Security中配置会话管理:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.antMatchers("/secured/**").authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) // 会话创建策略
.maximumSessions(1) // 最大并发会话数量
.maxSessionsPreventsLogin(true) // 当会话达到最大数量时阻止新的登录
.expiredUrl("/login?expired=true") // 会话过期后的重定向URL
.and()
.and()
.rememberMe()
.tokenValiditySeconds(604800); // 记住我功能,设置令牌有效期为一周
}
}