简介
使用声网平台时,如果你想为推流增加一层安全保障,可以添加一个 Token 服务。
本教程会教大家如何从运行声网 Token 服务器的 Web 服务中获取声网 token。
要想直接了解一个完整的 iOS app 如何通过特定的声网 token 服务器获取 token,点击查看 iOS 示例项目。
前期准备
- 有声网开发者帐户(详细步骤可参考这篇文章);
- 利用 Swift 进行 iOS 开发的基础知识;
- 最新版本的 Xcode;
- 一个本地或远程的声网 token 服务器(请参阅:声网 Token 服务示例代码);
- 使用声网 macOS 的 macOS app 或使用声网 iOS SDK 的 iOS app。
项目创建
可以阅读这篇文章查看如何创建 Token 服务器,该 GitHub 库包含帮大家快速创建 Token 服务器的所有代码。
完成 Token 服务器的创建之后,把它拉入应用程序中,本教程会示范怎么在 Swift 中做到这一点。
获取 Token
只有完整的 URL 才能访问 Token 服务。在我的例子中,该服务是在本地计算机上运行的,所以我访问的是 "http://localhost:8080/..."
,并且以 my-channel
作为频道名称、以 0
作为 userId。
如果你想在计算机上搭建服务器,但从 iOS 设备获取 Token,你可以使用 ngrok 之类的服务将请求路由到 localhost。
guard let tokenServerURL = URL(
string: "http://localhost:8080/rtc/my-channel/publisher/uid/0/"
) else {
return
}
接下来,我们需提出一个请求。我使用的是 Foundation 的 URLRequest
,
将请求的 httpMethod 设成 GET
,用 URLSession.shared.dataTask 创建任务,然后用 task.resume()
启动任务,如下所示:
var request = URLRequest(url: tokenServerURL, timeoutInterval: 10)
request.httpMethod = "GET"
let task = URLSession.shared.dataTask(
with: request
) { data, response, err in
// data task body here
}
task.resume()
我们可以在数据任务主体内部获取返回的 Token,可以这样写:
guard let data = data else {
// No data, no token
return
}
// parse response into json
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
// check that json has key "rtcToken"
let responseJSON = try? JSONSerialization.jsonObject(
with: data, options: []
) as? [String: Any]
if let token = responseJSON?["rtcToken"] as? String {
// Key "rtcToken" found in response, assigning to tokenToReturn
print("the token is: \(token)")
}
当 Token 抵达我们的设备时,main 方法可能已经返回了,因此我在下面的完整示例中添加了 DispatchSemaphore,用来保留 main 方法直至获得响应。这样我们就可以直接从方法中返回 Token,但这样可能会造成阻塞,所以如非必要,不要在主线程上运行此代码。
保持连接状态
通过此方法提供的所有 Token 都有有效期限,Token 服务器可以设置它们的有效期限,如果要更改,可以将其设置为请求中发送的参数。
如果已连接的用户的 Token 将在 30 秒后过期,就会调用 AgoraRtcEngineDelegate 的回调,这是再次连接 Token 服务器并请求更新 Token 的一种比较好的办法,无须使用 AgoraRtcEngineKit.renewToken(:String)
断开与频道的连接就能命令 RTC 引擎更新 Token。
完整示例
import Foundation
import Dispatch
/// - Parameters:
/// - domain: Domain which is hosting the Agora Token Server (ie http://localhost:8080)
/// - channelName: Name of the channel the token will allow the user to access
/// - userId: User ID requesting to join the server. A value of 0 works for all users.
/// - Returns: A new token which will expire in 24 Hours, or however specified by the token server.
/// An empty string response means that this function has failed.
func fetchRTCToken(domain: String, channelName: String, userId: UInt = 0) -> String {
// Construct the endpoint URL
guard let tokenServerURL = URL(string: "\(domain)/rtc/\(channelName)/publisher/uid/\(userId)/") else {
return ""
}
/// semaphore is used to wait for the request to complete, before returning the token.
let semaphore = DispatchSemaphore(value: 0)
var request = URLRequest(url: tokenServerURL, timeoutInterval: 10)
request.httpMethod = "GET"
var tokenToReturn = ""
// Construct the GET request
let task = URLSession.shared.dataTask(with: request) { data, response, err in
defer {
// Signal that the request has completed
semaphore.signal()
}
guard let data = data else {
// No data, no token
return
}
let responseJSON = try? JSONSerialization.jsonObject(with: data, options: [])
if let responseDict = responseJSON as? [String: Any], let token = responseDict["rtcToken"] as? String {
// Key "rtcToken" found in response, assigning to tokenToReturn
tokenToReturn = token
}
}
task.resume()
// Waiting for signal found inside the GET request handler
semaphore.wait()
return tokenToReturn
}
将以上代码添加到项目中时,请务必确保使用其他两个参数(response 和 err),因为它们能确保你的 Token 服务器的响应的有效性,还能帮你调试 bug。
我们要使用 joinChannel 发送加入频道的请求,获取到 Token 之后,将 Token 和加入频道的请求一起发送(查看声网——使用 Token 加入频道)。
要想查看从服务器获取 token 并 Token 失效前刷新 token 的 iOS 完整运行示例,可以点击查看声网 iOS Swift 示例项目。
上述项目中的 token 可以在声网 Token.swift 文件中获取和应用。
如果你已安装 Xcode,可以尝试在 Agora-Token-Swift 库中找到的 Agora-Swift-Token.playground 文件。你可以在自己的电脑上执行上述方法,查看从服务器中检索到的 token。
原文作者:Max Cobb
原文链接:https://www.agora.io/en/blog/connecting-to-agora-with-tokens-using-swift/