feat: 1 2
This commit is contained in:
parent
112912a6d3
commit
44c1ed4d60
@ -4,7 +4,7 @@ import Security
|
||||
/// 用于安全存储和检索敏感信息(如令牌)的 Keychain 帮助类
|
||||
public class KeychainHelper {
|
||||
// Keychain 键名
|
||||
private enum KeychainKey: String {
|
||||
private enum KeychainKey: String, CaseIterable {
|
||||
case accessToken = "com.memorywake.accessToken"
|
||||
case refreshToken = "com.memorywake.refreshToken"
|
||||
}
|
||||
@ -35,6 +35,38 @@ public class KeychainHelper {
|
||||
delete(for: .refreshToken)
|
||||
}
|
||||
|
||||
/// 清除所有存储的 Keychain 数据
|
||||
public static func clearAll() {
|
||||
// 清除所有已知的 keychain 项
|
||||
KeychainKey.allCases.forEach { key in
|
||||
delete(for: key)
|
||||
}
|
||||
|
||||
// 额外清理:删除所有通用密码项(作为安全措施)
|
||||
let query: [String: Any] = [
|
||||
kSecClass as String: kSecClassGenericPassword,
|
||||
kSecReturnAttributes as String: true,
|
||||
kSecMatchLimit as String: kSecMatchLimitAll
|
||||
]
|
||||
|
||||
var result: AnyObject?
|
||||
let status = SecItemCopyMatching(query as CFDictionary, &result)
|
||||
|
||||
if status == errSecSuccess, let items = result as? [[String: Any]] {
|
||||
for item in items {
|
||||
if let account = item[kSecAttrAccount as String] as? String,
|
||||
let service = item[kSecAttrService as String] as? String {
|
||||
let deleteQuery: [String: Any] = [
|
||||
kSecClass as String: kSecClassGenericPassword,
|
||||
kSecAttrAccount as String: account,
|
||||
kSecAttrService as String: service
|
||||
]
|
||||
SecItemDelete(deleteQuery as CFDictionary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - 私有方法
|
||||
|
||||
private static func save(_ string: String, for key: KeychainKey) -> Bool {
|
||||
|
||||
@ -2,6 +2,7 @@ import SwiftUI
|
||||
|
||||
@MainActor
|
||||
enum AppRoute: Hashable {
|
||||
case login
|
||||
case avatarBox
|
||||
case feedbackView
|
||||
case feedbackDetail(type: FeedbackView.FeedbackType)
|
||||
@ -12,6 +13,8 @@ enum AppRoute: Hashable {
|
||||
@ViewBuilder
|
||||
var view: some View {
|
||||
switch self {
|
||||
case .login:
|
||||
LoginView()
|
||||
case .avatarBox:
|
||||
AvatarBoxView()
|
||||
case .feedbackView:
|
||||
|
||||
@ -56,6 +56,7 @@ public struct AvatarPicker: View {
|
||||
SVGImage(svgName: "IP")
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.contentShape(Rectangle())
|
||||
.clipShape(RoundedRectangle(cornerRadius: 20))
|
||||
.overlay(
|
||||
RoundedRectangle(cornerRadius: 20)
|
||||
.stroke(style: StrokeStyle(
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user