Spring Boot
本指南介绍了在 Spring Boot 应用程序中集成 CKBox 的方法。如果你想直接跳到代码,可以在 GitHub 上找到本指南中描述的 应用程序的完整代码。
# 先决条件
在开始之前,请确保你的系统中安装了最新版本的 JDK。如果命令行中没有此工具,请先按照 JDK 安装说明 进行操作。
# 创建应用程序
作为示例的基础,我们将使用 Spring Initializr 向导创建一个新的 Spring Boot 项目。本文档中的示例将使用 Maven。如果你想一步一步地遵循本指南,请将你的项目类型设置为“Maven”。你也可以使用其他项目类型,并将命令和配置替换为其他工具中的等效项。
在本指南中创建项目时使用的参数
- 组:
io.ckbox
- 工件:
spring-example
- 名称:
spring-example
- 项目:
Maven
- 语言:
Java
- 依赖项:Spring Web
项目创建后,启动开发服务器
./mvnw spring-boot:run
# 创建授权控制器
首先,让我们创建一个控制器。控制器将负责服务令牌端点,用于在 CKBox 中对用户进行身份验证。
CKBox 以及其他 CKEditor 云服务使用 JWT 令牌进行身份验证和授权。所有这些令牌都在你的应用程序端生成,并使用你可以在 CKEditor 生态系统仪表板 中获取的共享密钥进行签名。有关如何创建访问凭据的信息,请参阅 身份验证指南 中的 创建访问凭据 部分。
现在我们有了所需的访问凭据,即:环境 ID 和访问密钥,让我们创建令牌端点。
首先,让我们将用于创建 JWT 令牌的 com.auth0.jwt
库添加到 pom.xml
文件中
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>4.4.0</version>
</dependency>
该依赖项将在下次应用程序启动时安装。
# 完整控制器代码
// src/main/java/io/ckbox/springexample/CKBoxController.java
package io.ckbox.springexample;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.*;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.JWT;
@RestController
public class CKBoxController {
@Value("${environment_id}")
private String environmentId;
@Value("${access_key}")
private String accessKey;
@GetMapping("/ckbox/auth")
public String tokenEndpoint() throws Exception {
Map<String, Object> authClaim = new HashMap<>() {{
put("ckbox", new HashMap<>() {{
put("role", "user");
}});
}};
Algorithm algorithm = Algorithm.HMAC256(this.accessKey.getBytes("ASCII"));
String token = JWT.create()
.withAudience(this.environmentId)
.withIssuedAt(Instant.now())
.withSubject("user id")
.withClaim("auth", authClaim)
.sign(algorithm);
return token;
}
}
如上面的代码清单所示,签名 JWT 令牌所需的访问凭据是从环境变量中获取的。现在,你可以使用以下命令运行应用程序
environment_id=REPLACE-WITH-ENVIRONMENT-ID access_key=REPLACE-WITH-ACCESS-KEY ./mvnw spring-boot:run
# 将 CKBox 脚本添加到页面
CKBox 可以使用多种方式嵌入应用程序中,有多种方法。为了简单起见,我们将使用从 CDN 提供的 CKBox 脚本。
本指南中的示例将涵盖三种常见的 CKBox 使用场景
- CKBox 与 CKEditor 5 集成。
- CKBox 用作对话框模式下的文件选择器。
- CKBox 用作全页面应用程序。
为了避免代码重复,让我们准备一个包含 CKBox 脚本的基本 Thymeleaf 布局模板,我们将在所有三个示例中重复使用它。首先,将 Thymeleaf 依赖项添加到 pom.xml
文件中
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
然后,你可以创建一个布局文件
<!-- src/main/resources/templates/layout.html -->
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<html>
<head>
<meta charset="UTF-8"/>
<title>CKBox example</title>
<script src="https://cdn.ckbox.io/ckbox/2.1.0/ckbox.js"></script>
</head>
<body>
<section layout:fragment="content">
<p>Page content goes here</p>
</section>
</body>
</html>
最后,为示例准备一个 MVP 控制器
// src/main/java/io/ckbox/springexample/CKBoxExampleWebpageController.java
package io.ckbox.springexample;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
@Controller
public class CKBoxExampleWebpageController {
}
# CKBox 与 CKEditor 5
在本示例中,我们将使用最快速、最简单的方法运行 CKEditor 5 – 从 CDN 提供。有关更高级的集成场景,请参阅 CKEditor 5 文档。
让我们创建扩展我们之前创建的布局的子视图
<!-- src/main/resources/templates/ckbox-example-ckeditor.html -->
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<head>
<script type="importmap">
{
"imports": {
"ckeditor5": "https://cdn.ckeditor.com/ckeditor5/42.0.0/ckeditor5.js",
"ckeditor5/": "https://cdn.ckeditor.com/ckeditor5/42.0.0/"
}
}
</script>
<link rel="stylesheet" href="https://cdn.ckeditor.com/ckeditor5/42.0.0/ckeditor5.css" />
</head>
<body>
<section layout:fragment="content">
<textarea id="editor"><h1>Example</h1><p>Hello world</p></textarea>
<script type="module">
import {
ClassicEditor,
CKBox,
Essentials,
Bold,
Italic,
Font,
Paragraph
} from 'ckeditor5';
ClassicEditor
.create( document.querySelector( '#editor' ), {
plugins: [ CKBox, Essentials, Bold, Italic, Font, Paragraph ],
ckbox: {
tokenUrl: 'https://your.token.url',
theme: 'lark',
allowExternalImagesEditing: [ /^data:/, 'origin', /ckbox/ ]
},
toolbar: [
'ckbox', '|', 'undo', 'redo', '|', 'bold', 'italic', '|',
'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor'
],
} )
.catch( error => {
console.error( error );
} );
</script>
</section>
</body>
</html>
并将视图添加到控制器中
@Controller
public class CKBoxExampleWebpageController {
@GetMapping("/ckbox-example-ckeditor")
public String ckeditorExample(Model model) {
return "ckbox-example-ckeditor";
}
}
上面的示例包含从 CDN 提供的 预定义的 CKEditor 5 版本,其中包括所需的 CKBox 插件。然后,通过设置 ckbox
属性的必需参数,将 CKEditor 5 配置为使用 CKBox。请注意,在 ckbox.tokenUrl
配置选项中,我们传递了之前步骤中创建的令牌端点的 URL。它将用于获取用于在 CKBox 中对用户进行身份验证的 JWT 令牌。
# CKBox 作为文件选择器
常见的场景之一是使用 CKBox 作为文件选择器,用户可以选择文件管理器中存储的文件之一。选择文件后,我们要获取有关所选文件的信息,特别是它们的 URL。这可以通过使用作为 CKBox 配置选项传递的 assets.onChoose
回调来实现
<!-- src/main/resources/templates/ckbox-example-modal.html -->
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<body>
<section layout:fragment="content">
<input type="text" id="file-url"></input><button id="choose">Choose file</button>
<div id="ckbox"></div>
<script>
document.getElementById('choose').addEventListener('click', function () {
CKBox.mount(document.querySelector('#ckbox'), {
tokenUrl: `${ location.origin }/ckbox/auth`,
dialog: true,
assets: {
// Callback executed after choosing assets
onChoose: (assets) => {
document.getElementById('file-url').value = assets[0].data.url;
assets.forEach((asset) => {
console.log(asset.data.url);
})
}
}
});
});
</script>
</section>
</body>
</html>
@Controller
public class CKBoxExampleWebpageController {
// ...
@GetMapping("/ckbox-example-modal")
public String modalExample(Model model) {
return "ckbox-example-modal";
}
}
# CKBox 在全屏模式下
要以全屏模式启动 CKBox,你可以将它附加到 document.body
并调整所需的 CSS 样式
<!-- src/main/resources/templates/ckbox-example-full-page.html -->
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout}">
<style>
html, body {
margin: 0;
padding: 0;
height: 100vh;
}
</style>
<body>
<section layout:fragment="content">
<script>
CKBox.mount(document.body, {
tokenUrl: `${ location.origin }/ckbox/auth`
});
</script>
</section>
</body>
</html>
@Controller
public class CKBoxExampleWebpageController {
// ...
@GetMapping("/ckbox-example-full-page")
public String fullPageExample(Model model) {
return "ckbox-example-full-page";
}
}
# 完整代码
您可以在 GitHub 上找到本指南中描述的 应用程序的完整代码。