密码扩展
由 AgileBits 的 one-password-app-extension 重写的 Swift 4 版本
密码扩展让您可以使用符合 PasswordExtension URL 方案的第三方密码管理器(例如 1Password、LastPass)访问用户的登录凭证,从他们的保险库中填写他们的登录凭证,向他们的保险库中添加凭证,以及更改任何给定 URL 的保险库中的密码。
示例
要运行示例项目,请先克隆仓库,然后在 Example 目录中运行 pod install
。
要求
- Swift 4
- iOS 8 及以上版本
安装
密码扩展通过以下方式提供:
CocoaPods
要安装它,只需将以下行添加到您的 Podfile
文件中
pod 'PasswordExtension'
Carthage
要安装它,只需将以下内容添加到您的 Cartfile
文件中
github "fahlout/PasswordExtension"
手动安装
将 'PasswordExtension/Classes' 目录中的所有 Swift 文件添加到您的项目中,您就可以开始使用了。
入门指南
为了让您的应用能够完全集成此扩展,需要将以下内容添加到您的应用的 Info.plist 文件中,以便允许密码管理器(如 1Password 和 LastPass)使用的 URL 方案来检查这些应用程序是否已安装在用户的设备上。
<key>LSApplicationQueriesSchemes</key>
<array>
<string>org-appextension-feature-password-management</string>
</array>
现在您可以使用此库让用户在密码管理器的保险库中填写凭据、保存凭据和更改密码。
只需为您的登录界面等添加一个带有适当图标(例如 1Password 图标)的按钮,并根据 PasswordExtension 中的 isAvailable 函数显示它。现在应该使用此按钮来调用所需的 PasswordExtension 功能。
注意:并非每个 PasswordExtensionLoginDetails 字段在所有密码管理器中都有支持。PEGeneratedPasswordOptions 也可能根据密码管理器有所支持或不支持。
示例代码
在用户保险库中查找凭证
// Using the provided classes
PasswordExtension.shared.findLoginDetails(for: "https://test.com", viewController: self, sender: nil) { (loginDetails, error) in
if let loginDetails = loginDetails {
print("Title: \(loginDetails.title ?? "")")
print("Username: \(loginDetails.username)")
print("Password: \(loginDetails.password ?? "")")
print("URL: \(loginDetails.urlString)")
} else if let error = error {
switch error.code {
case .extensionCancelledByUser:
print(error.localizedDescription)
default:
print("Error: \(error)")
}
}
}
// Using dictionaries
PasswordExtension.shared.findLoginDict(for: "https://test.com", viewController: self, sender: nil) { (loginDict, error) in
if let loginDict = loginDict {
print("Title: \(loginDict[PELogin.title.key()] as? String ?? "")")
print("Username: \(loginDict[PELogin.username.key()] as? String ?? "")")
print("Password: \(loginDict[PELogin.password.key()] as? String ?? "")")
print("URL: \(loginDict[PELogin.urlString.key()] as? String ?? "")")
} else if let error = error {
switch error.code {
case .extensionCancelledByUser:
print(error.localizedDescription)
default:
print("Error: \(error)")
}
}
}
在用户保险库中存储新凭证
// Using the provided classes
let fields = [
"firstname": "Tim",
"lastname": "Tester"
]
let loginDetails = PELoginDetails(urlString: "https://test.com", username: "tester1337", password: "test1234", title: "Test App", notes: "Saved with PasswordExtension", fields: fields)
let generatedPasswordOptions = PEGeneratedPasswordOptions(minLength: 5, maxLength: 45)
PasswordExtension.shared.storeLogin(for: loginDetails, generatedPasswordOptions: generatedPasswordOptions, viewController: self, sender: nil) { (loginDetails, error) in
if let loginDetails = loginDetails {
print("Title: \(loginDetails.title ?? "")")
print("Username: \(loginDetails.username)")
print("Password: \(loginDetails.password ?? "")")
print("URL: \(loginDetails.urlString)")
} else if let error = error {
print("Error: \(error)")
}
}
// Using dictionaries
let fields = [
"firstname": "Tim",
"lastname": "Tester"
]
let loginDetails: [String : Any] = [
PELogin.urlString.key(): "https://test.com",
PELogin.username.key(): "tester1337",
PELogin.password.key(): "test1234",
PELogin.title.key(): "Test App",
PELogin.fields.key(): fields
]
let generatedPasswordOptions: [String: Any] = [
PEGeneratedPassword.minLength.key(): 5,
PEGeneratedPassword.maxLength.key(): 45
]
PasswordExtension.shared.storeLogin(for: loginDetails, generatedPasswordOptions: generatedPasswordOptions, viewController: self, sender: nil) { (loginDict, error) in
if let loginDict = loginDict {
print("Title: \(loginDict[PELogin.title.key()] as? String ?? "")")
print("Username: \(loginDict[PELogin.username.key()] as? String ?? "")")
print("Password: \(loginDict[PELogin.password.key()] as? String ?? "")")
print("URL: \(loginDict[PELogin.urlString.key()] as? String ?? "")")
} else if let error = error {
print("Error: \(error)")
}
}
在用户保险库中更新凭证
// Using the provided classes
let loginDetails = PELoginDetails(urlString: "https://test.com", username: "tester1337", title: "Test App")
let generatedPasswordOptions = PEGeneratedPasswordOptions(minLength: 5, maxLength: 45)
PasswordExtension.shared.changePasswordForLogin(for: loginDetails, generatedPasswordOptions: generatedPasswordOptions, viewController: self, sender: nil) { (loginDetails, error) in
if let loginDetails = loginDetails {
print("Title: \(loginDetails.title ?? "")")
print("Username: \(loginDetails.username)")
print("Old Password: \(loginDetails.oldPassword ?? "")")
print("Password: \(loginDetails.password ?? "")")
print("URL: \(loginDetails.urlString)")
} else if let error = error {
print("Error: \(error)")
}
}
// Using dictionaries
let loginDetails: [String : Any] = [
PELogin.urlString.key(): "https://test.com",
PELogin.username.key(): "tester1337",
PELogin.title.key(): "Test App"
]
let generatedPasswordOptions: [String: Any] = [
PEGeneratedPassword.minLength.key(): 5,
PEGeneratedPassword.maxLength.key(): 45
]
PasswordExtension.shared.changePasswordForLogin(for: loginDetails, generatedPasswordOptions: generatedPasswordOptions, viewController: self, sender: nil) { (loginDict, error) in
if let loginDict = loginDict {
print("Title: \(loginDict[PELogin.title.key()] as? String ?? "")")
print("Username: \(loginDict[PELogin.username.key()] as? String ?? "")")
print("Old Password: \(loginDict[PELogin.oldPassword.key()] as? String ?? "")")
print("Password: \(loginDict[PELogin.password.key()] as? String ?? "")")
print("URL: \(loginDict[PELogin.urlString.key()] as? String ?? "")")
} else if let error = error {
print("Error: \(error)")
}
}
作者
Niklas Fahl (fahlout) - LinkedIn
许可
PasswordExtension遵循MIT许可。有关更多信息,请参阅LICENSE文件。