Flutter中SharedPreferences存用户ID的正确性、安全及GetX存储问题
关于登录系统自动登录与数据存储的疑问
问题背景
我正在开发登录系统,已在main.dart的import语句后、void main前声明全局变量uID和nameOfUser。目前用SharedPreferences存储用户信息,通过检查uID是否已保存实现用户自动登录,无需重复登录。想确认:
- 该方式是否正确?
- 是否存在被破解的风险?
- 能否在GetX状态管理器中实现类似
SharedPreferences的数据存储功能?
附上相关代码:
void auth() async { final SharedPreferences prefs = await SharedPreferences.getInstance(); try { var authResponse = await _dio.post( '/app_api/login.php', data: { "mobile": _phoneController.text, "pass": _passController.text, }, options: Options( headers: { "Content-Type": "application/json", }, ), ); var responseData = authResponse.data; if (responseData['status'] == true) { setState(() { uID = responseData['UID']; nameOfUser = responseData['Name']; }); await prefs.setString('uID', '${responseData['UID']}'); await prefs.setString('nameOfUser', '${responseData['Name']}'); Get.offAll(() => const HomeScreen()); } else { _passController.clear(); Get.snackbar( 'Login Failed', 'Please enter correct mobile number and password', backgroundColor: Colors.red, colorText: Colors.white, ); } } catch (e) { Get.snackbar( 'Error', 'An error occurred during login: $e', backgroundColor: Colors.red, colorText: Colors.white, ); } }
解答
1. 当前自动登录方式是否正确?
从功能实现角度,这个方式可行,但有几个优化点:
- 全局变量
uID和nameOfUser在APP重启后会丢失初始值,必须在APP启动时从SharedPreferences读取并赋值,否则启动后全局变量会是默认值,直到登录操作触发才更新。 - 仅靠
uID做自动登录逻辑存在局限性:如果后端有用户会话过期机制,本地存储的uID无法验证用户是否仍处于有效登录状态。建议同时存储后端返回的登录令牌(Token),自动登录时携带Token请求后端验证有效性,再决定是否进入首页。
2. 是否存在被破解的风险?
是的,存在明确风险:
SharedPreferences是明文存储在设备沙盒目录中,root过的设备可直接查看数据。如果后端仅靠uID验证用户身份,攻击者获取uID后可能伪造请求冒用身份。- 优化方案:优先存储后端签发的JWT令牌或会话Token;如果必须存储
uID,可对其进行AES加密后再存储,提升破解成本。
3. 能否在GetX中实现类似SharedPreferences的数据存储功能?
可以实现,两种常见方案:
方案一:在GetX Controller中封装SharedPreferences
将存储逻辑封装到GetX控制器中,结合响应式状态管理实现数据同步:
class AuthController extends GetxController { final RxString uID = ''.obs; final RxString nameOfUser = ''.obs; late SharedPreferences prefs; @override void onInit() async { super.onInit(); prefs = await SharedPreferences.getInstance(); // 初始化时读取本地数据 uID.value = prefs.getString('uID') ?? ''; nameOfUser.value = prefs.getString('nameOfUser') ?? ''; } Future<void> auth(String mobile, String pass) async { try { var authResponse = await _dio.post( '/app_api/login.php', data: {"mobile": mobile, "pass": pass}, options: Options(headers: {"Content-Type": "application/json"}), ); var responseData = authResponse.data; if (responseData['status'] == true) { uID.value = responseData['UID']; nameOfUser.value = responseData['Name']; await prefs.setString('uID', uID.value); await prefs.setString('nameOfUser', nameOfUser.value); Get.offAll(() => const HomeScreen()); } else { Get.snackbar( '登录失败', '请输入正确的手机号和密码', backgroundColor: Colors.red, colorText: Colors.white, ); } } catch (e) { Get.snackbar( '错误', '登录过程中发生错误: $e', backgroundColor: Colors.red, colorText: Colors.white, ); } } }
方案二:使用GetX官方的GetStorage插件
get_storage是轻量级本地存储方案,API更简洁且支持响应式:
- 添加依赖到
pubspec.yaml:
dependencies: get_storage: ^2.1.1
- 在
main.dart初始化:
void main() async { await GetStorage.init(); runApp(const MyApp()); }
- 在GetX控制器中使用:
class AuthController extends GetxController { final RxString uID = ''.obs; final RxString nameOfUser = ''.obs; final storage = GetStorage(); @override void onInit() { super.onInit(); // 读取存储数据 uID.value = storage.read('uID') ?? ''; nameOfUser.value = storage.read('nameOfUser') ?? ''; } Future<void> auth(String mobile, String pass) async { try { var authResponse = await _dio.post( '/app_api/login.php', data: {"mobile": mobile, "pass": pass}, options: Options(headers: {"Content-Type": "application/json"}), ); var responseData = authResponse.data; if (responseData['status'] == true) { uID.value = responseData['UID']; nameOfUser.value = responseData['Name']; // 存储数据 storage.write('uID', uID.value); storage.write('nameOfUser', nameOfUser.value); Get.offAll(() => const HomeScreen()); } else { Get.snackbar( '登录失败', '请输入正确的手机号和密码', backgroundColor: Colors.red, colorText: Colors.white, ); } } catch (e) { Get.snackbar( '错误', '登录过程中发生错误: $e', backgroundColor: Colors.red, colorText: Colors.white, ); } } }
内容的提问来源于stack exchange,提问作者Ram Gupta
相关产品推荐
相关产品推荐

