美文网首页
如何在.NET Core上建立Agora的AccessToken

如何在.NET Core上建立Agora的AccessToken

作者: horsefaced | 来源:发表于2020-09-23 20:40 被阅读0次

随着大量公司将办公会议、产品发布等改为网上进行后, 视频通信的安全性越来越成为受关注的重点。声网平台在 2.1.0 版本之后,通过使用 AccessToken 认证统一了视频通话RTC、录制、消息通讯RTM等各 SDK 的安全认证形式,相较于原先的 DynmicKey 更加方便于用户使用。

.NET Core 是微软的跨平台开发框架,可运行在 Windows、Linux、macOS 等操作系统之上,通过命令行工具就可以方便的创建、编译、运行,并可搭配 Docker 容器使用,方便嵌入微服务架构中。

本文将基于 .NET Core 3.1 版本说明如何建立一个 Agora RTC Token 服务,同样这个服务也可以用于录制和 RTM SDK中。

预备知识

  • 本文默认读者了解基本的 C# 编程知识,如果有需要可以访问C#文档 进行了解。

  • 本文需要 ASP.NET Core 及相关的 WebAPI 知识,如果有需要可以访问ASP.NET 文档进行了解。

  • 本文会有一点点 Git 相关的使用,但不是必要的。

本文所需工具

  • .NET Core SDK - 包括 .NET Core 运行时、开发包及命令行工具。

  • Visual Studio Code - 微软推出的跨平台开发工具,你也可以使用自己喜欢或习惯的开发工具。

  • .NET Core开发环境配置 - 如果你刚开始使用 Visual Studio Code,推荐阅读这个链接中的安装配置。

  • Git - 本文会使用到 Git 但不是必要条件,在相应章节会进行说明。

项目创建

  1. 打开终端,进入你平时开发目录

  2. 运行以下命令


dotnet new webapi -o AgoraTokenServer

code -r AgoraTokenServer

  1. 如果你正确的安装了 Visual Studio Code 的话,这时系统应该会打开 Visual Studio Code 程序并将 AgoraTokenServer 这个项目显示在左侧,如下图所示:
image

为了方便起见,以下 Visual Studio Code 将简称为 vscode。此时整个项目的目录结构应该如下图所示:

image-20200913165358515

我们将 WeatherForecast.cs 与 Controllers/WeatherForecastController.cs 删除,稍后我们将建立起自己的服务。

开发

引入工具代码

Agora 在其AgoraIO in GitHub中提供了 AccessToken 的 C# 实现,我们可以直接使用它。

  1. 进入AgoraIO in GitHub,点击页面上那个绿色的Code按钮
image-20200913170057183
  1. 如果你会 Git 那么可以直接在其他目录中,注意不要直接在上一章节建立的 AgoraTokenServer 项目目录中,把项目克隆下来。

git clone https://github.com/AgoraIO/Tools.git

​ 如果你不会 Git ,可以直接点击 Download ZIP 将其下载下来并解压缩。

image-20200913172902977
  1. 进入刚刚 Git 克隆或者下载解压缩后的目录

cd Tools/DynamicKey/AgoraDynamicKey/csharp/src/AgoraIO

将其中的 Common、Extensions、Media、Utils 四个目录直接拷贝至你创建的 AgoraTokenServer 目录下,之后你的 AgoraTokenServer 目录结构应该是如下图这样子的:

image-20200913174340000

解决依赖

你会发现上图中 Media/AccessToken.cs 是红色的,那是因为这个项目依赖于Crc32.NET这个包,如果你正确的安装了 .NET Core 的运行时和命令行工具的话 我们直接使用命令行将其安装就可以了。

进入 AgoraTokenServer 项目的根目录下,运行如下命令:


dotnet add package Crc32.NET

这样子我们唯一一个外部依赖包就解决了。

设置 AppID 与 AppCertificate

  1. 在通常环境中 AppCertificate 应当保存在安全性较高的服务端,不宜通过客户端请求进行传输,在 .NET Core 中这种设置通常可以保存在 appsetting.json 中。下面 appsetting.json 代码中的 AppID 和 AppCertificate 为示例,请在使用中替换为自己使用的对应 AppID 和 AppCertificate。

{

"AppSettings": {

"AppID": "970CA35de60c44645bbae8a215061b33",

"AppCertificate": "5CFd2fd1755d40ecb72977518be15d3b"

},

"Logging": {

"LogLevel": {

"Default": "Information",

"Microsoft": "Warning",

"Microsoft.Hosting.Lifetime": "Information"

}

},

"AllowedHosts": "*"

}

  1. 建立配置类

在 Utils 目录下创建一个名为 AppSettings.cs 的文件,文件内容为:


namespace AgoraTokenServer.Utils

{

public class AppSettings

{

public string AppID { get; set; }

public string AppCertificate { get; set; }

}

}

  1. 注入配置类

ASP.NET Core 使用依赖注入来解决整个程序的依赖问题,通过这个机制我们可以很方便的把上面定义的配置注入进去。依赖注入需要在 Startup.cs 文件中添加自定义的配置类,添加后 Startup.cs 文件内容如下:


using AgoraTokenServer.Utils;

using Microsoft.AspNetCore.Builder;

using Microsoft.AspNetCore.Hosting;

using Microsoft.Extensions.Configuration;

using Microsoft.Extensions.DependencyInjection;

using Microsoft.Extensions.Hosting;

namespace AgoraTokenServer

{

public class Startup

{

public Startup(IConfiguration configuration)

{

Configuration = configuration;

}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.

public void ConfigureServices(IServiceCollection services)

{

services.AddCors(); //添加跨域请求

services.AddControllers();

services.Configure<AppSettings>(Configuration.GetSection("AppSettings")); //添加程序配置

}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

{

if (env.IsDevelopment())

{

app.UseDeveloperExceptionPage();

}

app.UseHttpsRedirection();

app.UseRouting();

app.UseCors(x => x

.AllowAnyOrigin()

.AllowAnyMethod()

.AllowAnyHeader());

app.UseAuthorization();

app.UseEndpoints(endpoints =>

{

endpoints.MapControllers();

});

}

}

}

创建 Model

我们先定义两个对象来描述接受的内容和返回的结果。首先建立一个名为 Models 的目录,再在目录下创建两个文件。

  1. 请求对象文件

Path: /Models/AuthenticateRequest.cs

在 Models 目录下创建 AuthenticateRequest.cs 文件,文件内容为:


using System.ComponentModel.DataAnnotations;

namespace AgoraTokenServer.Models

{

public class AuthenticateRequest

{

[Required]

public string channel { get; set; }

[Required]

public dynamic uid { get; set; }

public uint expiredTs { get; set; } = 0;

public int role { get; set; } = 1;

}

}

因为 Agora 的用户标识有两种类型,一种是 uint 型,一种是 string 型的,所以这里直接使用 dynamic 类型来同时兼容两种类型。

  1. 回应对象

Path: /Models/AuthenticateResponse.cs

在 Models 目录下创建 AuthenticateResponse.cs 文件,文件内容为:


namespace AgoraTokenServer.Models

{

public class AuthenticateResponse

{

public string channel { get; set; }

public dynamic uid { get; set; }

public string token { get; set; }

}

}

  1. 现在项目的结构如下图:
image-20200913194237623

创建服务

  1. 现在我们创建一个控制器来提供服务,首先在 AgoraTokenServer 项目的 Controllers 目录下建立一个名为 AccessTokenController.cs 的文件。

Path: /Controllers/AccessTokenController.cs


using AgoraTokenServer.Models;

using Microsoft.AspNetCore.Mvc;

namespace AgoraTokenServer.Contollers

{

[ApiController]

[Route("[controller]")]

public class AccessTokenController : ControllerBase

{

}

}

  1. 添加程序配置

using AgoraTokenServer.Utils;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.Options;

namespace AgoraTokenServer.Contollers

{

[ApiController]

[Route("[controller]")]

public class AccessTokenController : ControllerBase

{

private readonly AppSettings appSettings;

public AccessTokenController(IOptions<AppSettings> appSettings)

{

this.appSettings = appSettings.Value;

}

}

}

  1. 添加请求处理部分

using System.Net;

using System.Text.Json;

using AgoraIO.Media;

using AgoraTokenServer.Models;

using AgoraTokenServer.Utils;

using Microsoft.AspNetCore.Mvc;

using Microsoft.Extensions.Options;

namespace AgoraTokenServer.Contollers

{

[ApiController]

[Route("[controller]")]

public class AccessTokenController : ControllerBase

{

private readonly AppSettings appSettings;

public AccessTokenController(IOptions<AppSettings> appSettings)

{

this.appSettings = appSettings.Value;

}

[HttpPost]

public ActionResult<AuthenticateResponse> index(AuthenticateRequest request)

{

if (string.IsNullOrEmpty(appSettings.AppID) || string.IsNullOrEmpty(appSettings.AppCertificate))

{

return new StatusCodeResult((int)HttpStatusCode.PreconditionFailed);

}

var uid = request.uid.ValueKind == JsonValueKind.Number ? request.uid.GetUInt64().ToString() : request.uid.GetString();

var tokenBuilder = new AccessToken(appSettings.AppID, appSettings.AppCertificate, request.channel, uid);

tokenBuilder.addPrivilege(Privileges.kJoinChannel, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kPublishAudioStream, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kPublishVideoStream, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kPublishDataStream, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kRtmLogin, request.expiredTs);

return Ok(new AuthenticateResponse

{

channel = request.channel,

uid = request.uid,

token = tokenBuilder.build()

});

}

}

}

在请求处理中,直接调用了从 AgoraIO 上下载的代码,并且在没有配置 AppID 和 AppCertificate 情况下会回报 412 错误。

同时,这个示例代码中直接将[kJoinChannel, kPublishAudioStream, kPublishVideoStream, kPubishDataStream, kRtmLogin] 的权限一次性给出来,你可以根据直接的需要,在 AuthenticateRequest 中添加权限申请的字段, 实现权限的申请功能。


[HttpPost]

public ActionResult<AuthenticateResponse> index(AuthenticateRequest request)

{

if (string.IsNullOrEmpty(appSettings.AppID) || string.IsNullOrEmpty(appSettings.AppCertificate))

{

return new StatusCodeResult((int)HttpStatusCode.PreconditionFailed);

}

var uid = request.uid.ValueKind == JsonValueKind.Number ? request.uid.GetUInt64().ToString() : request.uid.GetString();

var tokenBuilder = new AccessToken(appSettings.AppID, appSettings.AppCertificate, request.channel, uid);

tokenBuilder.addPrivilege(Privileges.kJoinChannel, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kPublishAudioStream, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kPublishVideoStream, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kPublishDataStream, request.expiredTs);

tokenBuilder.addPrivilege(Privileges.kRtmLogin, request.expiredTs);

return Ok(new AuthenticateResponse

{

channel = request.channel,

uid = request.uid,

token = tokenBuilder.build()

});

}

编译并运行

.NET Core 的编译和运行只需要通过命令行既可以解决,在 AgoraTokenServer 目录下,直接在命令行中运行


dotnet build

就可以编译整个工程了。

运行也很直接,直接在命令行中运行


dotnet run

就可以在 https://localhost:5001http://localhost:5000 上运行服务了。

如果你想改缺省的运行端口,推荐直接修改 Path: /Properties/launchSettings.json 文件中的 AgoraTokenServer 这一节的 applicationUrl 参数,其内容如下:


"AgoraTokenServer": {

"commandName": "Project",

"launchBrowser": true,

"launchUrl": "weatherforecast",

"applicationUrl": "https://localhost:5001;http://localhost:5000",

"environmentVariables": {

"ASPNETCORE_ENVIRONMENT": "Development"

}

}

因为修改过的 launchSettings.json 本身也会做为一个配置文件发布在最终运行目录中,这样子就不用吧端口写死在源代码中,或者在 Program.cs 中额外添加代码了。

测试结果

在本文中,使用Postman对服务进行测试,大家可以使用自己习惯的工具。在具体的请求中,因为 expiredTS 和 role 在程序中有缺省值,所以请求中就可以忽略,并且在现阶段,role 只有一个值,所以推荐可以暂时忽略这个。而 expiredTS 的具体用法,可以参考Agora官方网站的生成Token一文中的说明。

image-20200913214230336

具体的 Postman 请求结果如下图所示。

image-20200913213711509

如果你在使用 Postman 发送请求的时候发生了下图的错误:

image-20200913214838643

是因为你现在访问的 https 链接使用的证书是无效的,实际使用中你需要部署真实的证书,测试阶段你可以通过下图的 Settings 按钮将第一个 Enable SSL certificate verification 关闭

image-20200913215607065

完成

到现在为止,基于 .NET Core 的 Agora Token 服务已经开发完成。在实际使用中,还需要添加安全机制,这个可以根据你自己的具体架构情况进行完善。

.NET Core 的 docker 化可以参考微软的 Docker 容器 这编文章。

本文的所有代码都可以在 GitHub 上下载。

相关文章

网友评论

      本文标题:如何在.NET Core上建立Agora的AccessToken

      本文链接:https://www.haomeiwen.com/subject/bazoyktx.html