29. Security

如果Spring Security在 Classpath 上,则默认情况下将保护 Web 应用程序的安全。 Spring Boot 依靠 Spring Security 的内容协商策略来确定使用httpBasic还是formLogin。要将方法级安全性添加到 Web 应用程序,您还可以使用所需的设置添加@EnableGlobalMethodSecurity。其他信息可以在Spring Security 参考指南中找到。

默认的UserDetailsService有一个用户。用户名为user,密码为随机密码,并在应用程序启动时以 INFO 级别显示,如下例所示:

Using generated security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35

Note

如果您微调日志记录配置,请确保将org.springframework.boot.autoconfigure.security类别设置为记录INFO级消息。否则,不会打印默认密码。

您可以通过提供spring.security.user.namespring.security.user.password来更改用户名和密码。

默认情况下,您在 Web 应用程序中获得的基本功能是:

  • 具有内存存储的UserDetailsService(或 WebFlux 应用程序为ReactiveUserDetailsService)bean 和具有生成的密码的单个用户(有关用户的属性,请参见SecurityProperties.User)。

  • 整个应用程序的基于表单的登录或 HTTP 基本安全性(取决于 Content-Type)(如果 Actuator 位于 Classpath 上,则包括 Actuator 端点)。

  • DefaultAuthenticationEventPublisher用于发布身份验证事件。

您可以通过添加一个 Bean 来提供另一个AuthenticationEventPublisher

29.1 MVC 安全性

默认的安全配置在SecurityAutoConfigurationUserDetailsServiceAutoConfiguration中实现。 SecurityAutoConfiguration导入SpringBootWebSecurityConfiguration以获得 Web 安全性,并且UserDetailsServiceAutoConfiguration配置身份验证,这也与非 Web 应用程序相关。要完全关闭默认的 Web 应用程序安全性配置,可以添加类型为WebSecurityConfigurerAdapter的 bean(这样做不会禁用UserDetailsService配置或 Actuator 的安全性)。

要也关闭UserDetailsService配置,可以添加UserDetailsServiceAuthenticationProviderAuthenticationManager类型的 Bean。 Spring Bootsample中有几个安全的应用程序,可帮助您开始使用常见的用例。

通过添加自定义WebSecurityConfigurerAdapter可以覆盖访问规则。 Spring Boot 提供了便利的方法,可用于覆盖 Actuator 端点和静态资源的访问规则。 EndpointRequest可用于创建基于management.endpoints.web.base-path属性的RequestMatcherPathRequest可用于为常用位置的资源创建RequestMatcher

29.2 WebFlux 安全性

与 Spring MVC 应用程序类似,您可以通过添加spring-boot-starter-security依赖项来保护 WebFlux 应用程序。默认的安全配置在ReactiveSecurityAutoConfigurationUserDetailsServiceAutoConfiguration中实现。 ReactiveSecurityAutoConfiguration导入WebFluxSecurityConfiguration以获得 Web 安全性,并且UserDetailsServiceAutoConfiguration配置身份验证,这也与非 Web 应用程序相关。要完全关闭默认的 Web 应用程序安全性配置,可以添加类型为WebFilterChainProxy的 bean(这样做不会禁用UserDetailsService配置或 Actuator 的安全性)。

要也关闭UserDetailsService配置,可以添加ReactiveUserDetailsServiceReactiveAuthenticationManager类型的 Bean。

可以通过添加自定义SecurityWebFilterChain来配置访问规则。 Spring Boot 提供了便利的方法,可用于覆盖 Actuator 端点和静态资源的访问规则。 EndpointRequest可用于创建基于management.endpoints.web.base-path属性的ServerWebExchangeMatcher

PathRequest可用于为常用位置的资源创建ServerWebExchangeMatcher

例如,您可以通过添加以下内容来自定义安全配置:

@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
	return http
		.authorizeExchange()
			.matchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
			.pathMatchers("/foo", "/bar")
				.authenticated().and()
			.formLogin().and()
		.build();
}

29.3 OAuth2

OAuth2是 Spring 支持的广泛使用的授权框架。

29.3.1 Client

如果您的 Classpath 上有spring-security-oauth2-client,则可以利用一些自动配置功能来轻松设置 OAuth2/Open ID Connect Client 端。此配置使用OAuth2ClientProperties下的属性。相同的属性适用于 servlet 和反应式应用程序。

您可以使用spring.security.oauth2.client前缀注册多个 OAuth2 Client 端和提供者,如以下示例所示:

spring.security.oauth2.client.registration.my-client-1.client-id=abcd
spring.security.oauth2.client.registration.my-client-1.client-secret=password
spring.security.oauth2.client.registration.my-client-1.client-name=Client for user scope
spring.security.oauth2.client.registration.my-client-1.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-1.scope=user
spring.security.oauth2.client.registration.my-client-1.redirect-uri-template=http://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-1.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-1.authorization-grant-type=authorization_code

spring.security.oauth2.client.registration.my-client-2.client-id=abcd
spring.security.oauth2.client.registration.my-client-2.client-secret=password
spring.security.oauth2.client.registration.my-client-2.client-name=Client for email scope
spring.security.oauth2.client.registration.my-client-2.provider=my-oauth-provider
spring.security.oauth2.client.registration.my-client-2.scope=email
spring.security.oauth2.client.registration.my-client-2.redirect-uri-template=http://my-redirect-uri.com
spring.security.oauth2.client.registration.my-client-2.client-authentication-method=basic
spring.security.oauth2.client.registration.my-client-2.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.my-oauth-provider.authorization-uri=http://my-auth-server/oauth/authorize
spring.security.oauth2.client.provider.my-oauth-provider.token-uri=http://my-auth-server/oauth/token
spring.security.oauth2.client.provider.my-oauth-provider.user-info-uri=http://my-auth-server/userinfo
spring.security.oauth2.client.provider.my-oauth-provider.user-info-authentication-method=header
spring.security.oauth2.client.provider.my-oauth-provider.jwk-set-uri=http://my-auth-server/token_keys
spring.security.oauth2.client.provider.my-oauth-provider.user-name-attribute=name

对于支持OpenID Connect 发现的 OpenID Connect 提供程序,可以进一步简化配置。提供者需要配置一个issuer-uri,这是它声明为其发布者标识符的 URI。例如,如果提供的issuer-uri是“ https://example.com”,则将对“ https://example.com/.well-known/openid-configuration”设置OpenID Provider Configuration Request。结果预期为OpenID Provider Configuration Response。以下示例显示了如何使用issuer-uri配置 OpenID Connect 提供程序:

spring.security.oauth2.client.provider.oidc-provider.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/

默认情况下,Spring Security 的OAuth2LoginAuthenticationFilter只处理与/login/oauth2/code/*匹配的 URL。如果要定制redirect-uri以使用其他模式,则需要提供配置以处理该定制模式。例如,对于 servlet 应用程序,您可以添加自己的WebSecurityConfigurerAdapter,其类似于以下内容:

public class OAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http
			.authorizeRequests()
				.anyRequest().authenticated()
				.and()
			.oauth2Login()
				.redirectionEndpoint()
					.baseUri("/custom-callback");
	}
}

通用提供商的 OAuth2 Client 端注册

对于常见的 OAuth2 和 OpenID 提供程序,包括 Google,Github,Facebook 和 Okta,我们提供了一组提供程序默认值(分别为googlegithubfacebookokta)。

如果不需要自定义这些提供程序,则可以将provider属性设置为您需要为其推断默认值的属性。另外,如果用于 Client 端注册的密钥与默认支持的提供程序匹配,则 Spring Boot 也会进行推断。

换句话说,以下示例中的两种配置都使用 Google 提供程序:

spring.security.oauth2.client.registration.my-client.client-id=abcd
spring.security.oauth2.client.registration.my-client.client-secret=password
spring.security.oauth2.client.registration.my-client.provider=google

spring.security.oauth2.client.registration.google.client-id=abcd
spring.security.oauth2.client.registration.google.client-secret=password

29.3.2 资源服务器

如果您的 Classpath 上有spring-security-oauth2-resource-server,则只要指定了 JWK Set URI 或 OIDC Issuer URI,Spring Boot 就可以设置 OAuth2 资源服务器,如以下示例所示:

spring.security.oauth2.resourceserver.jwt.jwk-set-uri=https://example.com/oauth2/default/v1/keys
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://dev-123456.oktapreview.com/oauth2/default/

相同的属性适用于 servlet 和反应式应用程序。

另外,您可以为 Servlet 应用程序定义自己的JwtDecoder bean 或为 Reactive 应用程序定义ReactiveJwtDecoder

29.3.3 授权服务器

当前,Spring Security 不提供对实现 OAuth 2.0 授权服务器的支持。但是,此功能可从Spring Security OAuth项目获得,最终将被 Spring Security 完全取代。在此之前,您可以使用spring-security-oauth2-autoconfigure模块轻松设置 OAuth 2.0 授权服务器;有关说明,请参见其documentation

29.4 Actuator 安全性

为了安全起见,默认禁用除/health/info以外的所有 Actuator。 management.endpoints.web.exposure.include属性可用于启用 Actuator。

如果 Spring Security 位于 Classpath 上,并且不存在其他 WebSecurityConfigurerAdapter,则通过 Spring Boot 自动配置来保护/health/info以外的所有 Actuator。如果您定义一个自定义WebSecurityConfigurerAdapter,Spring Boot 自动配置将退出,您将完全控制 Actuator 访问规则。

Note

在设置management.endpoints.web.exposure.include之前,请确保裸露的 Actuator 不包含敏感信息和/或通过将它们放置在防火墙后面或通过诸如 Spring Security 之类的东西进行保护。

29.4.1 跨站点请求伪造保护

由于 Spring Boot 依赖于 Spring Security 的默认值,因此默认情况下 CSRF 保护是打开的。这意味着在使用默认安全性配置时,需要POST的 Actuator 端点(关机和 Logger 端点),PUTDELETE将收到 403 禁止错误。

Note

我们建议仅在创建非浏览器 Client 端使用的服务时完全禁用 CSRF 保护。

有关 CSRF 保护的其他信息可以在Spring Security 参考指南中找到。