Hello Spring Security
本节涵盖了如何在 Spring Boot 中使用 Spring Security 的最低设置,然后为你指出之后的步骤。
完整的 starter 程序可以在 在我们的示例库找到。为了方便,你可以下载一个 由 Spring Initializr 准备的 最小的 Spring Boot + Spring Security 应用程序。 |
启动 Hello Spring Security Boot
随着 Spring Security 在 classpath 上,你现在可以 运行 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 将为该请求提供服务,在这种情况下返回 404 Not Found
,因为 /some/path
不存在。
从这里,你可以:
运行时异常
Spring Boot 和 Spring Security 的默认安排在运行时提供了以下行为:
-
任何端点(包括 Boot 的
/error
端点)都需要一个认证的用户。 -
在启动时用生成的密码 注册一个默认用户(密码被记录到控制台;在前面的例子中,密码是
8e557245-73e2-4286-969a-ff57fe326336
)。 -
用 BCrypt 以及其他方式保护密码存储。
-
对 基于表单 的登录以及 HTTP Basic 进行认证。
-
提供内容协商;对于web请求,重定向到登录页面;对于服务请求,返回
401 Unauthorized
。 -
减缓 CSRF 攻击。
-
写入 X-Content-Type-Options 以减缓 嗅探攻击。
-
写入保护认证资源的 Cache Control header。
-
写入 X-Frame-Options,以缓解 点击劫持 的情况。
-
与
HttpServletRequest
的认证方法 整合。 -
发布 认证成功和失败的事件。
了解 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("ROLE_USER").build());
}
@Bean
@ConditionalOnMissingBean(AuthenticationEventPublisher.class)
DefaultAuthenticationEventPublisher defaultAuthenticationEventPublisher(ApplicationEventPublisher delegate) { (3)
return new DefaultAuthenticationEventPublisher(delegate);
}
}
-
添加了
@EnableWebSecurity
注解。(在其他方面,它将 Spring Security 的默认Filter
chain 作为@Bean
发布)。 -
发布一个
UserDetailsService
@Bean
,其用户名是user
,密码是随机生成的,会被记录到控制台。 -
发布一个
AuthenticationEventPublisher
@Bean
,用于发布认证事件。
Spring Boot 将任何以 @Bean 形式发布的 Filter 添加到应用程序的 filter chain 中。这意味着,结合 Spring Boot 使用 @EnableWebSecurity 会自动为每个请求注册 Spring Security 的 filter chain。
|
Security 用例
从这里开始,你可能想去很多地方。要想知道你和你的应用程序的下一步是什么,请考虑 Spring Security 为解决的这些常见用例:
-
我正在构建一个REST API,我需要 验证一个JWT 或 其他 bearer token。
-
我正在构建一个 Web 应用程序、API网关或BFF,并且:
-
我需要 使用OAuth 2.0或OIDC登录。
-
我需要 使用SAML 2.0登录。
-
我需要 用CAS登录。
-
-
我需要管理
-
LDAP 或 Active Directory 中的用户,使用 Spring Data,或使用 JDBC。
-
如果这些都不符合你正在寻找的东西,可以考虑按照以下顺序考虑你的应用:
-
协议: 首先,考虑你的应用程序将使用何种协议进行通信。对于基于Servlet的应用程序,Spring Security 支持 HTTP 以及 Websockets。
-
认证: 接下来,考虑用户将如何进行 认证,以及这种认证是有状态的还是无状态的。
-
授权: 然后,考虑你将如何确定一个 用户被授权做什么。
-
防御: 最后, 与 Spring Security 的默认保护措施相结合,并考虑你 需要哪些额外的保护措施。