# Local 本地配置

### 1. 功能开关

Spring Cloud Data Flow Server 提供了功能启动时的启动/禁用开关。功能包含在Spring Cloud Data Flow 中流转的所有操作以及REST的节点（服务器端以及客户端实现，包括shell和UI）如下：

* Streams (requires Skipper)
* Tasks
* Task Scheduler

可以通过在启动数据流服务器时设置boolean属性来开启和关闭这些功能

* `spring.cloud.dataflow.features.streams-enabled`
* `spring.cloud.dataflow.features.tasks-enabled`
* `spring.cloud.dataflow.features.schedules-enabled`

默认情况下，Stream(包括Skipper)，Tasks 是启用状态，Task Scheduler 是关闭状态。&#x20;

通过 REST `/about`端点可以查看功能的启用禁用信息。

### 2. 数据库

使用关系型数据库来存储 Stream 和 Task 的定义以及 Task 的执行状态。Spring Cloud Data Flow支持H2，HSQLDB，MySQL，Oracle，Postgresql，DB2和SqlServer数据库。服务在启动的时候会自动创建数据结构，无需手动创建。

默认情况下，Spring Cloud Data Flow 使用 H2 数据库的嵌入式实例。 H2 数据库方便在开发过程中使用，但不建议在生产环境中部署。

**MySQL**（通过MariaDB驱动程序），**HSQLDB**，**PostgreSQL**和嵌入式**H2**的JDBC驱动程序无需额外配置即可使用。如果需要使用其他的数据库，则需要将相应的JDBC驱动程序放在server 对应的 classpath 目录下。

数据库的配置可以通过启动行命令的形式进行配置或者通过环境变量的形式进行配置。

以下示例展示通过环境变量定义数据库的连接：

```bash
export spring_datasource_url=jdbc:postgresql://localhost:5432/mydb
export spring_datasource_username=myuser
export spring_datasource_password=mypass
export spring_datasource_driver_class_name="org.postgresql.Driver"
```

以下示例显示如何使用命令行参数定义MySQL数据库连接：

```bash
java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:mysql://localhost:3306/mydb \
    --spring.datasource.username= \
    --spring.datasource.password= \
    --spring.datasource.driver-class-name=org.mariadb.jdbc.Driver &
```

以下示例显示如何使用命令行参数定义MariaDB数据库连接：

```bash
java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:mariadb://localhost:3306/mydb?useMysqlMetadata=true \
    --spring.datasource.username= \
    --spring.datasource.password= \
    --spring.datasource.driver-class-name=org.mariadb.jdbc.Driver &
```

{% hint style="info" %}
从MariaDB v2.4.1版本开始，需要在JDBC URL 添加 useMysqlMetadata=true。这个是强制性的配置，直到MariaDB和MySQL能拆分为两个不同的数据库。
{% endhint %}

以下示例显示如何使用命令行参数定义PostgreSQL数据库连接：

```
java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:postgresql://localhost:5432/mydb \
    --spring.datasource.username= \
    --spring.datasource.password= \
    --spring.datasource.driver-class-name=org.postgresql.Driver &
```

以下示例显示如何使用命令行参数定义HSQLDB数据库连接：

```
java -jar spring-cloud-dataflow-server/target/spring-cloud-dataflow-server-2.1.0.RELEASE.jar \
    --spring.datasource.url=jdbc:hsqldb://localhost:9001/mydb \
    --spring.datasource.username=SA \
    --spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver &
```

{% hint style="info" %}
H2 数据库不支持外部配置
{% endhint %}

#### 2.1 数据库创建以及迁移策略开关

在服务启动的时候，可以控制在启动是否进行数据库的创建。不过在生产环境中，由于权限问题，可能你不能直接进行限制。这个时候可以采用配置属性的方式来禁用它，如下：

&#x20;`spring.cloud.dataflow.rdbms.initialize.enable=false`

数据库的创建脚本位于 `spring-cloud-dataflow-core/src/main/resources/` 的目录下。

如果是首次安装运行的系统，请运行位于 `/schemas`和`/migrations.1.x.x` 的数据库脚本，如果是版本升级到1.2.0的系统，只需`/migrations.1.x.x`下的数据脚本即可。

#### 2.2 添加自定义JDBC驱动

如果需要使用其他数据库，这时需要添加自定义的驱动程序（例如，ORACLE）， 您应该修改 Maven 的配置 `pom.xml` 文件，并重新打包 Data Flow 服务。 平台部署的服务版本不同，但是所有版本都应该修改对应 `pom.xml` 的文件，GitHub中有每个版本的项目源码。

为本地服器添加自定义JDBC驱动程序依赖：

* 选择需要重新打包的服务版本，并到GitHub中获取源码
* 编辑 spring-cloud-dataflow-server / pom.xml，并且添加数据库驱动程序的依赖项。在以下示例中，已选择Oracle驱动程序：

```markup
<dependencies>
...
  <dependency>
    <groupId>com.oracle.jdbc</groupId>
    <artifactId>ojdbc8</artifactId>
    <version>12.2.0.1</version>
  </dependency>
...
</dependencies> 
```

* &#x20;按照 [构建Spring Cloud](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#building) 中的方式，创建应用程序

### 3. 部署配置

在部署Stream和Tasks时，可以使用 [本地部署程序](https://github.com/spring-cloud/spring-cloud-deployer-local) 中的配置来部署。使用Data Flow shell进行部署时，

```yaml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: myuser
    password: mypass
    driver-class-name:org.postgresql.Driver
```

当您使用 [本地部署](https://github.com/spring-cloud/spring-cloud-deployer-local) 的方式，部署 Streams 和 Tasks 的时，配置可以参考下表。

当您使用Data Flow shell 进行部署时，可以使用如下语法，配置可以参考下表。`deployer.<appName>.local.<deployerPropertyName>`&#x20;

当在 Data Flow Serve 和 Skipper 中配置 Local Task 时，也会用到下表的配置。

| Deployer Property Name | Description                 | Default Value                                                                                                                                                                          |
| ---------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| workingDirectoriesRoot | 程序启动后日志目录                   | java.io.tmpdir                                                                                                                                                                         |
| envVarsToInherit       | 环境变量集合，支持正则表达式，程序启动时加载进应用程序 | <p><"TMP", "LANG", "LANGUAGE", "LC<em>.*", "PATH", "SPRING\_APPLICATION\_JSON"></em></p><p> <em>on windows</em> </p><p><em><"TMP", "LANG", "LANGUAGE", "LC</em>.*", PATH"> on Unix</p> |
| deleteFilesOnExit      | 当JVM退出时，删除创建的文件和目录          | true                                                                                                                                                                                   |
| javaCmd                | Command to run java         | java                                                                                                                                                                                   |
| shutdownTimeout        | 等待应用程序关闭最大时间（秒）             | 30                                                                                                                                                                                     |
| javaOpts               | Jvm 的java配置，例如 -Dtest = foo | \<none>                                                                                                                                                                                |
| inheritLogging         | 是否将日志写入到触发应用的输出流中。          | false                                                                                                                                                                                  |
| debugPort              | 用于远程调试的端口                   | \<none>                                                                                                                                                                                |

现在创建一个名为 ticktock 的 Time Stream 程序，可以参考以下例子配置：

```bash
dataflow:> stream create --name ticktock --definition "time --server.port=9000 | log"
dataflow:> stream deploy --name ticktock --properties "deployer.time.local.javaOpts=-Xmx2048m -Dtest=foo"
```

可以通过简略写法，通过 `deployer.memory` 属性来替代 java 的 -Xmx 属性，如下示例：

```bash
dataflow:> stream deploy --name ticktock --properties "deployer.time.memory=2048m"
```

部署时，如果在 `deployer.<app>.local.javaOpts` 中指定了 `-Xmx` 的值，并且在配置中也使用了 `deployer.<app>.local.memory` 的配置，则`javaOpts`优先级高。 此外，部署应用程序时设置的 `javaOpts` 属性优先级高于 `spring.cloud.deployer.local.javaOpts` 的配置。

### 4.  Logging 日志

&#x20;Spring Cloud Data Flow 的 `local` 服务器自动配置日志，使用`RollingFileAppender`进行日志记录。日志的配置文件是在classpath下的`logback-spring.xml`。

在 默认情况下，使用的日志配置为：

```bash
<property name="LOG_FILE" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/spring-cloud-dataflow-server}"/>
```

使用 logback 配置 `RollingPolicy` 方式：

```markup
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>${LOG_FILE}.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <!-- daily rolling -->
        <fileNamePattern>${LOG_FILE}.${LOG_FILE_ROLLING_FILE_NAME_PATTERN:-%d{yyyy-MM-dd}}.%i.gz</fileNamePattern>
        <maxFileSize>${LOG_FILE_MAX_SIZE:-100MB}</maxFileSize>
        <maxHistory>${LOG_FILE_MAX_HISTORY:-30}</maxHistory>
        <totalSizeCap>${LOG_FILE_TOTAL_SIZE_CAP:-500MB}</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>${FILE_LOG_PATTERN}</pattern>
    </encoder>
</appender>
```

查看当前 Spring Cloud Data Flow Server `local`服务器配置的 java.io.tmpdir ：

```bash
jinfo <pid> | grep "java.io.tmpdir"
```

如果你要修改或者覆盖  `LOG_FILE`, `LOG_PATH`, `LOG_TEMP`, `LOG_FILE_MAX_SIZE`, `LOG_FILE_MAX_HISTORY` and `LOG_FILE_TOTAL_SIZE_CAP` 请将它们设置为系统属性。

### 5. Streams&#x20;

使用Data Flow Server 使用 Skipper 服务进行 Stream 的生命周期管理，将 `spring.cloud.skipper.client.serverUri` 属性值配置为Skipper的服务地址接口：

```bash
$ java -jar spring-cloud-dataflow-server-2.1.0.RELEASE.jar --spring.cloud.skipper.client.serverUri=https://192.51.100.1:7577/api
```

通过 Skipper 服务进行配置 `platform accounts` 可以显示 Stream 部署到哪个 Platforms。

### 6. Task 任务

Data Flow Server 负责部署 Task。 在 Data Flow Server 启动时，将 Task 的状态写入到相同的数据库中。当 Task 类型为 Spring Batch Jobs 时，job 和 step 的执行数据也会写入到同一个数据库中。与 Skipper 发布 Streams 一样，Task 也可以发布到多个 Platforms，如果没有指定 Platforms， [LocalDeployerProperties](https://github.com/spring-cloud/spring-cloud-deployer-local/blob/master/spring-cloud-deployer-local/src/main/java/org/springframework/cloud/deployer/spi/local/LocalDeployerProperties.java) 会创建一个名称为 `default` 的 Platforms，详细配置可参考  [Local Deployer Properties](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#configuration-local-deployer) 。

要配置一个新的 Local Platforms 时，只需通过添加配置 `application.yaml` 中的spring.cloud.dataflow\.task.platform.local 即可实现。Spring Boot 提供了相应的支持。 在以下的示例中，将创建两个名为 `localDev` 和 `localDevDebug` 的 Local Platforms。可以使用 `shutdownTimeout` 和 `javaOpts` 进行属性设置。

```yaml
spring:
  cloud:
    dataflow:
      task:
        platform:
          local:
            accounts:
              localDev:
                shutdownTimeout: 60
                javaOpts: "-Dtest=foo -Xmx1024m"
              localDevDebug:
                javaOpts: "-Xdebug -Xmx2048m"
```

启动 Task 时，可以通过启动命令 `--platformName` 指定 Platforms 的名称，如果没有指定，则会使用  `default` 。

{% hint style="warning" %}
当 Task 部署多个 Platforms 时，需要指定 Data Flow Server 连接同一个数据库。
{% endhint %}

你可以在本地运行 Data Flow server ，将 Tasks 部署到 Cloud Foundry 或 Kubernetes 上。 请参阅有关[Cloud Foundry任务平台配置](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#configuration-cloudfoundry-tasks)和[Kubernetes任务平台配置](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#configuration-kubernetes-tasks)的部分。

### 7. Security 安全

默认情况下，Data Flow Server 是不安全的，它采用未加密的HTTP作为连接。可以通过启用HTTPS 并使用  [OAuth 2.0](https://oauth.net/2/) 进行身份验证，以保证你的 REST 节点安全性。

{% hint style="info" %}
默认情况下，REST节点（管理，运行状态）以及 Dashboard UI 界面无需身份认证。
{% endhint %}

理论上，Spring Cloud Data Flow 支持任何一个 OAuth 提供的服务，我们建议使用   [CloudFoundry User Account and Authentication (UAA) Server](https://github.com/cloudfoundry/uaa).

UAA OpenID不仅经过认证被 Cloud Foundry 使用，而且还可以在本地独立部署方案中使用。此外，UAA不仅提供自己的用户存储，还提供全面的LDAP集成。

#### 7.1. 开启 HTTPS&#x20;

您可以通过在application.yml中的配置中添加证书来切换到HTTPS，如下例所示:

```yaml
server:
  port: 8443                                          
  ssl: 
    key-alias: yourKeyAlias                 
    key-store: path/to/keystore                      
    key-store-password: yourKeyStorePassword         
    key-password: yourKeyPassword                    
    trust-store: path/to/trust-store                 
    trust-store-password: yourTrustStorePassword     
```

| key                  | content                                                              |
| -------------------- | -------------------------------------------------------------------- |
| port                 | 作为默认端口`9393`，您可以选择将端口更改为更常见的HTTPS端口                                  |
| key-alias            | 密钥存储在密钥库中的别名（或名称）。                                                   |
| key-store            | 密钥库文件的路径。也可以使用 lasspath 前缀指定资源路径，例如：`classpath:path/to/keystore`。    |
| key-store-password   | 密钥库的密码。                                                              |
| key-password         | 密钥的密码。                                                               |
| trust-store          | 信任库文件的路径。也可以使用 lasspath 前缀指定资源路径, 例如：`classpath:path/to/trust-store` |
| trust-store-password | 信任存储的密码。                                                             |

{% hint style="info" %}
如果启动HTTPS，它讲完全替代HTTP作为 REST 端点和 Data Flow Dashboard 的交互协议。纯粹的HTTP请求将会失败，请确保配置相应的Shell。
{% endhint %}

**使用 Self-Signed 证书**

在开发和测试的过程中，创建 Self-Signed 证书可能会很便捷，开始创建证书，请使用以下命令：

```bash
$ keytool -genkey -alias dataflow -keyalg RSA -keystore dataflow.keystore \
          -validity 3650 -storetype JKS \
          -dname "CN=localhost, OU=Spring, O=Pivotal, L=Kailua-Kona, ST=HI, C=US"  
          -keypass dataflow -storepass dataflowa
```

{% hint style="warning" %}
CN 是一个重要的参数，它应该和你需要访问的域名一致。
{% endhint %}

然后将下列代码添加 `application.yml`  文件中：

```yaml
server:
  port: 8443
  ssl:
    enabled: true
    key-alias: dataflow
    key-store: "/your/path/to/dataflow.keystore"
    key-store-type: jks
    key-store-password: dataflow
    key-password: dataflow
```

Data Flow Server 的证书配置到此结束，启动服务以后，可以通过  [`localhost:8443/`](https://localhost:8443/) 进行访问，由于这是一个自签名的证书，浏览器会提示警告，你需要忽略它。

**Shell 使用 Self-Signed**&#x20;

一般情况下，Shell 使用 Self-Signed 证书存在问题，需要额外的步骤才能正常在 Shell 中运行 Self-Signed 证书。可以采用一下两种方案：

* 添加 Self-Signed 证书 到 JVM truststore 中。
* 跳过证书认证

***添加Self-Signed 证书到 JVM truststore***&#x20;

为了使用 JVM truststore，我们需要先将之前创建的证书导出：

```bash
$ keytool -export -alias dataflow -keystore dataflow.keystore -file dataflow_cert -storepass dataflow
```

接下来， 我们需要创建一个 Shell 可以使用的 `truststore` ：

```bash
$ keytool -importcert -keystore dataflow.truststore -alias dataflow -storepass dataflow -file dataflow_cert -noprompt
```

现在，使用已经创建好的配置，来启动 Data Flow Shell：

```bash
$ java -Djavax.net.ssl.trustStorePassword=dataflow \
       -Djavax.net.ssl.trustStore=/path/to/dataflow.truststore \
       -Djavax.net.ssl.trustStoreType=jks \
       -jar spring-cloud-dataflow-shell-2.1.0.RELEASE.jar
```

{% hint style="info" %}
如果您在创建SSL的连接过程中遇到问题，可以设置 javax.net.debug 的 JVM 参数记录 SSL 的日志。
{% endhint %}

最后别忘记配置 Data Flow Server 地址

```bash
dataflow:> dataflow config server https://localhost:8443/
```

***Skipping Certificate Validation***

您可以通过命令行参数来绕过认证验证`--dataflow.skip-ssl-validation=true`。

如果设置此命令行参数，则shell将接受任何（自签名）SSL证书。

{% hint style="info" %}
您应该避免使用此选项。禁用 trust manager 违背了 SSL 的初衷，会是您更容易受到 man-in-the-middle （中间人） 攻击。
{% endhint %}

#### 7.2. 使用 OAuth 2.0 进行身份验证

Spring Cloud Data Flow 使用  [OAuth 2.0](https://oauth.net/2/) 和 [OpenID Connect](https://openid.net/connect/) 来支持身份验证和授权，它允许您将 Spring Cloud Data Flow 集成到单点登录（SSO）环境中。

{% hint style="info" %}
从 Spring Cloud Data Flow 2.0 开始，OAuth2 是授权和身份验证的唯一方式。
{% endhint %}

使用以下OAuth2授权类型：

* &#x20;**Authorization Code：**&#x7528;于GUI（浏览器）集成。访问者将重定向到您的OAuth服务以进行身份​​验证
* &#x20;**Password：**&#x7531;shell（以及REST集成）使用，因此访问者可以使用用户名和密码登录
* &#x20;**Client Credentials：**&#x76F4;接从 OAuth 提供程序检索访问令牌，并使用Authorization HTTP标头将其传递给 Data Flow server

{% hint style="info" %}
目前，Spring Cloud Data Flow 使用 opaque tokens 而不是 transparent tokens（JWT）。
{% endhint %}

REST端点可以通过两种方式访问：

* &#x20;**Basic authentication，** 使用 *Password Grant Type*  对您的OAuth2服务进行身份验证
* &#x20;**Access token，**&#x4F7F;用 *Credentials Grant Type* 进行用户凭证验证

{% hint style="info" %}
在设置身份认证时，强烈建议开启HTTPS，尤其是在生产环境中
{% endhint %}

你可以通过配置 `application.yml` 或者通过环境变量来启用 OAuth2 身份验证：

```yaml
security:
  oauth2:
    client:
      client-id: myclient                                             
      client-secret: mysecret
      access-token-uri: http://127.0.0.1:9999/oauth/token
      user-authorization-uri: http://127.0.0.1:9999/oauth/authorize
    resource:
      user-info-uri: http://127.0.0.1:9999/me                         
      token-info-uri: https://dataflow.local:8080/uaa/check_token   
```

| key            | content                          |
| -------------- | -------------------------------- |
| client-id      | 配置client-id，激活对应 OAuth2 Security |
| user-info-uri  | 用于检索用户信息，例如用户名。强制性。              |
| token-info-uri | 用于自检和验证直接传入的令牌。强制性的。             |

您可以使用 `curl` 命令，验证 `basic authentication` 是否正常工作，如下所示：&#x20;

```bash
$ curl -u myusername:mypassword http://localhost:9393/ -H 'Accept: application/json'
```

执行完成，您应该可以看到REST端点的列表

{% hint style="danger" %}
请注意，使用Web浏览器访问 Root URL 并启用  security 时，您将被重定向到Dashboard UI。要查看REST端点列表，请指定application/jsonAccept标头。另外，使用Postman（Chrome）或RESTClient（Firefox）等工具请务必添加 `Accept`。
{% endhint %}

除了 Basic Authentication 外，您还可以使用 Access Token 来访问 REST Api。为了实现这一点，您首先要从 OAuth2 提供程序中找到 OAuth2 的访问令牌，然后在 REST Api 中添加**Authorization** header：

```bash
$ curl -H "Authorization: Bearer <ACCESS_TOKEN>" http://localhost:9393/ -H 'Accept: application/json'
```

#### 7.3. 自定义授权

前面的内容主要涉及身份验证，即如何认证用户的身份。在本节中，我们将讨论  **authorization** 选项 - that is, who can do what&#x20;

authorization rules 在`dataflow-server-defaults.yml`（Spring Cloud Data Flow Core模块的一部分）中定义。

由于 security roles 的分配是在特定环境中，因此 Spring Cloud Data Flow 会默认将所有roles分配给 authenticated OAuth2 的认证用户。`DefaultDataflowAuthoritiesExtractor` class 就是具体的实现。

或者，通过 Spring Cloud Data Flow 设置`spring.cloud.dataflow.security.authorization.map-oauth-scopes` 设置为 `true`    将 OAuth2 映射到 Data Flow roles  。有关更多详细信息，请参阅[角色映射](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#configuration-security-role-mapping)一章。

最后，您可以通过扩展Spring Security OAuth `AuthoritiesExtractor`接口，来实现自定义的角色权限关联。在这种情况下，自定义 bean 优先于Spring Cloud Data Flow提供的默认定义。

默认方案使用七种 roles 来控制 [REST端点](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#api-guide) Spring Cloud Data Flow的访问：

* **ROLE\_CREATE** 用于涉及创建的任何内容，例如创建 streams 或 tasks
* **ROLE\_DEPLOY** 用于部署 streams 或启动tasks
* **ROLE\_DESTROY** 用于涉及删除streams，tasks等的任何内容。
* **ROLE\_MANAGE** 用于启动管理端点
* **ROLE\_MODIFY** 用于涉及改变系统状态的任何事情
* **ROLE\_SCHEDULE** 用于调度相关操作（例如，安排 tasks 执行）
* **ROLE\_VIEW** 用于检索状态的任何内容

如上所述，所有与授权相关的默认设置都在`dataflow-server-defaults.yml`其中指定，它是 Spring Cloud 数据流核心模块的一部分。如果需要，您可以覆盖这些设置。例如：在`application.yml`。

{% hint style="info" %}
请始终参考您的application.yml文件版本，因为以下代码段可能已过时。
{% endhint %}

默认规则如下：

```yaml
spring:
  cloud:
    dataflow:
      security:
        authorization:
          enabled: true
          rules:
            # About

            - GET    /about                          => hasRole('ROLE_VIEW')

            # Audit

            - GET /audit-records                     => hasRole('ROLE_VIEW')
            - GET /audit-records/**                  => hasRole('ROLE_VIEW')

            # Boot Endpoints

            - GET /management/**                  => hasRole('ROLE_MANAGE')

            # Apps

            - GET    /apps                           => hasRole('ROLE_VIEW')
            - GET    /apps/**                        => hasRole('ROLE_VIEW')
            - DELETE /apps/**                        => hasRole('ROLE_DESTROY')
            - POST   /apps                           => hasRole('ROLE_CREATE')
            - POST   /apps/**                        => hasRole('ROLE_CREATE')
            - PUT    /apps/**                        => hasRole('ROLE_MODIFY')

            # Completions

            - GET /completions/**                    => hasRole('ROLE_VIEW')

            # Job Executions & Batch Job Execution Steps && Job Step Execution Progress

            - GET    /jobs/executions                => hasRole('ROLE_VIEW')
            - PUT    /jobs/executions/**             => hasRole('ROLE_MODIFY')
            - GET    /jobs/executions/**             => hasRole('ROLE_VIEW')

            # Batch Job Instances

            - GET    /jobs/instances                 => hasRole('ROLE_VIEW')
            - GET    /jobs/instances/*               => hasRole('ROLE_VIEW')

            # Running Applications

            - GET    /runtime/streams                => hasRole('ROLE_VIEW')
            - GET    /runtime/apps                   => hasRole('ROLE_VIEW')
            - GET    /runtime/apps/**                => hasRole('ROLE_VIEW')

            # Stream Definitions

            - GET    /streams/definitions            => hasRole('ROLE_VIEW')
            - GET    /streams/definitions/*          => hasRole('ROLE_VIEW')
            - GET    /streams/definitions/*/related  => hasRole('ROLE_VIEW')
            - POST   /streams/definitions            => hasRole('ROLE_CREATE')
            - DELETE /streams/definitions/*          => hasRole('ROLE_DESTROY')
            - DELETE /streams/definitions            => hasRole('ROLE_DESTROY')

            # Stream Deployments

            - DELETE /streams/deployments/*          => hasRole('ROLE_DEPLOY')
            - DELETE /streams/deployments            => hasRole('ROLE_DEPLOY')
            - POST   /streams/deployments/**         => hasRole('ROLE_MODIFY')
            - GET    /streams/deployments/**         => hasRole('ROLE_VIEW')

            # Stream Validations

            - GET /streams/validation/               => hasRole('ROLE_VIEW')
            - GET /streams/validation/*              => hasRole('ROLE_VIEW')

            # Task Definitions

            - POST   /tasks/definitions              => hasRole('ROLE_CREATE')
            - DELETE /tasks/definitions/*            => hasRole('ROLE_DESTROY')
            - GET    /tasks/definitions              => hasRole('ROLE_VIEW')
            - GET    /tasks/definitions/*            => hasRole('ROLE_VIEW')

            # Task Executions

            - GET    /tasks/executions               => hasRole('ROLE_VIEW')
            - GET    /tasks/executions/*             => hasRole('ROLE_VIEW')
            - POST   /tasks/executions               => hasRole('ROLE_DEPLOY')
            - DELETE /tasks/executions/*             => hasRole('ROLE_DESTROY')

            # Task Schedules

            - GET    /tasks/schedules                => hasRole('ROLE_VIEW')
            - GET    /tasks/schedules/*              => hasRole('ROLE_VIEW')
            - GET    /tasks/schedules/instances      => hasRole('ROLE_VIEW')
            - GET    /tasks/schedules/instances/*    => hasRole('ROLE_VIEW')
            - POST   /tasks/schedules                => hasRole('ROLE_SCHEDULE')
            - DELETE /tasks/schedules/*              => hasRole('ROLE_SCHEDULE')

            # Task Validations

            - GET    /tasks/validation/               => hasRole('ROLE_VIEW')
            - GET    /tasks/validation/*              => hasRole('ROLE_VIEW')

            # Tools

            - POST   /tools/**                       => hasRole('ROLE_VIEW')
```

每行的格式如下：

```
HTTP_METHOD URL_PATTERN'=>'SECURITY_ATTRIBUTE
```

* HTTP\_METHOD， HTTP Request Method 共15种，采用大写方式
* URL\_PATTERN，采用 Ant 风格的 URL 路径
* SECURITY\_ATTRIBUTE，SpEL表达式。请参阅[基于表达式的访问控制](https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#el-access)。
* 每个由一个或多个空白字符（空格，制表符等）分隔的字符串

请注意，上面配置的是 YAML 中的一个 List ，而不是一个 Map（因此在每一行的开头使用      ' - ' 破折号）配置到`spring.cloud.dataflow.security.authorization.rules` 下方。

***授权 - Shell和Dashboard***

启用 security 后，Dashboard 和 Shell 将会按照角色展示对应的功能。所以，对于不同的角色，并非所有功能都可见。

例如，Shell 命令可以知道用户角色有哪些命令可用。

{% hint style="danger" %}
如果，shell 的 help 命令列出了不可用的命令。请参考以下问题：`github.com/spring-projects/spring-shell/issues/115`
{% endhint %}

同样，对于 Dashboard ，UI 不会显示用户未授权的页面或页面元素。

***保护Spring Boot Management端点***

启用 security 后， [Spring Boot HTTP Management端点](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/html/production-ready-monitoring.html) 的 security 与其他REST端点的security 相同。管理REST端点可以使用`MANAGEMENT`角色访问`/management`进行管理。

默认配置`dataflow-server-defaults.yml` ：

```yaml
management:
  endpoints:
    web:
      base-path: /management
  security:
    roles: MANAGE
```

{% hint style="danger" %}
请不要自定义管理路径。
{% endhint %}

#### **7.4. 设置UAA身份验证**

对于本地部署场景，我们建议使用 [CloudFoundry用户帐户和身份验证（UAA）服务器](https://github.com/cloudfoundry/uaa) ，采用 [OpenID的认证](https://openid.net/certification/)。虽然 UAA 使用的是 [Cloud Foundry](https://www.cloudfoundry.org/) ，但它也是一个功能齐全的独立OAuth2服务器，具有 [LDAP集成](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md) 等企业功能 。

Checkout, Build 和 Run UAA :

```bash
$ git clone https://github.com/cloudfoundry/uaa.git
$ cd uaa/
$ ./gradlew  run
```

{% hint style="danger" %}
&#x20;UAA 支持的 Java 版本是 jdk1.8。
{% endhint %}

UAA的配置由 [uaa.yml](https://github.com/cloudfoundry/uaa/blob/develop/uaa/src/main/resources/uaa.yml) 文件控制 ，您可以自定义配置，在这中情况下，我们将采用嵌入式的方案进行配置，并且提供默认用户。

```bash
curl -v -d "username=marissa&password=koala&client_id=app&grant_type=password" -u "app:appclientsecret" http://localhost:8080/uaa/oauth/token -d 'token_format=opaque'
```

会产生类似于以下的输出：

```bash
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
* Server auth using Basic with user 'app'
> POST /uaa/oauth/token HTTP/1.1
> Host: localhost:8080
> Authorization: Basic YXBwOmFwcGNsaWVudHNlY3JldA==
> User-Agent: curl/7.54.0
> Accept: */*
> Content-Length: 85
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 85 out of 85 bytes
< HTTP/1.1 200
< Cache-Control: no-store
< Pragma: no-cache
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Date: Mon, 03 Dec 2018 23:58:41 GMT
<
* Connection #0 to host localhost left intact
{"access_token":"0f935cea42fd4516bb36e4088f6d7c44","token_type":"bearer","id_token":"eyJhbGciOiJIUzI1NiIsImprdSI6Imh0dHBzOi8vbG9jYWxob3N0OjgwODAvdWFhL3Rva2VuX2tleXMiLCJraWQiOiJsZWdhY3ktdG9rZW4ta2V5IiwidHlwIjoiSldUIn0.eyJzdWIiOiI1ODExMWNlNC02NGRlLTQ3ZDYtYjZiZi0wZDRhNDFhNGFlMDAiLCJhdWQiOlsiYXBwIl0sImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6ODA4MC91YWEvb2F1dGgvdG9rZW4iLCJleHAiOjE1NDM5MjQ3MjEsImlhdCI6MTU0Mzg4MTUyMSwiYW1yIjpbInB3ZCJdLCJhenAiOiJhcHAiLCJzY29wZSI6WyJvcGVuaWQiXSwiZW1haWwiOiJtYXJpc3NhQHRlc3Qub3JnIiwiemlkIjoidWFhIiwib3JpZ2luIjoidWFhIiwianRpIjoiMGY5MzVjZWE0MmZkNDUxNmJiMzZlNDA4OGY2ZDdjNDQiLCJwcmV2aW91c19sb2dvbl90aW1lIjoxNTQzODgxMTk1NzU2LCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwiY2xpZW50X2lkIjoiYXBwIiwiY2lkIjoiYXBwIiwiZ3JhbnRfdHlwZSI6InBhc3N3b3JkIiwidXNlcl9uYW1lIjoibWFyaXNzYSIsInJldl9zaWciOiI1ZmI4N2M1NiIsInVzZXJfaWQiOiI1ODExMWNlNC02NGRlLTQ3ZDYtYjZiZi0wZDRhNDFhNGFlMDAiLCJhdXRoX3RpbWUiOjE1NDM4ODE1MjF9.qSxoygd7LUUJSEN0wGI3-U0x2tYZzHnTDuzk6AJUfBk","refresh_token":"d106513b98804a508c35d3f7b656a7fe-r","expires_in":43199,"scope":"scim.userids openid cloud_controller.read password.write cloud_controller.write","jti":"0f935cea42fd4516bb36e4088f6d7c44"}
```

`token_format`的参数，可以设置为：

* opaque
* jwt

配置UAA，建议使用`uaac`命令行工具，配置 UAA 服务器：

```bash
$ gem install cf-uaac
$ uaac target http://localhost:8080/uaa
```

查询`marissa`用户的详细信息：

```bash
$ uaac token owner get cf marissa -s "" -p koala
$ uaac contexts
```

获取 admin 用户对用的 token （密码是`adminsecret`）

```
$ uaac token client get admin -s adminsecret
```

获取所有已配置的 client 列表：

```
$ uaac clients
```

它会返回应用程序可用的 client

```bash
…
  app
    scope: cloud_controller.read cloud_controller.write openid password.write scim.userids organizations.acme
    resource_ids: none
    authorized_grant_types: password implicit authorization_code client_credentials refresh_token
    redirect_uri: http://localhost:8080/** http://localhost:8080/app/
    autoapprove: openid
    authorities: uaa.resource
    name: The Ultimate Oauth App
    signup_redirect_url: http://localhost:8080/app/
    change_email_redirect_url: http://localhost:8080/app/
    lastmodified: 1543879731285
…
```

我们将在Spring Cloud Data Flow中使用 `app` ，不过，还需要更新 `redirect_uri` 和客户端密码：

```
$ uaac client update app --redirect_uri http://localhost:9393/login
$ uaac secret set app --secret dataflow
```

现在我们可以更新 Spring Cloud Data Flow 中相关OAuth的配置：

```
security:
  oauth2:
    client:
      client-id: app
      client-secret: dataflow
      scope: openid                                                     
      access-token-uri: http://localhost:8080/uaa/oauth/token
      user-authorization-uri: http://localhost:8080/uaa/oauth/authorize
    resource:
      user-info-uri: http://localhost:8080/uaa/userinfo                 
      token-info-uri: http://localhost:8080/uaa/check_token             
```

| key            | content                                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------------------ |
| scope          | <p>如果您配置 scope 属性来指定认证Key ，请确保在 <code>dataflow\.view</code>, </p><p><code>dataflow\.create</code> 等方法中也传入相关参数。</p> |
| user-info-uri  | 用于检索用户信息，例如用户名。强制性。                                                                                                |
| token-info-uri | 用于自检和验证直接传入的令牌。强制性。                                                                                                |

`token-info-uri`配置非常重要，它会通过外部服务查询到 OAuth 的 Access Token 并传给Spring Cloud Data Flow。在这种情况下，Spring Cloud Data Flow将通过[TokenValidatingUserInfoTokenServices](https://github.com/spring-cloud/spring-cloud-common-security-config/blob/master/spring-cloud-common-security-config-web/src/main/java/org/springframework/cloud/common/security/support/TokenValidatingUserInfoTokenServices.java) 获取 OAuth 的 Access Token ，并使用UAA的 [Check Token Endpoint](https://docs.cloudfoundry.org/api/uaa/version/4.27.0/index.html#check-token) 检查令牌的有效性，并从 UAA 中查询相关联的OAuth scopes并将认证成功的用户 authentication 存储到  Spring Cloud Data Flow的 [TokenStore](https://docs.spring.io/spring-security/oauth/apidocs/org/springframework/security/oauth2/provider/token/TokenStore.html) 中。

**角色映射**

默认情况下，Spring Cloud Data Flow 的用户拥有所有权限。但是，您可以通过配置：

`spring.cloud.dataflow.security.authorization.map-oauth-scopes: true`

通过 `DefaultAuthoritiesExtractor` 方法配置 OAuth 相应权限。范围参考如下：

* 范围`dataflow.create` 对应 `CREATE` role
* 范围`dataflow.deploy` 对应 `DEPLOY` role
* 范围`dataflow.destroy` 对应 `DESTROY` role
* 范围`dataflow.manage` 对应 `MANAGE` role
* 范围`dataflow.modify` 对应 `MODIFY` role
* 范围`dataflow.schedule` 对应 `SCHEDULE` role
* 范围`dataflow.view` 对应 `VIEW` role

此外，还可以将任意范围映射到每个数据流角色：

```yaml
spring:
  cloud:
    deployer:
      local:
        free-disk-space-percentage: 0
    dataflow:
      security:
        authorization:
          map-oauth-scopes: true                                    
          role-mappings:
            ROLE_CREATE: dataflow.create                            
            ROLE_DEPLOY: dataflow.deploy
            ROLE_DESTROY: dataflow.destoy
            ROLE_MANAGE: dataflow.manage
            ROLE_MODIFY: dataflow.modify
            ROLE_SCHEDULE: dataflow.schedule
            ROLE_VIEW: dataflow.view
```

| key              | content                                                                                                                                                                                                                                                                                                               |
| ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| map-oauth-scopes | 启用 role-mappings 映射                                                                                                                                                                                                                                                                                                   |
| role-mappings    | <p>启用 role-mappings 映射支持后，</p><p>必须为7个 Spring Cloud Data Flow roles 配置映射。</p><p><strong>ROLE\_CREATE</strong>，<strong>ROLE\_DEPLOY</strong>，<strong>ROLE\_DESTROY</strong>，</p><p><strong>ROLE\_MANAGE</strong>，<strong>ROLE\_MODIFY</strong>，<strong>ROLE\_SCHEDULE</strong>，</p><p><strong>ROLE\_VIEW</strong> </p> |

{% hint style="info" %}
您可以将 OAuth scope 分配给不同的 Spring Cloud Data Flow 角色，使您可以更灵活的配置。
{% endhint %}

#### **7.5. LDAP 身份认证**

Spring Cloud Data Flow 可以使用 UAA 搭建 LDAP Authentication（轻量级目录访问协议）。UAA 自身提[ 完整的LDAP支持](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md)。

{% hint style="danger" %}
虽然您可以使用自己搭建的 OAuth2 Authentication服务，但 *LDAP* *Support* 要求使用 UAA 作为 Authentication 服务。对于其他的提供商，请参阅提供商的文档。
{% endhint %}

UAA 支持使用以下模式服务进行 LDAP（轻量级目录访问协议）的身份验证：

* [Direct bind](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md#ldap-search-and-bind)
* [Search and bind](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md#ldap-bind)
* [Search and Compare](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md#ldap-search-and-compare)

{% hint style="success" %}
与 LDAP 等外部 Authentication 服务集成时，UAA 中的身份验证会与之关联。UAA 在使用外部 Authenticate 服务认证之前，会先尝试使用用户的 credentials 对 UAA 用户进行身份验证。有关更多信息，请参阅  [Chained Authentication](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md#chained-authentication) 中的  *User Account and Authentication LDAP Integration*。
{% endhint %}

**LDAP Role Mapping**

OAuth2 Authentication 服务（UAA）[将 LDAP Role 映射到 OAuth Scopes ](https://github.com/cloudfoundry/uaa/blob/develop/docs/UAA-LDAP.md#scopes)提供完整支持。

存在以下选项时：

* `ldap/ldap-groups-null.xml` 不会映射任何组
* `ldap/ldap-groups-as-scopes.xml`将从LDAP Attribute 中检索 Group 名称。例如`CN`
* `ldap/ldap-groups-map-to-scopes.xml` 使用external\_group\_mapping表将组映射到UAA Groups

在 Spring XML 的配置文件中通过配置`ldap.groups.file controls`属性指定。

{% hint style="info" %}
在测试和开发的过程中，可能需要频繁更改 LDAP 的 groups 和 users ，并查看UAA 中的最新内容。但是，用户信息在登录期间被缓存。以下脚本有助于快速检索更新的信息：

```bash
#!/bin/bash
uaac token delete --all
uaac target http://localhost:8080/uaa
uaac token owner get cf <username> -s "" -p  <password>
uaac token client get admin -s adminsecret
uaac user get <username>
```

{% endhint %}

**LDAP Security  和 UAAD 示例应用程序**

为了帮助您快速启动运行程序，并了解 LDAP Security 的体系结构，我们在GitHub上提供了  [LDAP Security and UAA Example](https://github.com/spring-cloud/spring-cloud-dataflow-samples/tree/master/security-ldap-uaa-example)。

{% hint style="danger" %}
这只是一个演示/示例应用程序，请勿用于生产。
{% endhint %}

设置包括：

* Spring Cloud Data Flow Server
* Skipper Server
* CloudFoundry User Account and Authentication (UAA) Server
* Lightweight Directory Access Protocol (LDAP) Server (provided by [Apache Directory Server](https://directory.apache.org/)(ApacheDS))

最后，作为此示例的一部分，您将学习如何使用此安全设置配置和启动组合任务。

#### **7.6. Spring Security OAuth2 Resource/Authorization 服务示例**

在进行本地测试和开发时，您可以使用 [Spring Security OAuth](https://projects.spring.io/spring-security-oauth/) 提供的Resource/Authorization 服务 。它允许您使用以下简单注释轻松创建自己的（非常基本的）OAuth2服务器：

* `@EnableResourceServer`
* `@EnableAuthorizationServer`

{% hint style="info" %}
实际上，UAA 使用了 Spring Security OAuth2 ，因此 basic endpoints 是相同的。
{% endhint %}

可以在以下网址找到一个工作示例应用程序：

<https://github.com/ghillert/oauth-test-server/>

克隆项目并使用相应的 Client ID 和 Client Secret 配置Spring Cloud数据流：

```yaml
security:
  oauth2:
    client:
      client-id: myclient
      client-secret: mysecret
      access-token-uri: http://127.0.0.1:9999/oauth/token
      user-authorization-uri: http://127.0.0.1:9999/oauth/authorize
    resource:
      user-info-uri: http://127.0.0.1:9999/me
      token-info-uri: http://127.0.0.1:9999/oauth/check_token
```

{% hint style="info" %}
此示例应用程序不适用于生产用途
{% endhint %}

#### **7.7. Data Flow Shell 身份验证**

使用 Shell 管理程序时，您可以通过用户名和密码或通过 *`credentials-provider`*&#x547D;令来提供凭证。如果您的 OAuth2 服务支持 *Password*  授予类型，则可以使用以下命令启动 *Data Flow Shell*：

```bash
$ java -jar spring-cloud-dataflow-shell-2.1.0.RELEASE.jar         \
  --dataflow.uri=http://localhost:9393                                \   
  --dataflow.username=my_username                                     \   
  --dataflow.password=my_password                                     \   
  --skip-ssl-validation  true                                         \   
```

| key                 | content                                         |
| ------------------- | ----------------------------------------------- |
| dataflow\.uri       | 可选，默认为[localhost：9393](http://localhost:9393/)。 |
| dataflow\.username  | 强制性。                                            |
| dataflow\.password  | 如果未提供密码，则会提示用户输入密码。                             |
| skip-ssl-validation | 可选，默认为`false`，忽略证书错误（使用自签名证书时）                  |

{% hint style="info" %}
请谨记，在启用 Spring Cloud Data Flow 身份验证时，使用 Shell 时，如果要通过用户名/密码进行身份验证 ，则底层 OAuth2 提供程序必须支持 Password OAuth2 Grant Type。
{% endhint %}

在 Data Flow Shell中，您还可以使用以下命令提供凭据：

```bash
server-unknown:>dataflow config server                                \
  --uri  http://localhost:9393                                        \   
  --username myuser                                                   \   
  --password mysecret                                                 \   
  --skip-ssl-validation  true                                         \   
```

下图显示了连接和验证 Data Flow Server 的 shell 命令：

![在Shell中使用数据流服务器进行目标和身份验证](https://raw.githubusercontent.com/spring-cloud/spring-cloud-dataflow/master/spring-cloud-dataflow-docs/src/main/asciidoc/images/dataflow-security-shell-target.png)

成功执行后，您应该看到以下输出：

```bash
dataflow:>dataflow config info
dataflow config info

╔═══════════╤═══════════════════════════════════════╗
║Credentials│[username='my_username, password=****']║
╠═══════════╪═══════════════════════════════════════╣
║Result     │                                       ║
║Target     │http://localhost:9393                  ║
╚═══════════╧═══════════════════════════════════════╝
```

或者，您可以指定 *credentials-provider* 命令以直接传入令牌，而不是提供用户名和密码。这可以在 shell 中运行，也可以在启动Shell时指定`--dataflow.credentials-provider-command`命令行参数。

{% hint style="danger" %}
使用credentials-provider命令时，请注意您的指定命令必须返回 *Bearer token*（以Bearer为前缀的token）。例如，在Unix环境中，可以使用以下简单命令：

```bash
$ java -jar spring-cloud-dataflow-shell-2.1.0.RELEASE.jar \
  --dataflow.uri=http://localhost:9393 \
  --dataflow.credentials-provider-command="echo Bearer 123456789"
```

{% endhint %}

### 8. 关于配置

&#x20;Spring Cloud Data Flow 的 相关 Restful API 包含显示名称，版本，包含name, version, 和Spring Cloud Data Flow 的 依赖项URL（如果指定了）。 shell dependency 还包括 sha1 或 sha256 的值的校验（如果启用）。通过设置以下属性，可以配置为每个依赖项返回的信息：

* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-core.name：用于核心的名称。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-core.version：用于核心的版本。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-dashboard.name：用于仪表板的名称。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-dashboard.version：用于仪表板的版本。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-implementation.name：用于实现的名称。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-implementation.version：用于实现的版本。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.name：用于shell的名称。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.version：用于shell的版本。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.url：用于下载shell依赖项的URL。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.checksum-sha1：与shell依赖关系信息一起返回的sha1校验和值。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.checksum-sha256：与shell依赖关系信息一起返回的sha256校验和值。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.checksum-sha1-url：如果`spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha1` 未指定，则SCDF使用此URL指定的文件内容作为校验和。
* spring.cloud.dataflow\.version-info.spring-cloud-dataflow-shell.checksum-sha256-url：如果`spring.cloud.dataflow.version-info.spring-cloud-dataflow-shell.checksum-sha256` 未指定，则SCDF使用此URL指定的文件内容作为校验和。

#### **8.1. 启用  Shell Checksum values**&#x20;

默认情况下，不会进行 shell dependency 的值的校验。如果需要启用此功能，请将该`spring.cloud.dataflow.version-info.dependency-fetch.enabled`属性设置为true。

#### **8.2. URL的 Reserved Values**

您可以在URL中插入 Reserved Values（用花括号括起来），以确保链接是最新的：

* repository ：如果使用 Data Flow 的构建快照，里程碑或候选发布版，则使用`repo-spring-io`存储库。否则，它指的是Maven Central。
* version：jar 的 pom的版本。

例如， 如果您用的是Spring Cloud Data Shell 的1.2.3.RELEASE版本，则会[`myrepository/org/springframework/cloud/spring-cloud-dataflow-shell/{version}/spring-cloud-dataflow-shell-{version}.jar`](https://myrepository/org/springframework/cloud/spring-cloud-dataflow-shell/%7Bversion%7D/spring-cloud-dataflow-shell-%7Bversion%7D.jar) 生成 [`myrepository/org/springframework/cloud/spring-cloud-dataflow-shell/1.2.3.RELEASE/spring-cloud-dataflow-shell-1.2.3.RELEASE.jar`](https://myrepository/org/springframework/cloud/spring-cloud-dataflow-shell/1.2.3.RELEASE/spring-cloud-dataflow-shell-1.2.3.RELEASE.jar)
