28. Security
如果 Spring Security 在 Classpath 中,则默认情况下,Web 应用程序将在所有 HTTP 端点上使用“基本”身份验证来确保安全。要将方法级安全性添加到 Web 应用程序中,您还可以添加@EnableGlobalMethodSecurity
和所需的设置。其他信息可以在Spring Security 参考中找到。
默认的AuthenticationManager
具有一个用户(“用户”用户名和随机密码,在应用程序启动时以 INFO 级别打印)
Using default security password: 78fa095d-3f4c-48b1-ad50-e24c31d5cf35
Note
如果您微调日志记录配置,请确保将org.springframework.boot.autoconfigure.security
类别设置为记录INFO
消息,否则将不会打印默认密码。
您可以通过提供security.user.password
来更改密码。此属性和其他有用的属性通过SecurityProperties(属性前缀“ security”)外部化。
默认的安全配置在SecurityAutoConfiguration
以及从那里导入的类中实现(对于 Web 安全,SpringBootWebSecurityConfiguration
表示安全,对于非 Web 应用程序也相关的AuthenticationManagerConfiguration
认证配置)。要完全关闭默认的 Web 应用程序安全性配置,可以添加带有@EnableWebSecurity
的 bean(这不会禁用身份验证 Management 器配置或 Actuator 的安全性)。要对其进行自定义,通常使用外部属性和WebSecurityConfigurerAdapter
类型的 Bean(例如,添加基于表单的登录名)。
Note
如果添加@EnableWebSecurity
并且还禁用了 Actuator 安全性,则除非添加自定义WebSecurityConfigurerAdapter
,否则将获得整个应用程序的默认基于表单的登录名。
要也关闭身份验证 Management 器配置,您可以添加AuthenticationManager
类型的 bean,或者通过将AuthenticationManagerBuilder
自动装配到@Configuration
类之一的方法中来配置全局AuthenticationManager
。 Spring Bootsample中有几个安全的应用程序,可帮助您开始使用常见的用例。
在 Web 应用程序中开箱即用的基本功能是:
-
具有内存存储和单个用户的
AuthenticationManager
bean(有关该用户的属性,请参见SecurityProperties.User
)。 -
常见的静态资源位置(
/css/**
,/js/**
,/images/**
,/webjars/**
和**/favicon.ico
)的路径被忽略(不安全)。 -
所有其他端点的 HTTP 基本安全性。
-
发布到 Spring 的
ApplicationEventPublisher
的安全事件(成功和失败的身份验证以及访问被拒绝)。 -
默认情况下,Spring Security 提供的常见低级功能(HSTS,XSS,CSRF,缓存)处于启用状态。
可以使用外部属性(security.*
)打开或关闭以上所有内容或对其进行修改。要覆盖访问规则而不更改任何其他自动配置的功能,请使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
添加类型为WebSecurityConfigurerAdapter
的@Bean
并对其进行配置以满足您的需求。
Note
默认情况下,WebSecurityConfigurerAdapter
将匹配任何路径。如果您不想完全覆盖 Spring Boot 的自动配置访问规则,则适配器必须显式配置您要覆盖的路径。
28.1 OAuth2
如果您的 Classpath 上有spring-security-oauth2
,则可以利用一些自动配置功能来轻松设置授权或资源服务器。有关详细信息,请参见Spring Security OAuth 2 开发人员指南。
28.1.1 授权服务器
要创建授权服务器并授予访问令牌,您需要使用@EnableAuthorizationServer
并提供security.oauth2.client.client-id
和security.oauth2.client.client-secret]
属性。Client 端将在内存中为您注册。
完成后,您将能够使用 Client 端凭据来创建访问令牌,例如:
$ curl client:[emailprotected]:8080/oauth/token -d grant_type=password -d username=user -d password=pwd
/token
终结点的基本身份验证凭据是client-id
和client-secret
。用户凭证是正常的 Spring Security 用户详细信息(在 Spring Boot 中默认为“ user”和随机密码)。
要关闭自动配置并自己配置授权服务器功能,只需添加类型@Bean
的@Bean
即可。
28.1.2 资源服务器
要使用访问令牌,您需要一个资源服务器(可以与授权服务器相同)。创建资源服务器很容易,只需添加@EnableResourceServer
并提供一些配置即可允许服务器解码访问令牌。如果您的应用程序也是授权服务器,则它已经知道如何解码令牌,因此无需执行其他操作。如果您的应用是独立服务,那么您需要为其提供更多配置,以下选项之一:
-
security.oauth2.resource.user-info-uri
以使用/me
资源(例如,Pivotal Web Services(PWS)上的https://uaa.run.pivotal.io/userinfo
) -
security.oauth2.resource.token-info-uri
以使用令牌解码端点(例如,PWS 上的https://uaa.run.pivotal.io/check_token
)。
如果同时指定了user-info-uri
和token-info-uri
,则可以设置一个标志来表示一个优先于另一个(默认为prefer-token-info=true
)。
另外,如果令牌是 JWT,则可以代替_或token-info-uri
(而不是user-info-uri
或token-info-uri
),您可以配置security.oauth2.resource.jwt.key-value
以在本地对其进行解码(其中密钥为验证密钥)。验证密钥值可以是对称密钥,也可以是 PEM 编码的 RSA 公钥。如果您没有密钥,并且它是公开的,则可以提供security.oauth2.resource.jwt.key-uri
,以供您下载 URI(作为带有“值”字段的 JSON 对象)。例如。在 PWS 上:
$ curl https://uaa.run.pivotal.io/token_key
{"alg":"SHA256withRSA","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"}
此外,如果授权服务器的端点返回一组 JSON Web 密钥(JWK),则可以配置security.oauth2.resource.jwk.key-set-uri
。例如。在 PWS 上:
$ curl https://uaa.run.pivotal.io/token_keys
{"keys":[{"kid":"key-1","alg":"RS256","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"]}
Note
同时配置 JWT 和 JWK 属性将导致错误。只能配置security.oauth2.resource.jwt.key-uri
(或security.oauth2.resource.jwt.key-value
)和security.oauth2.resource.jwk.key-set-uri
中的一个。
Warning
如果您使用security.oauth2.resource.jwt.key-uri
或“ security.oauth2.resource.jwk.key-set-uri”,则在您的应用程序启动时,授权服务器需要正在运行。如果找不到密钥,它将记录一条警告,并告诉您如何解决。
OAuth2 资源由 Sequences 为security.oauth2.resource.filter-order
的过滤器链保护,默认情况下是在过滤器之后默认情况下保护 Actuator 端点(因此,除非更改 Sequences,否则 Actuator 端点将保留在 HTTP Basic 上)。
28.2 用户信息中的令牌类型
Google 和某些其他第三方身份提供者对 Headers 中发送到用户信息端点的令牌类型名称更加严格。默认值为“ Bearer”,它适合大多数提供商并符合规范,但是如果需要更改它,则可以设置security.oauth2.resource.token-type
。
28.3 自定义用户信息 RestTemplate
如果您具有user-info-uri
,则资源服务器功能会在内部使用OAuth2RestTemplate
来获取用户详细信息以进行身份验证。这是类型为UserInfoRestTemplateFactory
的@Bean
提供的。对于大多数提供程序来说,默认值应该是合适的,但有时您可能需要添加其他拦截器,或更改请求验证器(这是令牌与传出请求的连接方式)。要添加定制,只需创建类型为UserInfoRestTemplateCustomizer
的 bean-它具有一个方法,该方法将在创建 bean 之后但初始化之前调用。在此自定义的其余模板仅供内部使用,以进行身份验证。另外,您可以定义自己的UserInfoRestTemplateFactory
@Bean
以完全控制。
Tip
要在 YAML 中设置 RSA 密钥值,请使用“管道”延续标记将其分成多行(“ |”),并记住缩进密钥值(这是标准的 YAML 语言功能)。例:
security:
oauth2:
resource:
jwt:
keyValue: |
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...
-----END PUBLIC KEY-----
28.3.1 Client
要使您的 Web 应用程序成为 OAuth2Client 端,您只需添加@EnableOAuth2Client
,Spring Boot 就会创建OAuth2ClientContext
和OAuth2ProtectedResourceDetails
,这对于创建OAuth2RestOperations
是必需的。 Spring Boot 不会自动创建此类 bean,但您可以轻松创建自己的 bean:
@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext,
OAuth2ProtectedResourceDetails details) {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
Note
您可能要添加一个限定符并检查您的配置,因为您的应用程序中可能定义了多个RestTemplate
。
此配置使用security.oauth2.client.*
作为凭据(与您在 Authorization Server 中可能使用的凭据相同),但是除此之外,它还需要知道 Authorization Server 中的授权和令牌 URI。例如:
application.yml.
security:
oauth2:
client:
clientId: bd1c0a783ccdd1c9b9e4
clientSecret: 1a9030fbca47a5b2c28e92f19050bb77824b5ad1
accessTokenUri: https://github.com/login/oauth/access_token
userAuthorizationUri: https://github.com/login/oauth/authorize
clientAuthenticationScheme: form
当您尝试使用OAuth2RestTemplate
时,具有此配置的应用程序将重定向到 Github 进行授权。如果您已经登录 Github,您甚至不会注意到它已通过身份验证。仅当您的应用程序在端口 8080 上运行时,这些特定的凭据才有效(在 Github 或其他提供商中注册您自己的 Client 端应用程序以获得更大的灵 Active)。
要限制 Client 端获得访问令牌时要求的范围,可以设置security.oauth2.client.scope
(逗号分隔或 YAML 中的数组)。默认情况下,作用域为空,并且由授权服务器决定默认值是什么,通常取决于它所拥有的 Client 端注册中的设置。
Note
还有一个security.oauth2.client.client-authentication-scheme
的设置,默认为“Headers”(但是,例如,例如 Github,如果您的 OAuth2 提供者不喜欢 Headers 身份验证,则可能需要将其设置为“ form”)。实际上,security.oauth2.client.*
属性绑定到AuthorizationCodeResourceDetails
的实例,因此可以指定其所有属性。
Tip
在非 Web 应用程序中,您仍然可以创建OAuth2RestOperations
,并且仍连接到security.oauth2.client.*
配置中。在这种情况下,这是您要使用它的“Client 凭证令牌授予”(并且不需要使用@EnableOAuth2Client
或@EnableOAuth2Sso
)。要阻止定义该基础结构,只需从配置中删除security.oauth2.client.client-id
(或将其设为空字符串)。
28.3.2 单点登录
OAuth2Client 端可用于从提供商那里获取用户详细信息(如果可用的功能可用),然后将它们转换为 Spring Security 的Authentication
令牌。上面的资源服务器通过user-info-uri
属性支持此功能。这是基于 OAuth2 的单点登录(SSO)协议的基础,Spring Boot 通过提供 Comments@EnableOAuth2Sso
使其易于参与。上面的 GithubClient 端可以保护 Github 的所有资源,并使用 Github /user/
端点进行身份验证,方法是添加该 Comments 并声明在何处可以找到该端点(除了上面已经列出的security.oauth2.client.*
配置之外):
application.yml.
security:
oauth2:
...
resource:
userInfoUri: https://api.github.com/user
preferTokenInfo: false
由于默认情况下所有路径都是安全的,因此没有可以显示给未经身份验证的用户并邀请他们登录的“主页”页面(通过访问/login
路径或security.oauth2.sso.login-path
指定的路径)。
要自定义要保护的访问规则或路径,例如,您可以添加一个“主页”页面,可以将@EnableOAuth2Sso
添加到WebSecurityConfigurerAdapter
中,并且 Comments 将对其进行修饰和增强,并添加必要的部分以使/login
路径起作用。例如,在这里,我们仅允许未经授权的访问主页“ /”,并保留其他所有内容的默认设置:
@Configuration
static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void init(WebSecurity web) {
web.ignoring().antMatchers("/");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
}
}
28.4Actuator 安全性
如果还使用了 Actuator,则会发现:
-
即使应用程序端点不安全,Management 端点也是安全的。
-
安全事件被转换为
AuditEvent
实例,并发布到AuditEventRepository
。 -
默认用户将具有
ACTUATOR
角色和USER
角色。
可以使用外部属性(management.security.*
)修改 Actuator 的安全功能。要覆盖应用程序访问规则,请添加WebSecurityConfigurerAdapter
类型的@Bean
,如果您不想覆盖 Actuator 访问规则,请使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
;如果您想要覆盖 Actuator 访问规则,请使用@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)
。