You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:45:39