ASP.NET Core
本指南介绍了与 ASP.NET Core 应用程序的集成。如果您想直接跳转到代码,可以在 GitHub 上找到本指南中描述的应用程序的完整代码。
# 先决条件
在开始之前,请确保您的系统中已安装 .NET SDK 7.0
。如果命令行中无法使用 dotnet
工具,请先访问 .NET SDK 下载页面。
# 创建应用程序
作为示例的基础,我们将创建一个新的项目目录和一个使用以下命令创建的空 ASP.NET 项目
dotnet new web --name AspdotnetCkbox
项目创建后,您可以启动开发服务器
cd AspdotnetCkbox
dotnet run
该应用程序将在控制台中列出的端口下可用,例如 https://127.0.0.1:5063。您也可以在 Properties/launchSettings.json
文件中调整端口。
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "https://127.0.0.1:52536",
"sslPort": 44341
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://127.0.0.1:5063",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://127.0.0.1:7029;https://127.0.0.1:5063",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
# 创建令牌端点
CKBox 与其他 CKEditor 云服务一样,使用 JWT 令牌进行身份验证和授权。有关如何创建访问凭据的信息,请参阅 身份验证 指南中的 创建访问凭据 部分。
现在我们有了所需的访问凭据,即:环境 ID 和访问密钥,让我们创建令牌端点。
首先,让我们安装 System.IdentityModel.Tokens.Jwt 包,用于创建 JWT 令牌。
dotnet add package System.IdentityModel.Tokens.Jwt
# 完整端点代码
// Program.cs
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapGet("/token", () =>
{
var environmentId = builder.Configuration.GetValue<string>("CKBoxEnvironmentId");
var accessKey = builder.Configuration.GetValue<string>("CKBoxAccessKey");
var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(accessKey));
var signingCredentials = new SigningCredentials(securityKey, "HS256");
var header = new JwtHeader(signingCredentials);
var dateTimeOffset = new DateTimeOffset(DateTime.UtcNow);
var payload = new JwtPayload
{
{ "aud", environmentId },
{ "iat", dateTimeOffset.ToUnixTimeSeconds() },
{ "sub", "user-123" },
{ "user", new Dictionary<string, string> {
{ "email", "joe.doe@example.com" },
{ "name", "Joe Doe" }
} },
{ "auth", new Dictionary<string, object> {
{ "ckbox", new Dictionary<string, string> {
{ "role", "admin" }
} }
} }
};
var securityToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(securityToken);
});
app.Run();
正如您在上面的代码清单中所看到的,签署 JWT 令牌所需的访问凭据是从 Configuration 对象中获取的。借助此功能,您可以方便地将它们添加到 appsettings.json
文件中
{
"CKBoxAccessKey": "REPLACE-WITH-ACCESS-KEY",
"CKBoxEnvironmentId": "REPLACE-WITH-ENVIRONMENT-ID",
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
# 将 CKBox 脚本添加到页面
CKBox 可以通过多种方式嵌入到应用程序中。为简单起见,在本例中,我们将使用从 CDN 提供的 CKBox 脚本。
本指南中的示例将涵盖使用 CKBox 的三种常见场景
- CKBox 与 CKEditor 5 集成。
- CKBox 用作对话框模式下的文件选择器。
- CKBox 用作全页面应用程序。
首先,让我们向我们的应用程序添加 Razor 模板支持。
// Program.cs
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Microsoft.IdentityModel.Tokens;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
var app = builder.Build();
app.MapGet("/token", () =>
{
var environmentId = builder.Configuration.GetValue<string>("CKBoxEnvironmentId");
var accessKey = builder.Configuration.GetValue<string>("CKBoxAccessKey");
var securityKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(accessKey));
var signingCredentials = new SigningCredentials(securityKey, "HS256");
var header = new JwtHeader(signingCredentials);
var dateTimeOffset = new DateTimeOffset(DateTime.UtcNow);
var payload = new JwtPayload
{
{ "aud", environmentId },
{ "iat", dateTimeOffset.ToUnixTimeSeconds() },
{ "sub", "user-123" },
{ "user", new Dictionary<string, string> {
{ "email", "joe.doe@example.com" },
{ "name", "Joe Doe" }
} },
{ "auth", new Dictionary<string, object> {
{ "ckbox", new Dictionary<string, string> {
{ "role", "admin" }
} }
} }
};
var securityToken = new JwtSecurityToken(header, payload);
var handler = new JwtSecurityTokenHandler();
return handler.WriteToken(securityToken);
});
app.MapRazorPages();
app.Run();
为了避免代码重复,让我们准备一个包含 CKBox 脚本的基本布局,我们将在所有三个示例中重复使用该布局
Pages/Shared/_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>CKBox example</title>
<script src="https://cdn.ckbox.io/ckbox/2.5.1/ckbox.js"></script>
@await RenderSectionAsync("Head", required: false)
</head>
<body>
@RenderBody()
</body>
</html>
现在,让我们添加三个示例的页面。
# CKBox 与 CKEditor 5
在本例中,我们将使用最快速简便的方式运行 CKEditor 5 - 从 CDN 提供。有关更高级的集成方案,请参阅 CKEditor 5 文档。
让我们创建扩展我们在上一步中创建的布局的子视图
Pages/index.cshtml
@page
@{
Layout = "Shared/_Layout";
var tokenUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/token";
}
@section 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" />
}
<div>
<textarea id="editor">@Html.Raw("Hello world")</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'
},
toolbar: [
'ckbox', '|', 'undo', 'redo', '|', 'bold', 'italic', '|',
'fontSize', 'fontFamily', 'fontColor', 'fontBackgroundColor'
],
} )
.catch( error => {
console.error( error );
} );
</script>
</div>
上面的示例包含从 CDN 提供的 预定义的 CKEditor 5 构建,其中包含所需的 CKBox 插件。然后,通过设置 ckbox
属性的必需参数,将 CKEditor 5 配置为使用 CKBox。请注意,在 ckbox.tokenUrl
配置选项中,我们传递了之前步骤中创建的令牌端点的 URL,该 URL 将用于获取用于在 CKBox 中验证用户的 JWT 令牌。
# CKBox 作为文件选择器
常见场景之一是将 CKBox 用作文件选择器,用户可以在其中选择文件管理器中存储的文件之一。选择文件后,我们希望获取有关所选文件的信息,尤其是它们的 URL。这可以通过使用作为 CKBox 配置选项传递的 assets.onChoose
回调来实现
Pages/filePicker.cshtml
@page
@{
Layout = "Shared/_Layout";
var tokenUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/token";
}
<div>
<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: '@tokenUrl',
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>
</div>
该示例将在 https://127.0.0.1:5063/filePicker 下可用。
# CKBox 在全页面模式下
要以全页面模式启动 CKBox,您可以将其附加到 document.body
并调整所需的 CSS 样式
Pages/fullPage.cshtml
@page
@{
Layout = "Shared/_Layout";
var tokenUrl = $"{HttpContext.Request.Scheme}://{HttpContext.Request.Host}/token";
}
@section Head {
<style>
html, body {
margin: 0;
padding: 0;
height: 100vh;
}
</style>
}
<div>
<script>
CKBox.mount(document.body, {
tokenUrl: '@tokenUrl',
});
</script>
</div>
该示例将在 https://127.0.0.1:5063/fullPage 下可用。
# 完整代码
您可以在 GitHub 上找到本指南中描述的应用程序的完整代码。