Swift/MSAL异步调用时出现‘internal保护级别导致无法访问’错误,但原完成块代码无此问题
Swift/MSAL异步调用时出现‘internal保护级别导致无法访问’错误,但原完成块代码无此问题
我来帮你分析这个问题,看起来你在把MSAL的回调式调用改成async/await后遇到了访问权限问题,而原来的代码却能正常运行,这大概率和API的访问权限或者MSAL的API风格变化有关,下面给你拆解原因和解决方案:
可能的原因分析
- MSAL API版本迭代的变化:新版MSAL已经把Objective-C风格的
getGlobalId()、getUserName()这类getter方法,替换成了更符合Swift习惯的属性(比如globalId、userName),原来的getter方法被标记为internal不再对外公开。你的旧代码可能基于老版本MSAL编写,当时这些方法还是公开的,所以没报错。 - 自定义异步封装的类型问题:你自己封装的
B2CAuthApi.logInAsync方法,可能在返回结果时,result.account的类型不是公开的MSALAccount,而是MSAL内部的子类(比如MSALAccountInternal),导致你在外部无法访问这些内部方法。
解决方案
方案1:改用MSAL官方的异步API(推荐)
MSAL本身已经提供了async/await版本的API,不需要手动封装续体,直接用官方方法能确保拿到正确的公开类型:
public func logIn(msalApplication: MSALPublicClientApplication, webViewParameters: MSALWebviewParameters) async throws { let interactiveParameters = MSALInteractiveTokenParameters(scopes: [], webviewParameters: webViewParameters) let result = try await msalApplication.acquireToken(with: interactiveParameters) if !result.accessToken.isEmpty { self.accountToken = result.accessToken } self.accountTokenExpiration = result.expiresOn self.account = result.account self.isAuthenticated = true // 改用Swift风格的属性访问 self.accountGlobalId = result.account.globalId self.accountUserName = result.account.userName }
方案2:修复自定义封装的logInAsync方法
如果必须使用自己的封装,要确保返回的结果类型是公开的MSALResult,并且account是MSALAccount类型:
先检查你的B2CAuthApi.logInAsync实现,确保续体返回正确的公开类型:
static func logInAsync(msalApplication: MSALPublicClientApplication, webViewParameters: MSALWebviewParameters) async throws -> MSALResult { return try await withCheckedThrowingContinuation { continuation in let interactiveParameters = MSALInteractiveTokenParameters(scopes: [], webviewParameters: webViewParameters) msalApplication.acquireToken(with: interactiveParameters) { result, error in if let error = error { continuation.resume(throwing: error) return } guard let result = result else { continuation.resume(throwing: NSError(domain: "B2CAuth", code: -1, userInfo: [NSLocalizedDescriptionKey: "Expected result but got nil"])) return } continuation.resume(returning: result) } } }
然后同样将getter方法替换成属性访问:
self.accountGlobalId = result.account.globalId self.accountUserName = result.account.userName
方案3:显式指定类型适配旧版本(不推荐)
如果你的项目依赖的MSAL版本确实还在使用getter方法,可能是自定义封装时类型推断出了问题,可以显式指定account的类型为MSALAccount:
guard let account = result.account as? MSALAccount else { preconditionFailure("Expected MSALAccount type") } self.accountGlobalId = account.getGlobalId() self.accountUserName = account.getUserName()
不过这个方案不推荐,因为MSAL的API风格已经向Swift属性迁移,老方法后续可能会被废弃。
备注:内容来源于stack exchange,提问作者lcj
相关产品推荐
相关产品推荐

