简介
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不要对这些静态资源路径应用任何安全性控制,因此它们可以被所有用户直接访问,而不需要登录或授权。
HttpSecurity常见配置
-
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); // 记住我功能,设置令牌有效期为一周
}
}