如何用SharedPreferences存储Token?登录后Token未保存引发401问题
问题分析与修复方案
核心问题
- 登录成功后未保存Token:你的登录方法在拿到200响应并解析User后,完全没有调用
UtilSharedPreferences.setToken()将接口返回的Token存入本地,这直接导致后续API请求时无法获取有效Token,返回401。 - 登录请求冗余携带旧Token:登录接口本身是用来获取新Token的,通常不需要在请求头中携带
Authorization,但你当前代码里却带上了之前存储的旧Token(初始为空),虽然接口返回200,但这不符合接口设计逻辑。
修复步骤
1. 移除登录请求的冗余请求头
登录接口不需要携带认证信息,直接删除Authorization头:
var response = await http.post( Uri.parse('http://dev.api.app.masoemuniversity.ac.id/v1/login_mhs'), // 移除多余的Authorization头 body: body, );
2. 登录成功后添加Token保存逻辑
解析响应数据后,提取Token并调用工具类保存到SharedPreferences:
if (response.statusCode == 200) { var responseData = jsonDecode(response.body); // 注意:这里的字段名要和接口返回的Token字段完全一致,比如接口返回的是access_token就用这个 String newToken = responseData['access_token']; // 保存Token到本地 await UtilSharedPreferences.setToken(newToken); // 返回解析后的User对象 return User.fromJson(responseData); } else { return null; }
3. 优化工具类的setToken方法(可选)
给setToken添加返回值,方便验证是否保存成功:
class UtilSharedPreferences { static Future<String> getToken() async { SharedPreferences _prefs = await SharedPreferences.getInstance(); return _prefs.getString('access_token') ?? ''; } static Future<bool> setToken(String value) async { SharedPreferences _prefs = await SharedPreferences.getInstance(); return _prefs.setString('access_token', value); } }
调用时可以打印验证:
bool saveSuccess = await UtilSharedPreferences.setToken(newToken); print('Token保存状态:$saveSuccess');
完整修改后的登录代码
Future<User?> login(String nim, String password) async { try { var body = { 'username': nim, 'password': password, }; var response = await http.post( Uri.parse('http://dev.api.app.masoemuniversity.ac.id/v1/login_mhs'), body: body, ); print(response.statusCode); print(response.body); if (response.statusCode == 200) { var responseData = jsonDecode(response.body); String newToken = responseData['access_token']; await UtilSharedPreferences.setToken(newToken); return User.fromJson(responseData); } else { return null; } } catch (e) { print(e); return null; } }
内容的提问来源于stack exchange,提问作者sharon
相关产品推荐
相关产品推荐

