自定义重定向 URI 到 macOS 应用程序不起作用
Custom redirect URI to macOS app not working
重定向的目的
我正在开发一个与 Cisco 的 Webex Teams 集成的应用程序 Api。不幸的是,对于 macOS,他们没有 SDK(他们只有一个用于 iOS),所以我正在尝试使用他们的 Api 类型的 "manually" 进行身份验证。
所以,我正在使用自定义 URL,它有一个客户端 ID 来检索代码。当调用此 URL 时,Cisco 的常规登录程序开始,要求用户使用她/他的用户名和密码登录。成功登录后,Cisco 的服务器会为您提供一个 URL,其中包含一个代码,然后需要该代码才能继续。
到目前为止我得到了什么
自定义url
我的原型目前只包含一个调用自定义 URL 进行身份验证的按钮。要获得此 URL,我需要在此处注册与 Cisco 的集成:https://developer.webex.com/my-apps
到目前为止,当我点击我的按钮时,一个 WKWebView 实例接管了我的自定义 URL:
https://api.ciscospark.com/v1/authorize?client_id=<**personalClientId**>&response_type=code&redirect_uri=<**BundleIdentifier**>3A%2F%2Fredirect&scope=spark%3Aall%20spark%3Akms&state=set_state_here
重定向 URI
所以,我的重定向 uri 当前是 ch.appfros.webexoauthwokflowprototype://redirect;此重定向 uri 已在我的集成注册表中向 Cisco 注册。
我知道我必须将此重定向 uri 放入我的应用程序中,所以我这样做导致相应的 info.plist
部分如下所示:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>response</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ch.appfros.webexoauthwokflowprototype://</string>
</array>
</dict>
</array>
正在准备 AppDelegate
据我目前所知,似乎我还需要在 AppDelegate
中添加一个处理回调的函数。对于 cocoa
,这似乎是 func application(_ application: NSApplication, open urls: [URL])
方法。
据我所知,我必须在那里处理所有重定向。我的 AppDelegate
目前看起来像这样:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func application(_ application: NSApplication, open urls: [URL]) {
print("got answer")
}
}
我遇到的问题
我的问题是,完成登录过程会导致消息 There is no application set to open the URL ch.appfros.webexoauthwokflowprototype://redirect?code=
&state=loggedIn.
因此,Cisco 端的身份验证过程成功,它为我的系统提供了 URL -- 我的计算机不知道如何处理...我什至可以看到我需要的代码在即将返回的 URL 中检索访问权限,我只是在我的应用程序中没有它们来继续...
我错过了什么?
很明显,我在这里遗漏了一些重要的东西——我只是不知道它是什么,在线研究对我没有帮助。我可以在这里和那里找到点点滴滴,但我仍然要找到关于我的 macOS 应用程序如何处理的简明说明。
环境
- Xcode10.1
- Swift 4.2
- Cocoa 应用
- Cisco Webex Teams 与身份验证集成 URL
编辑:对 AppDelegate 的更改
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application)
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func application(_ application: NSApplication, open urls: [URL]) {
print("got answer")
}
@objc
func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
print("got answer in event handler")
}
}
编辑 2:更新 AppDelegate(以反映 NoHalfBits 的提示和技巧)
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application)
}
func applicationWillFinishLaunching(_ notification: Notification) {
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func application(_ application: NSApplication, open urls: [URL]) {
print("got answer")
}
@objc
func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
print("got answer in event handler")
}
}
在Info.plist中,在CFBundleURLSchemes
键下的数组中指定URL方案,不带://
后缀(ch.appfros.webexoauthwokflowprototype
而不是ch.appfros.webexoauthwokflowprototype://
).
顺便说一句,Apple 建议对 CFBundleURLName
(名称,而不是方案本身).
使用反向 DNS 样式标识符
我设置了一个最小的测试项目:Xcode 10.1,Cocoa app Swift 模板。定义自定义方案的 Info.plist 部分是:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>no.half.bits</string>
<key>CFBundleURLSchemes</key>
<array>
<string>nohalfbits</string>
</array>
</dict>
</array>
应用委托人是:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
func application(_ application:NSApplication, open urls: [URL]) {
print("openURLs:", urls)
}
}
这在使用小型命令行工具进行测试时按预期工作:
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[])
{
@autoreleasepool
{
NSURL* url = [NSURL URLWithString:@"nohalfbits://hello.world"];
// is there app that handles the scheme, and where is it
NSLog(@"appURL = %@", [NSWorkspace.sharedWorkspace URLForApplicationToOpenURL:url]);
// actually open the url; the app should log this
[NSWorkspace.sharedWorkspace openURL:url];
}
return 0;
}
我还在项目中添加了一个 WKWebView 并让它从服务器加载一个最小的网页,只包含一个带有自定义方案的 link - 正如预期的那样,单击此 link 会触发打开使用自定义方案的 URL 方法(必须将所需的 NSAppTransportSecurity
字典添加到 Info.plist 并在项目的沙箱设置中启用传出连接)。
过去,我看到一些第 3 方浏览器在包含连字符和点的自定义方案上阻塞。对于 WKWebView 和 os 中的底层自定义 URL 方案处理,这似乎没有问题; no.half-bits
而不是 nohalfbits
在使用 NSWorkspace 方法和 WKWebView 进行测试时按预期工作。
事实证明,沙盒确实是问题所在。禁用沙盒后——这将是我公司的一个小帮手,没什么特别的,对任何商店来说肯定没什么——它马上就起作用了。
如果需要,我将不得不研究 NSAppTransportSecurity
需要如何实施——感谢@NoHalfBits 将我推向正确的方向。
所以现在我有
- 自定义 url 已注册
- 应用沙盒已禁用
func application(_ application: NSApplication, open urls: [URL])
在我的 AppDelegate 中实现(事实证明这真的足够了,正如@Aaron Raimist 所说
感谢您的帮助;希望这可以帮助其他人(或我未来的自己):-)
重定向的目的
我正在开发一个与 Cisco 的 Webex Teams 集成的应用程序 Api。不幸的是,对于 macOS,他们没有 SDK(他们只有一个用于 iOS),所以我正在尝试使用他们的 Api 类型的 "manually" 进行身份验证。
所以,我正在使用自定义 URL,它有一个客户端 ID 来检索代码。当调用此 URL 时,Cisco 的常规登录程序开始,要求用户使用她/他的用户名和密码登录。成功登录后,Cisco 的服务器会为您提供一个 URL,其中包含一个代码,然后需要该代码才能继续。
到目前为止我得到了什么
自定义url
我的原型目前只包含一个调用自定义 URL 进行身份验证的按钮。要获得此 URL,我需要在此处注册与 Cisco 的集成:https://developer.webex.com/my-apps
到目前为止,当我点击我的按钮时,一个 WKWebView 实例接管了我的自定义 URL:
https://api.ciscospark.com/v1/authorize?client_id=<**personalClientId**>&response_type=code&redirect_uri=<**BundleIdentifier**>3A%2F%2Fredirect&scope=spark%3Aall%20spark%3Akms&state=set_state_here
重定向 URI
所以,我的重定向 uri 当前是 ch.appfros.webexoauthwokflowprototype://redirect;此重定向 uri 已在我的集成注册表中向 Cisco 注册。
我知道我必须将此重定向 uri 放入我的应用程序中,所以我这样做导致相应的 info.plist
部分如下所示:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>response</string>
<key>CFBundleURLSchemes</key>
<array>
<string>ch.appfros.webexoauthwokflowprototype://</string>
</array>
</dict>
</array>
正在准备 AppDelegate
据我目前所知,似乎我还需要在 AppDelegate
中添加一个处理回调的函数。对于 cocoa
,这似乎是 func application(_ application: NSApplication, open urls: [URL])
方法。
据我所知,我必须在那里处理所有重定向。我的 AppDelegate
目前看起来像这样:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application)
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func application(_ application: NSApplication, open urls: [URL]) {
print("got answer")
}
}
我遇到的问题
我的问题是,完成登录过程会导致消息 There is no application set to open the URL ch.appfros.webexoauthwokflowprototype://redirect?code=
&state=loggedIn.
因此,Cisco 端的身份验证过程成功,它为我的系统提供了 URL -- 我的计算机不知道如何处理...我什至可以看到我需要的代码在即将返回的 URL 中检索访问权限,我只是在我的应用程序中没有它们来继续...
我错过了什么?
很明显,我在这里遗漏了一些重要的东西——我只是不知道它是什么,在线研究对我没有帮助。我可以在这里和那里找到点点滴滴,但我仍然要找到关于我的 macOS 应用程序如何处理的简明说明。
环境
- Xcode10.1
- Swift 4.2
- Cocoa 应用
- Cisco Webex Teams 与身份验证集成 URL
编辑:对 AppDelegate 的更改
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application)
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func application(_ application: NSApplication, open urls: [URL]) {
print("got answer")
}
@objc
func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
print("got answer in event handler")
}
}
编辑 2:更新 AppDelegate(以反映 NoHalfBits 的提示和技巧)
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application)
}
func applicationWillFinishLaunching(_ notification: Notification) {
NSAppleEventManager.shared().setEventHandler(self, andSelector: #selector(self.handleAppleEvent(event:replyEvent:)), forEventClass: AEEventClass(kInternetEventClass), andEventID: AEEventID(kAEGetURL))
}
func applicationWillTerminate(_ aNotification: Notification) {
// Insert code here to tear down your application
}
func application(_ application: NSApplication, open urls: [URL]) {
print("got answer")
}
@objc
func handleAppleEvent(event: NSAppleEventDescriptor, replyEvent: NSAppleEventDescriptor) {
print("got answer in event handler")
}
}
在Info.plist中,在CFBundleURLSchemes
键下的数组中指定URL方案,不带://
后缀(ch.appfros.webexoauthwokflowprototype
而不是ch.appfros.webexoauthwokflowprototype://
).
顺便说一句,Apple 建议对 CFBundleURLName
(名称,而不是方案本身).
我设置了一个最小的测试项目:Xcode 10.1,Cocoa app Swift 模板。定义自定义方案的 Info.plist 部分是:
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>no.half.bits</string>
<key>CFBundleURLSchemes</key>
<array>
<string>nohalfbits</string>
</array>
</dict>
</array>
应用委托人是:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
@IBOutlet weak var window: NSWindow!
func application(_ application:NSApplication, open urls: [URL]) {
print("openURLs:", urls)
}
}
这在使用小型命令行工具进行测试时按预期工作:
#import <Cocoa/Cocoa.h>
int main(int argc, const char * argv[])
{
@autoreleasepool
{
NSURL* url = [NSURL URLWithString:@"nohalfbits://hello.world"];
// is there app that handles the scheme, and where is it
NSLog(@"appURL = %@", [NSWorkspace.sharedWorkspace URLForApplicationToOpenURL:url]);
// actually open the url; the app should log this
[NSWorkspace.sharedWorkspace openURL:url];
}
return 0;
}
我还在项目中添加了一个 WKWebView 并让它从服务器加载一个最小的网页,只包含一个带有自定义方案的 link - 正如预期的那样,单击此 link 会触发打开使用自定义方案的 URL 方法(必须将所需的 NSAppTransportSecurity
字典添加到 Info.plist 并在项目的沙箱设置中启用传出连接)。
过去,我看到一些第 3 方浏览器在包含连字符和点的自定义方案上阻塞。对于 WKWebView 和 os 中的底层自定义 URL 方案处理,这似乎没有问题; no.half-bits
而不是 nohalfbits
在使用 NSWorkspace 方法和 WKWebView 进行测试时按预期工作。
事实证明,沙盒确实是问题所在。禁用沙盒后——这将是我公司的一个小帮手,没什么特别的,对任何商店来说肯定没什么——它马上就起作用了。
如果需要,我将不得不研究 NSAppTransportSecurity
需要如何实施——感谢@NoHalfBits 将我推向正确的方向。
所以现在我有
- 自定义 url 已注册
- 应用沙盒已禁用
func application(_ application: NSApplication, open urls: [URL])
在我的 AppDelegate 中实现(事实证明这真的足够了,正如@Aaron Raimist 所说
感谢您的帮助;希望这可以帮助其他人(或我未来的自己):-)