Flutter结合MongoDB获取当前登录用户及帖子权限配置问题
问题解决指南
一、获取当前登录用户的用户名
你已经把token存在SharedPreferences里,推荐同时缓存用户核心信息(比如username、id),这样无需频繁解析token,更高效。
1. 封装SharedPreferences操作工具类
创建AuthService类统一处理用户信息的存储与读取:
import 'package:shared_preferences/shared_preferences.dart'; class AuthService { // 存储用户信息 static Future<void> saveUserInfo(String userId, String username, String token) async { final prefs = await SharedPreferences.getInstance(); await prefs.setString('user_id', userId); await prefs.setString('username', username); await prefs.setString('token', token); } // 获取当前用户名 static Future<String?> getCurrentUsername() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('username'); } // 获取当前用户ID static Future<String?> getCurrentUserId() async { final prefs = await SharedPreferences.getInstance(); return prefs.getString('user_id'); } // 清除用户信息(退出登录) static Future<void> clearUserInfo() async { final prefs = await SharedPreferences.getInstance(); await prefs.remove('user_id'); await prefs.remove('username'); await prefs.remove('token'); } }
2. 登录成功时存储用户信息
当从后端拿到User对象后,调用工具类存储信息:
// 假设登录接口返回User对象 User loggedInUser = User.fromJson(responseData); await AuthService.saveUserInfo( loggedInUser.id!, loggedInUser.username, loggedInUser.token, );
3. 任意场景获取用户名
在需要显示用户名的页面,直接调用方法获取:
String? username = await AuthService.getCurrentUsername(); if (username != null) { // 例如显示:Text('欢迎, $username') }
如果不想缓存,也可以解析JWT token获取用户名(需添加jwt_decoder依赖):
// pubspec.yaml添加依赖:jwt_decoder: ^2.0.1 import 'package:jwt_decoder/jwt_decoder.dart'; String? getUsernameFromToken(String token) { Map<String, dynamic> decodedToken = JwtDecoder.decode(token); return decodedToken['username']; // 字段名需和后端token payload一致 }
二、实现用户仅能操作自己的帖子
需从前端UI控制和后端权限校验两方面入手,避免前端限制被绕过。
1. 前端UI控制:仅显示自己帖子的操作按钮
获取当前用户ID,对比帖子的author.id,匹配时才显示编辑/删除按钮:
// 获取当前用户ID String? currentUserId = await AuthService.getCurrentUserId(); // 遍历帖子列表构建UI ListView.builder( itemCount: posts.length, itemBuilder: (context, index) { Post post = posts[index]; return ListTile( title: Text(post.text), subtitle: Text(post.author.username), trailing: currentUserId == post.author.id ? Row( mainAxisSize: MainAxisSize.min, children: [ IconButton(icon: const Icon(Icons.edit), onPressed: () => editPost(post)), IconButton(icon: const Icon(Icons.delete), onPressed: () => deletePost(post)), ], ) : null, ); }, );
2. 后端MongoDB权限校验(核心)
前端控制只是表面,必须在后端做校验防止恶意请求:
查询个人帖子:只返回当前用户发布的内容(以Node.js + Mongoose为例)
// 假设已通过中间件解析token获取当前用户ID const userId = req.user.id; // 查询当前用户的所有帖子 const userPosts = await Post.find({ 'author._id': userId });修改/删除帖子:先验证帖子归属
// 修改帖子接口 app.put('/posts/:id', async (req, res) => { const postId = req.params.id; const userId = req.user.id; // 校验帖子存在且归属当前用户 const post = await Post.findById(postId); if (!post) return res.status(404).json({ message: '帖子不存在' }); if (post.author._id.toString() !== userId) { return res.status(403).json({ message: '无权限操作此帖子' }); } // 执行修改 const updatedPost = await Post.findByIdAndUpdate(postId, req.body, { new: true }); res.json(updatedPost); }); // 删除帖子接口同理 app.delete('/posts/:id', async (req, res) => { const postId = req.params.id; const userId = req.user.id; const post = await Post.findById(postId); if (!post) return res.status(404).json({ message: '帖子不存在' }); if (post.author._id.toString() !== userId) { return res.status(403).json({ message: '无权限操作此帖子' }); } await Post.findByIdAndDelete(postId); res.json({ message: '删除成功' }); });
3. 发布帖子时关联用户ID
发布帖子时,必须将当前用户ID作为author字段存入MongoDB:
// Flutter端发布帖子请求 Future<void> createPost(String text) async { String? token = await AuthService.getToken(); String? userId = await AuthService.getCurrentUserId(); final response = await http.post( Uri.parse('你的后端帖子接口地址'), headers: { 'Authorization': 'Bearer $token', 'Content-Type': 'application/json', }, body: jsonEncode({ 'text': text, 'author': userId, // 或传入完整用户信息,依后端要求而定 // 其他字段:images、videos等 }), ); }
内容的提问来源于stack exchange,提问作者YAZAN FARRAH
相关产品推荐
相关产品推荐

