【问题标题】:Custom redirect URI to macOS app not working自定义重定向 URI 到 macOS 应用程序不起作用
【发布时间】:2023-03-07 03:39:01
【问题描述】:

重定向的目的

我正在开发一个与 Cisco 的 Webex Teams Api 集成的应用程序。不幸的是,对于 macOS,他们没有 SDK(他们只有一个用于 iOS),所以我试图用他们的 Api 类型的“手动”进行身份验证。

因此,我使用了一个自定义 URL,该 URL 具有支持的客户端 ID 来检索代码。调用此 URL 时,思科的常规登录程序开始,要求用户使用她/他的用户名和密码登录。成功登录后,Cisco 的服务器会为您提供一个 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=&amp;state=loggedIn.

因此,Cisco 端的身份验证过程是成功的,它为我的系统提供了 URL——我的计算机不知道如何处理……我什至可以看到我需要在 URL 中检索访问权限的代码那又回来了,我只是没有在我的应用程序中继续...

我错过了什么?

很明显,我在这里遗漏了一些重要的东西——我只是不知道它是什么,并且在线研究对我没有帮助。我可以在这里和那里找到一些零碎的东西,但我仍然想找到一个简明的说明,说明我的 macOS 应用程序在我的情况下应该做什么。

环境

  • Xcode 10.1
  • 斯威夫特 4.2
  • 可可应用
  • 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")
    }

}

【问题讨论】:

  • 你让它工作了吗?
  • 是的,我有(请参阅下面我接受的答案)。以我有限的技能组合对我来说是一个受欢迎的解决方法 - 虽然你的里程可能会有所不同,并且禁用沙盒可能不是你想要的......

标签: xcode cocoa wkwebview cisco webex


【解决方案1】:

在 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 并让它从服务器加载一个最小的网页,只包含一个带有自定义方案的链接 - 正如预期的那样,单击此链接会触发带有自定义方案的 openURL 方法(必须添加需要 NSAppTransportSecurity 字典到 Info.plist 并在项目的沙箱设置中启用传出连接)。

过去,我看到一些第 3 方浏览器使用包含连字符和点的自定义方案。对于 WKWebView 和操作系统中的底层自定义 URL 方案处理,这似乎没有问题;在使用 NSWorkspace 方法和 WKWebView 进行测试时,no.half-bits 而不是 nohalfbits 可以正常工作。

【讨论】:

  • 感谢您的输入-不幸的是没有帮助...尝试不使用://,还尝试反转以最终获得具有以下签名的重定向uri:dq-notfall://ch.appfros.webexoauthwokflowprototype?code=&lt;ACCESS_CODE&gt;&amp;state=loggedIn(顺便说一句,我不明白为什么苹果不希望我们对 URL 方案使用反向 url,因为那样该方案肯定是唯一的......)。显然也必须在思科方面进行更改。我只是在想:我是否遇到问题是因为我的系统不知道? 之后的url 附带的参数?
  • 对不起,我在阅读您的问题时似乎不够彻底;查看我的更新答案
  • 按照您的提示更改了我的 AppDelegate(见上文)- 不幸的是它仍然无法正常工作...一定有什么地方出了问题...
  • 不,将处理程序注册放入applicationWillFinishLaunching。 AE 在达到 didFinishLaunching 之前发送(但只有在自定义 url 方案正在启动应用程序时才会产生影响,而不是在它已经运行时)
  • 是的,这也无济于事——在我看来,macOS 仍然不知道我的(已经打开的应用程序)可以处理这个链接。再次更新了我上面的帖子,以便您可以看到 AppDelegate 的当前版本。
【解决方案2】:

事实证明,沙盒确实是问题所在。禁用沙盒后——这将是我公司的一个小帮手,没什么花哨的,而且对于任何商店来说肯定没有——它马上就起作用了。

如果需要,我将不得不研究如何实现 NSAppTransportSecurity - 感谢 @NoHalfBits 将我推向正确的方向。

所以现在我有

  • 注册的自定义网址
  • 应用沙盒已禁用
  • func application(_ application: NSApplication, open urls: [URL]) 在我的 AppDelegate 中实现(事实证明,正如 @Aaron Raimist 所说,这真的足够了

感谢您的帮助;希望这可以帮助其他人(或我未来的自己):-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 1970-01-01
    • 2017-09-11
    • 1970-01-01
    相关资源
    最近更新 更多