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

Flutter登录后会话存储、登录校验及自定义仪表盘实现咨询

解决方案与实现思路

一、登录后获取用户个性化数据

1. 后端接口调整

PHP登录验证接口在确认邮箱密码正确后,除返回登录成功状态,还需返回用户的个性化数据(如用户名、主题偏好、常用设置等)。示例PHP代码:

<?php
// 验证邮箱密码逻辑(略)
if ($valid) {
    // 从MySQL查询用户个性化数据
    $userData = $db->query("SELECT username, theme, preferred_lang FROM users WHERE email = '$email'")->fetch_assoc();
    // 返回JSON响应
    echo json_encode([
        'status' => 'success',
        'user' => $userData
    ]);
} else {
    echo json_encode(['status' => 'error', 'msg' => '登录失败']);
}
?>

2. Flutter端处理与本地存储

登录请求成功后,解析后端返回的用户数据,用shared_preferences(轻量键值存储)或Hive(本地数据库)保存到设备本地,仪表盘页面从本地读取数据渲染个性化内容。示例Flutter代码:

import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart';
import 'dart:convert';

// 登录请求方法
Future<void> login(String email, String password, BuildContext context) async {
  final response = await http.post(
    Uri.parse('你的PHP接口地址'),
    body: {'email': email, 'password': password},
  );
  if (response.statusCode == 200) {
    final data = jsonDecode(response.body);
    if (data['status'] == 'success') {
      // 保存用户数据到本地
      final prefs = await SharedPreferences.getInstance();
      await prefs.setString('username', data['user']['username']);
      await prefs.setString('theme', data['user']['theme']);
      // 跳转到仪表盘
      Navigator.pushReplacementNamed(context, '/dashboard');
    }
  }
}

// 仪表盘页面读取数据
class DashboardPage extends StatefulWidget {
  @override
  State<DashboardPage> createState() => _DashboardPageState();
}

class _DashboardPageState extends State<DashboardPage> {
  String? username;
  String? theme;

  @override
  void initState() {
    super.initState();
    _loadUserData();
  }

  Future<void> _loadUserData() async {
    final prefs = await SharedPreferences.getInstance();
    setState(() {
      username = prefs.getString('username') ?? '默认用户';
      theme = prefs.getString('theme') ?? 'light';
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('欢迎,$username')),
      body: Center(child: Text('当前主题:$theme')),
    );
  }
}

二、会话校验与登录状态维持

1. 基于JWT的无状态会话实现

后端(PHP)生成JWT

使用firebase/php-jwt库生成包含用户ID、过期时间的JWT,登录成功后随用户数据一起返回。示例代码:

<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;

$secretKey = '你的自定义密钥(需保密)';
$payload = [
  'user_id' => $userData['id'],
  'exp' => time() + 3600 // 令牌1小时后过期
];
$jwt = JWT::encode($payload, $secretKey, 'HS256');

// 返回响应时带上JWT
echo json_encode([
  'status' => 'success',
  'user' => $userData,
  'token' => $jwt
]);
?>

Flutter端存储JWT并携带请求

登录时保存JWT到本地,后续所有需要权限的接口请求都在请求头里带上Authorization: Bearer {token}。同时实现路由守卫,确保未登录用户无法进入仪表盘:

// 登录时保存JWT
await prefs.setString('auth_token', data['token']);

// 请求权限接口时携带JWT
Future<void> fetchUserSettings() async {
  final prefs = await SharedPreferences.getInstance();
  final token = prefs.getString('auth_token');
  final response = await http.get(
    Uri.parse('需要权限的用户设置接口'),
    headers: {'Authorization': 'Bearer $token'},
  );
  // 处理接口响应(略)
}

// 路由守卫(在MaterialApp的onGenerateRoute中实现)
Route<dynamic>? generateRoute(RouteSettings settings) async {
  switch (settings.name) {
    case '/dashboard':
      final prefs = await SharedPreferences.getInstance();
      final token = prefs.getString('auth_token');
      if (token != null) {
        return MaterialPageRoute(builder: (_) => DashboardPage());
      } else {
        return MaterialPageRoute(builder: (_) => LoginPage());
      }
    // 其他路由逻辑(略)
    default:
      return MaterialPageRoute(builder: (_) => LoginPage());
  }
}

2. 后端JWT校验

PHP接口收到请求时,校验请求头中的JWT有效性,无效则返回未授权状态:

<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;

$secretKey = '你的自定义密钥';
$token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
if (str_starts_with($token, 'Bearer ')) {
  $token = substr($token, 7);
  try {
    $decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
    // 校验通过,获取用户ID处理业务
    $userId = $decoded->user_id;
  } catch (Exception $e) {
    http_response_code(401);
    echo json_encode(['status' => 'error', 'msg' => '未授权']);
    exit;
  }
} else {
  http_response_code(401);
  echo json_encode(['status' => 'error', 'msg' => '缺少授权令牌']);
  exit;
}
// 后续业务逻辑(略)
?>

参考资源要点

  • Flutter本地存储:shared_preferences适合轻量键值对存储,Hive支持复杂对象或大量数据存储,可查看Flutter官方文档中本地存储章节的核心用法。
  • JWT实现:PHP端依赖firebase/php-jwt库,核心是生成包含用户标识和过期时间的令牌;Flutter端负责令牌的存储、携带与过期检测。
  • 路由守卫:通过onGenerateRoute或go_router等路由包实现页面权限控制,拦截未登录用户访问受保护页面。

内容的提问来源于stack exchange,提问作者Shawn Mulligan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:34:56