Hello Spring Security
本节介绍了如何将 Spring Security 与 Spring Boot 结合使用的最低配置要求,并指引您后续的操作步骤。
完整的入门应用程序可以在 我们的示例仓库 中找到。为了方便起见,你可以下载一个由 Spring Initializr 准备的 最小化 Spring Boot + Spring Security 应用程序。
更新依赖项
启动 Hello Spring Security Boot
当 Spring Security 位于类路径中时,你现在可以运行 Spring Boot 应用程序。以下代码片段展示了部分输出内容,表明 Spring Security 已在你的应用程序中启用:
- Maven
- Gradle
- Jar
$ ./mvnw spring-boot:run
...
INFO 23689 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: 8e557245-73e2-4286-969a-ff57fe326336
...
$ ./gradlew :bootRun
...
INFO 23689 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: 8e557245-73e2-4286-969a-ff57fe326336
...
$ java -jar target/myapplication-0.0.1.jar
...
INFO 23689 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration :
Using generated security password: 8e557245-73e2-4286-969a-ff57fe326336
...
现在你已经让它运行起来了,可以尝试访问一个端点看看会发生什么。如果你在没有凭证的情况下访问端点,例如:
$ curl -i http://localhost:8080/some/path
HTTP/1.1 401
...
随后 Spring Security 会以 401 Unauthorized 拒绝访问。
如果你在浏览器中提供相同的 URL,它将会重定向到默认的登录页面。
如果你使用凭据(在控制台输出中找到)访问端点,如下所示:
$ curl -i -u user:8e557245-73e2-4286-969a-ff57fe326336 http://localhost:8080/some/path
HTTP/1.1 404
...
随后 Spring Boot 将处理该请求,由于 /some/path 路径不存在,此时会返回 404 Not Found 状态码。
从这里,您可以:
运行时预期
Spring Boot与Spring Security的默认配置在运行时提供了以下行为:
-
要求经过身份验证的用户才能访问任何端点(包括 Boot 的
/error端点) -
在启动时注册一个默认用户,并生成密码(密码会记录到控制台;在前面的示例中,密码是
8e557245-73e2-4286-969a-ff57fe326336) -
支持基于表单的登录和 HTTP Basic 身份验证
-
提供内容协商;对于 Web 请求,重定向到登录页面;对于服务请求,返回
401 Unauthorized -
缓解 CSRF 攻击
-
缓解会话固定攻击
-
写入 X-Content-Type-Options 以缓解嗅探攻击
-
写入缓存控制头部以保护经过身份验证的资源
-
写入 X-Frame-Options 以缓解点击劫持
理解 Spring Boot 如何与 Spring Security 协同实现这一功能会很有帮助。查看 Boot 的安全自动配置,它执行以下操作(为便于说明已简化):
@EnableWebSecurity 1
@Configuration
public class DefaultSecurityConfig {
@Bean
@ConditionalOnMissingBean(UserDetailsService.class)
InMemoryUserDetailsManager inMemoryUserDetailsManager() { 2
String generatedPassword = // ...;
return new InMemoryUserDetailsManager(User.withUsername("user")
.password(generatedPassword).roles("USER").build());
}
@Bean
@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
DefaultAuthenticationEventPublisher defaultAuthenticationEventPublisher(ApplicationEventPublisher delegate) { 3
return new DefaultAuthenticationEventPublisher(delegate);
}
}
-
添加
@EnableWebSecurity注解。(除其他功能外,该注解会将 Spring Security 的默认过滤器链 作为@Bean发布) -
发布一个 UserDetailsService
@Bean,其用户名为user,并带有一个随机生成且会输出到控制台的密码 -
发布一个 AuthenticationEventPublisher
@Bean,用于发布身份验证事件
Spring Boot 会将任何发布为 @Bean 的 Filter 添加到应用程序的过滤器链中。这意味着在 Spring Boot 中使用 @EnableWebSecurity 会自动为每个请求注册 Spring Security 的过滤器链。
安全用例
从这里出发,您可能有许多方向可以选择。为了确定您和您的应用程序的下一步,请考虑以下 Spring Security 旨在解决的常见用例:
-
我正在构建一个 REST API,需要对 JWT 进行身份验证或对其他承载令牌进行身份验证
-
我正在构建一个 Web 应用程序、API 网关或 BFF,并且
-
我需要管理
-
LDAP 或 Active Directory 中的用户,使用 Spring Data 或使用 JDBC
-
如果以上都不符合您的需求,请按以下顺序思考您的应用场景:
-
协议:首先,考虑你的应用程序将使用何种协议进行通信。对于基于 servlet 的应用程序,Spring Security 支持 HTTP 以及 Websockets。
-
认证:接下来,考虑用户将如何进行认证,以及该认证是有状态的还是无状态的。
-
授权:然后,考虑你将如何确定用户被授权执行哪些操作。
-
防御:最后,集成 Spring Security 的默认保护措施,并考虑你需要哪些额外的保护措施。