我是靠谱客的博主 激昂电话,最近开发中收集的这篇文章主要介绍Flutter引入图形验证码,并保留SessionId问题描述解决,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Hello,I’m Shendi

百度搜索不到相关内容,官网也没有相关内容,问群里大佬得到答案,这里记录一下



问题描述

登陆时需要使用到后端提供的图形验证码,后端通过 Session 保存验证码信息

Flutter 中提供了加载网络图片的方式,但没办法保存 SessionId,于是改变思路,用 dio 读取图片数据流,拿到 SessionId,再渲染到组件


解决

关于 dio 获取 SessionId 的方法可以参考这篇文章
https://shendi.blog.csdn.net/article/details/122510279

获取图片字节流的代码如下

LoginData {
	var cookie;
	Map<String, String> session = {
		"name" : "",
		"value" : "",
		"domain" : "shendi"
	};
}
var loginData = LoginData();

Future<Uint8List> getVCCode() async {
	dio.options.followRedirects = false;
    dio.options.validateStatus = (status) {
      return status! < 500;
    };
    // 这里是设置Cookie,Cookie中包含SessionId
    if (loginData.cookie != null) dio.options.headers["Cookie"] = loginData.cookie;

	Response resp = await dio.get(
      "验证码地址" + Random().nextInt(100).toString(),
      options: Options(responseType: ResponseType.stream).timeout(const Duration(seconds: 3)));

	// 如果有 set-cookie 则获取保存
	if (resp.headers["set-cookie"] != null) {
		var cookie = resp.headers["set-cookie"].toString();
		cookie = cookie.substring(1, cookie.length - 1);
		loginData.cookie = cookie;
		
		// 设置session结构, 目前COOKIE内容为 JSESSIONID=xxx; Path=/; HttpOnly
		int len = cookie.indexOf('=');
		loginData.session["name"] = cookie.substring(0, len);
		cookie = cookie.substring(len);
		len = cookie.indexOf(';');
		loginData.session["value"] = cookie.substring(1, len);
		cookie = cookie.substring(len+1);
    }

	final stream = await (resp.data as ResponseBody).stream.toList();
	final result = BytesBuilder();
	for (Uint8List subList in stream) {
		result.add(subList);
	}

	return result.takeBytes();
}

因为使用的 dio,获取到的返回是 Future<Uint8List>,我们需要拿到 Uint8List,需要使用到状态管理,可参考官网文档
https://book.flutterchina.club/chapter2/state_manage.html


这里我直接将我的登陆页代码贴上,供参考

/// 登陆页面
class Login extends StatelessWidget {
  const Login({Key? key}) : super(key: key);

  final appTitle = "登录 - Shendi";

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      title: appTitle,
      home: const LoginPage(),
    );
  }
}

/// 登录页面
class LoginPage extends StatefulWidget {
  const LoginPage({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return LoginPageState();
  }

}

/// 登陆状态
class LoginPageState extends State<LoginPage> {
  var account = TextEditingController();
  var pwd = TextEditingController();
  var code = TextEditingController();

  var codeImg;

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

    // 初始化验证码
    flushVCCode();

    eventBus.on<VCCodeFlush>().listen((event) {
      flushVCCode();
    });
  }

  /// 刷新验证码
  flushVCCode() async {
    var data = await http.getVCCode();
    setState(() {
      codeImg = Image.memory(data);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          centerTitle: true,
          title: Text(const Login().appTitle),
        ),
        body: Padding(
        padding: const EdgeInsets.all(20),
        child: ListView(
          children: [
            TextFormField(
              controller: account,
              decoration: const InputDecoration(
                  labelText: "账号",
                  hintText: "请输入账号"
              ),
            ),
            TextField(
              controller: pwd,
              decoration: const InputDecoration(
                  labelText: "密码",
                  hintText: "请输入密码"
              ),
            ),
            Row(
              children: [
                Expanded(child: TextFormField(
                  controller: code,
                  decoration: const InputDecoration(
                      labelText: "验证码",
                      hintText: "请输入验证码"
                  ),
                )),
                GestureDetector(
                  child: codeImg ?? Container(),
                  onTap: () {
                    flushVCCode();
                  },
                )
              ],
            ),
            Padding(
              padding: const EdgeInsets.fromLTRB(0, 22, 0, 0),
              child: ElevatedButton(
                  onPressed: () async {
                    var msg;
                    if (pwd.text == "") msg = "请填写密码!";
                    if (account.text == "") msg = "请填写账号!";
                    if (code.text == "") msg = "请输入验证码!";

                    if (msg != null) {
                      Fluttertoast.showToast(
                          msg: msg,
                          toastLength: Toast.LENGTH_SHORT,
                          gravity: ToastGravity.TOP,
                          timeInSecForIosWeb: 1,
                          fontSize: 16.0
                      );
                      return;
                    }

                    bool isLogin = await http.login(account.text, pwd.text, code.text);
                    if (isLogin) {
                      // 登录成功,进入主页面
                      runApp(const RoomList());
                    }
                  },
                  child: const Text("登录")
              ),
            )
          ],
        ),
      )
    );
  }

}

END

最后

以上就是激昂电话为你收集整理的Flutter引入图形验证码,并保留SessionId问题描述解决的全部内容,希望文章能够帮你解决Flutter引入图形验证码,并保留SessionId问题描述解决所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(47)

评论列表共有 0 条评论

立即
投稿
返回
顶部