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类之一的方法中来配置全局AuthenticationManagerSpring Bootsample中有几个安全的应用程序,可帮助您开始使用常见的用例。

在 Web 应用程序中开箱即用的基本功能是:

可以使用外部属性(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-idsecurity.oauth2.client.client-secret]属性。Client 端将在内存中为您注册。

完成后,您将能够使用 Client 端凭据来创建访问令牌,例如:

$ curl client:[emailprotected]:8080/oauth/token -d grant_type=password -d username=user -d password=pwd

/token终结点的基本身份验证凭据是client-idclient-secret。用户凭证是正常的 Spring Security 用户详细信息(在 Spring Boot 中默认为“ user”和随机密码)。

要关闭自动配置并自己配置授权服务器功能,只需添加类型@Bean@Bean即可。

28.1.2 资源服务器

要使用访问令牌,您需要一个资源服务器(可以与授权服务器相同)。创建资源服务器很容易,只需添加@EnableResourceServer并提供一些配置即可允许服务器解码访问令牌。如果您的应用程序也是授权服务器,则它已经知道如何解码令牌,因此无需执行其他操作。如果您的应用是独立服务,那么您需要为其提供更多配置,以下选项之一:

如果同时指定了user-info-uritoken-info-uri,则可以设置一个标志来表示一个优先于另一个(默认为prefer-token-info=true)。

另外,如果令牌是 JWT,则可以代替_或token-info-uri(而不是user-info-uritoken-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 就会创建OAuth2ClientContextOAuth2ProtectedResourceDetails,这对于创建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.security.*)修改 Actuator 的安全功能。要覆盖应用程序访问规则,请添加WebSecurityConfigurerAdapter类型的@Bean,如果您不想覆盖 Actuator 访问规则,请使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER);如果您想要覆盖 Actuator 访问规则,请使用@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)

上一章 首页 下一章