25.md 13.5 KB
Newer Older
W
mkdocs  
wizardforcel 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
# 28\. Security

如果Spring Security位于类路径上,则默认情况下,Web应用程序将在所有HTTP端点上使用“basic”身份验证。 要向Web应用程序添加方法级安全性,您还可以使用所需的设置添加@EnableGlobalMethodSecurity。 有关更多信息,请参见“[Spring Security Reference](http://docs.spring.io/spring-security/site/docs/4.2.2.RELEASE/reference/htmlsingle#jc-method)”。

默认的AuthenticationManager有一个用户(用户名'user'和随机密码,在应用程序启动时以INFO级别打印)

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

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

您可以通过提供security.user.password来更改密码。 这个和其他有用的属性通过 [SecurityProperties](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java)(属性前缀“security”)进行外部化。

默认的安全配置在SecurityAutoConfiguration和从那里导入的类中实现(用于Web安全的SpringBootWebSecurityConfiguration和用于认证配置的AuthenticationManagerConfiguration,这在非Web应用程序中也是相关的)。 要完全关闭默认的Web应用程序安全配置,您可以使用@EnableWebSecurity添加一个bean(这不会禁用身份验证管理器配置或Actuator的安全性)。 要定制它,您通常使用WebSecurityConfigurerAdapter类型的外部属性和bean(例如添加基于表单的登录)。 要关闭身份验证管理器配置,您可以添加AuthenticationManager类型的bean,或者通过将AuthenticationManagerBuilder自动连接到您的一个@Configuration类中的方法来配置全局AuthenticationManager。 Spring Boot示例中有几个安全应用程序可以让您开始使用常见的[用例](https://github.com/spring-projects/spring-boot/tree/v1.5.2.RELEASE/spring-boot-samples/)

您在Web应用程序中获得的基本功能包括:

*   具有内存存储和单个用户的AuthenticationManager Bean(请参阅用于用户属性的SecurityProperties.User)。
*   对于常见的静态资源位置,忽略(不安全)路径(/css/**, /js/**, /images/**, /webjars/** and **/favicon.ico)。
*   HTTP所有其他端点的baseic security 。
*   安全事件发布到Spring的ApplicationEventPublisher(成功、不成功的身份验证、拒绝访问)。
*   默认情况下,Spring Security提供的常见的底层功能(HSTS,XSS,CSRF,缓存)都是打开的。

所有上述可以使用外部属性(security.*)打开、关闭或修改。 要覆盖访问规则而不更改任何其他自动配置的功能,请添加一个带有@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)的WebSecurityConfigurerAdapter类型的Bean,并配置它以满足您的需要。

> 默认情况下,WebSecurityConfigurerAdapter将匹配任何路径。 如果您不想完全覆盖Spring Boot自动配置的访问规则,您的适配器必须显式配置您要覆盖的路径。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#281-oauth2)28.1 OAuth2

如果您的类路径中有spring-security-oauth2,您可以利用一些自动配置来轻松设置授权或资源服务器。 有关完整的详细信息,请参阅“[Spring Security OAuth 2开发人员指南](http://projects.spring.io/spring-security-oauth/docs/oauth2.html)”。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2811-授权服务器)28.1.1 授权服务器

要创建授权服务器并授予访问令牌,您需要使用@EnableAuthorizationServer并提供security.oauth2.client.client-id和security.oauth2.client.client-secret]属性。 客户端将为您注册在内存中。

```
$ curl client:secret@localhost:8080/oauth/token -d grant_type=password -d username=user -d password=pwd
```

/token 端点的基本身份验证凭证是client-id和client-secret。 用户凭据是普通的Spring Security用户details (在Spring引导中默认为“user”和随机密码)。

要关闭自动配置并自行配置授权服务器功能,只需添加一个类型为AuthorizationServerConfigurer的@Bean。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2812-资源服务器)28.1.2 资源服务器

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

*   security.oauth2.resource.user-info-uri使用/me资源(例如PWS上的
*   security.oauth2.resource.token-info-uri使用令牌解码端点(例如,PWS上的

如果您同时指定user-info-uri和token-info-uri,那么您可以设置一个标志,表示优先于另一个(prefer-token-inf=true是默认值)。

或者(不是user-info-uri或token-info-uri的情况)如果令牌是JWT,您可以配置security.oauth2.resource.jwt.key-value来本地解码(key是验证密钥verification key)。 验证密钥值是对称秘密或PEM编码的RSA公钥。 如果您没有密钥,并且它是公开的,您可以提供一个可以使用security.oauth2.resource.jwt.key-uri下载的URI(具有“value”字段的JSON对象)。 例如在PWS上:

```
$ curl https://uaa.run.pivotal.io/token_key
{"alg":"SHA256withRSA","value":"-----BEGIN PUBLIC KEY-----\nMIIBI...\n-----END PUBLIC KEY-----\n"}
```

如果您使用security.oauth2.resource.jwt.key-uri,则应用程序启动时需要运行授权服务器。 如果找不到密钥,它将记录一个警告,并告诉您如何解决该问题。

> 如果您使用security.oauth2.resource.jwt.key-uri,则应用程序启动时需要运行授权服务器。 如果找不到密钥,它将会在日志记录一个警告,并告诉您如何解决该问题。

OAuth2资源由order security.oauth2.resource.filter-order的过滤器链保护,默认情况下保护执行器(actuator)端点的过滤器(所以执行器(actuator)端点将保留在HTTP Basic上,除非更改顺序)。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#282-user-info中的令牌类型)28.2 User Info中的令牌类型

Google和某些其他第三方身份认证提供商对在header中发送到用户信息端点的令牌类型名称更为严格。 默认值为“Bearer”,适合大多数提供程序并匹配规范,但如果需要更改,可以设置security.oauth2.resource.token-type。

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#283-自定义用户信息resttemplate)28.3 自定义用户信息RestTemplate

如果您有user-info-uri,则资源服务器功能在内部使用OAuth2RestTemplate来获取用户身份验证信息。 这是以UserInfoRestTemplateFactory类型的@Bean提供的。 大多数提供程序的默认值应该是能满足正常使用,但有时您可能需要添加其他拦截器,或者更改请求验证器(例如:令牌如何附加到传出请求)。 进行自定义,只需创建一个类型为UserInfoRestTemplateCustomizer的bean - 它具有一个方法,在bean创建之后但在初始化之前将被调用。 这里定制的rest模板只能在内部进行验证。 或者,您可以定义自己的UserInfoRestTemplateFactory @Bean来完全控制。

要在YAML中设置RSA密钥值,请使用“pipe”继续标记将其分割成多行(“|”),并记住缩进键值(它是标准的 YAML 语言功能)。 例:

```
security:
    oauth2:
        resource:
            jwt:
                keyValue: |
                    -----BEGIN PUBLIC KEY-----
                    MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC...
                    -----END PUBLIC KEY-----
```

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2831-client)28.3.1 Client

要使您的 web-app 进入OAuth2客户端,您可以简单地添加@ EnableOAuth2Client,Spring Boot将创建一个OAuth2ClientContext和OAuth2ProtectedResourceDetails,这些是创建OAuth2RestOperations所必需的。 Spring Boot不会自动创建这样的bean,但是您可以轻松创建自己的bean:

```
@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, OAuth2ProtectedResourceDetails details) {
    return new OAuth2RestTemplate(details, oauth2ClientContext);
}
```

> 您可能需要添加限定符并查看您的配置,因为您的应用程序可能会定义多个RestTemplate。

此配置使用security.oauth2.client.*作为凭据(可能与授权服务器中使用的相同),但另外还需要知道授权服务器中的授权和令牌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或其他提供商注册自己的客户端应用程序以获得更大的灵活性),这些特定的凭据才会起作用。

要限制客户端在获取访问令牌时要求的范围,您可以设置security.oauth2.client.scope(逗号分隔或YAML中的数组)。 默认情况下,scope是空的,由授权服务器决定其默认值,通常取决于客户端注册中的设置。

> 还有一个security.oauth2.client.client-authentication-scheme的设置,默认为“header”(但是如果像Github那样,您可能需要将其设置为“form”,例如,您的OAuth2提供程序不喜欢header 认证)。 事实上,security.oauth2.client.*属性绑定到AuthorizationCodeResourceDetails的一个实例,因此可以指定其所有的属性。

> 在非Web应用程序中,您仍然可以创建一个OAuth2RestOperations,它仍然连接到security.oauth2.client.*配置中。 在这种情况下,它是一个“客户端凭据令牌授予”,您如果使用它就请求它(并且不需要使用@EnableOAuth2Client或@EnableOAuth2Sso)。为了防止定义基础设施,只需从配置中删除security.oauth2.client.client-id(或使其成为空字符串)。

#### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#2832-单点登录)28.3.2 单点登录

OAuth2客户端可用于从提供商获取用户详细信息(如果此类功能可用),然后将其转换为Spring Security的身份验证令牌。 以上资源服务器通过user-info-uri属性支持此功能这是基于OAuth2的单点登录(SSO)协议的基础,Spring Boot可以通过提供@ EnableOAuth2Sso注解来轻松加入。 上面的Github客户端可以通过添加该注释并声明在何处查找端点(除了上面列出的security.oauth2.client.*配置)外,还可以保护所有资源并使用Github/user/endpoint进行身份验证:

application.yml.

```
security:
    oauth2:
...
    resource:
        userInfoUri: https://api.github.com/user
        preferTokenInfo: false
```

由于默认情况下所有路径都是安全的,所以没有可以向未经身份验证的用户显示“家”页面,并邀请他们登录(通过访问/登录路径或由security.oauth2.sso.login-path指定的路径) 。

由于默认情况下所有路径都是要求安全的,所以没有可以向未经身份验证的用户显示“home”页面,并邀请他们登录(通过访问/login 路径或由security.oauth2.sso.login-path指定的路径) 。

要自定义保护的访问规则或路径,因此您可以添加“home”页面,例如,@EnableOAuth2Sso可以添加到WebSecurityConfigurerAdapter,并且注解将使其被修饰和增强,以使所需的/login路径可以工作。 例如,这里我们简单地允许未经身份验证的访问“/"下的主页面,并保留其他所有内容的默认值:

```
@Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    public void init(WebSecurity web) {
        web.ignore("/");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
    }

}
```

### [](file:///C:/Users/geekidentity/AppData/Local/Youdao/YNote/markdown/index.html#284-actuator-security)28.4 Actuator Security

如果Actuator也在使用中,您会发现:

*   即使应用程序端点不安全,管理端点也是安全的。
*   Security 事件将转换为AuditEvent实例,并发布到AuditEventRepository。
*   默认用户将具有ACTUATOR角色以及USER角色。

Actuator的安全功能可以使用外部属性(management.security.*)进行修改。要覆盖应用程序访问规则,请添加一个类型为WebSecurityConfigurerAdapter的@Bean,如果您不想覆盖执行程序访问规则,则使用@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)或@Order(ManagementServerProperties.ACCESS_OVERRIDE_ORDER)覆盖执行器访问规则。