Hãy bắt đầu từ phần khó chịu, vì mọi thứ còn lại đều suy ra từ đó. Bất kỳ chuỗi nào được biên dịch vào ứng dụng đều là công khai. Không phải “khó tìm” — mà là công khai. Một file APK là file zip; chạy strings trên binary đã giải nén chỉ mất vài giây. Giá trị --dart-define , hằng số, tên đã làm rối, khối base64: tất cả đều lấy lại được bởi bất kỳ ai đủ quyết tâm tải ứng dụng của bạn về một lần. Đây không phải điểm yếu của Flutter. Điều đó đúng với mọi ứng dụng phía client trên mọi nền tảng. Thứ nó thay đổi là chỗ bạn kẻ ranh giới giữa “ứng dụng biết điều này” và “ứng dụng có thể hỏi xin điều này”. Ranh giới Loại bí mật Thuộc về đâu Khoá API bên thứ ba gắn với hoá đơn Chỉ ở máy chủ. Ứng dụng gọi backend của bạn, backend gọi họ Khoá công khai (Stripe publishable, cấu hình Firebase, khoá Maps) Nằm trong ứng dụng — chúng được thiết kế cho việc đó và được giới hạn phía máy chủ Token phiên của người dùng Kho an toàn trên thiết bị, vòng đời ngắn, làm mới ...
Refresh tokens in SharedPreferences are a security incident waiting to happen. Bài này chuyển quan sát đó thành một mô hình nhỏ để bạn có thể kiểm thử, đo lường và giữ cho code dễ bảo trì khi app lớn lên. Vấn đề cốt lõi Keychain/Keystore, biometric gates, and token rotation. Câu hỏi hữu ích không phải API hay pattern có đẹp riêng lẻ hay không, mà là state nằm ở đâu, boundary nào chịu trách nhiệm khi lỗi xảy ra, và người dùng phục hồi thế nào khi happy path biến mất. Mô hình thực tế Use platform keystores and optional biometric unlock for sensitive vaults. Hãy bắt đầu bằng một owner rõ ràng cho behavior. Widget chỉ nên render và phát intent; IO, persistence, permission và retry nên nằm sau một interface nhỏ. Nhờ vậy bạn có seam để fake trong test và một chỗ ghi lại các dữ kiện cần theo dõi ở production. Trong app Flutter, boundary thường có dạng: Widget phát intent như load, submit, refresh hoặc retry. Controller hoặc use case validate intent rồi gọi boundary. Boundary trả về...