Merge branch 'feature-cookies'

This commit is contained in:
guozhigq
2024-12-07 22:27:04 +08:00
4 changed files with 183 additions and 110 deletions

View File

@ -1,13 +1,11 @@
// ignore_for_file: avoid_print
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:hive/hive.dart';
import 'package:pilipala/models/user/info.dart';
import 'package:pilipala/utils/id_utils.dart';
import '../utils/storage.dart';
import '../utils/utils.dart';
@ -39,18 +37,7 @@ class Request {
dio.interceptors.add(cookieManager);
final List<Cookie> cookie = await cookieManager.cookieJar
.loadForRequest(Uri.parse(HttpString.baseUrl));
final UserInfoData? userInfo = userInfoCache.get('userInfoCache');
if (userInfo != null && userInfo.mid != null) {
final List<Cookie> cookie2 = await cookieManager.cookieJar
.loadForRequest(Uri.parse(HttpString.tUrl));
if (cookie2.isEmpty) {
try {
await Request().get(HttpString.tUrl);
} catch (e) {
log("setCookie, ${e.toString()}");
}
}
}
final userInfo = userInfoCache.get('userInfoCache');
setOptionsHeaders(userInfo, userInfo != null && userInfo.mid != null);
String baseUrlType = 'default';
if (setting.get(SettingBoxKey.enableGATMode, defaultValue: false)) {
@ -69,10 +56,10 @@ class Request {
static Future<String> getCsrf() async {
List<Cookie> cookies = await cookieManager.cookieJar
.loadForRequest(Uri.parse(HttpString.baseUrl));
String token = '';
if (cookies.where((e) => e.name == 'bili_jct').isNotEmpty) {
token = cookies.firstWhere((e) => e.name == 'bili_jct').value;
}
String token = cookies
.firstWhere((e) => e.name == 'bili_jct',
orElse: () => Cookie('bili_jct', ''))
.value;
return token;
}

View File

@ -1,14 +1,19 @@
import 'dart:async';
import 'dart:io';
import 'package:cookie_jar/cookie_jar.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:encrypt/encrypt.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:get/get.dart';
import 'package:pilipala/http/constants.dart';
import 'package:pilipala/http/index.dart';
import 'package:pilipala/http/login.dart';
import 'package:gt3_flutter_plugin/gt3_flutter_plugin.dart';
import 'package:pilipala/models/login/index.dart';
import 'package:pilipala/utils/login.dart';
import 'package:pilipala/utils/utils.dart';
class LoginPageController extends GetxController {
final GlobalKey mobFormKey = GlobalKey<FormState>();
@ -341,4 +346,32 @@ class LoginPageController extends GetxController {
Get.back();
}
}
// cookie登录
Future loginInByCookie({
required String cookiesStr,
String domain = HttpString.baseUrl,
}) async {
final List<String> cookiesStrList = cookiesStr.split('; ');
final List<Cookie> cookiesList = cookiesStrList.map((cookie) {
final cookieArr = cookie.split('=');
return Cookie(cookieArr[0], cookieArr[1]);
}).toList();
final String cookiePath = await Utils.getCookiePath();
final cookieJar = PersistCookieJar(
ignoreExpires: true,
storage: FileStorage(cookiePath),
);
CookieManager cookieManager = CookieManager(cookieJar);
Request.cookieManager = cookieManager;
await Request.cookieManager.cookieJar
.saveFromResponse(Uri.parse(HttpString.baseUrl), cookiesList);
try {
Request.dio.options.headers['cookie'] = cookiesStr;
} catch (err) {
debugPrint(err.toString());
}
LoginUtils.confirmLogin('', null);
}
}

View File

@ -14,6 +14,144 @@ class LoginPage extends StatefulWidget {
class _LoginPageState extends State<LoginPage> {
final LoginPageController _loginPageCtr = Get.put(LoginPageController());
// 浏览器登录
void loginInByWeb() {
Get.offNamed(
'/webview',
parameters: {
'url': 'https://passport.bilibili.com/h5-app/passport/login',
'type': 'login',
'pageTitle': '登录bilibili',
},
);
}
// 二维码方式登录
void loginInByWebQrcode() {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, StateSetter setState) {
return AlertDialog(
title: Row(
children: [
const Text('扫码登录'),
IconButton(
onPressed: () {
setState(() {});
},
icon: const Icon(Icons.refresh),
),
],
),
contentPadding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
content: AspectRatio(
aspectRatio: 1,
child: Container(
width: 200,
padding: const EdgeInsets.all(12),
child: FutureBuilder(
future: _loginPageCtr.getWebQrcode(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.data == null) {
return const SizedBox();
}
Map data = snapshot.data as Map;
return QrImageView(
data: data['data']['url'],
backgroundColor: Colors.white,
);
} else {
return const Center(
child: SizedBox(
width: 40,
height: 40,
child: CircularProgressIndicator(),
),
);
}
},
),
),
),
actions: [
TextButton(
onPressed: () {},
child: Obx(() {
return Text(
'有效期: ${_loginPageCtr.validSeconds.value}s',
style: Theme.of(context).textTheme.titleMedium,
);
}),
),
TextButton(
onPressed: () {},
child: Text(
'检查登录状态',
style: TextStyle(
fontSize: Theme.of(context).textTheme.titleMedium!.fontSize,
),
),
)
],
);
});
},
).then((value) {
_loginPageCtr.validTimer!.cancel();
});
}
// cookie登录
// cookie登录
void loginInByCookie() async {
var cookies = '';
final outline = Theme.of(context).colorScheme.outline;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('Cookie登录'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text('请将主站cookie粘贴到下方输入框中点击「确认」即可完成登录。记得清空粘贴板'),
const SizedBox(height: 12),
TextField(
minLines: 1,
maxLines: 3,
decoration: InputDecoration(
labelText: 'cookie',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(6.0),
),
),
onChanged: (e) => cookies = e,
),
],
),
actions: [
TextButton(
onPressed: Navigator.of(context).pop,
child: Text('取消', style: TextStyle(color: outline))),
TextButton(
onPressed: () async {
if (cookies.isEmpty) {
return;
}
await _loginPageCtr.loginInByCookie(cookiesStr: cookies);
if (context.mounted) {
Navigator.of(context).pop();
}
},
child: const Text('确认'))
],
);
},
);
}
@override
void dispose() {
_loginPageCtr.validTimer?.cancel();
@ -43,100 +181,17 @@ class _LoginPageState extends State<LoginPage> {
actions: [
IconButton(
tooltip: '浏览器打开',
onPressed: () {
Get.offNamed(
'/webview',
parameters: {
'url': 'https://passport.bilibili.com/h5-app/passport/login',
'type': 'login',
'pageTitle': '登录bilibili',
},
);
},
onPressed: loginInByWeb,
icon: const Icon(Icons.language, size: 20),
),
IconButton(
tooltip: 'cookie登录',
onPressed: loginInByCookie,
icon: const Icon(Icons.cookie_outlined, size: 20),
),
IconButton(
tooltip: '二维码登录',
onPressed: () {
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, StateSetter setState) {
return AlertDialog(
title: Row(
children: [
const Text('扫码登录'),
IconButton(
onPressed: () {
setState(() {});
},
icon: const Icon(Icons.refresh),
),
],
),
contentPadding: const EdgeInsets.fromLTRB(0, 0, 0, 4),
content: AspectRatio(
aspectRatio: 1,
child: Container(
width: 200,
padding: const EdgeInsets.all(12),
child: FutureBuilder(
future: _loginPageCtr.getWebQrcode(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.done) {
if (snapshot.data == null) {
return const SizedBox();
}
Map data = snapshot.data as Map;
return QrImageView(
data: data['data']['url'],
backgroundColor: Colors.white,
);
} else {
return const Center(
child: SizedBox(
width: 40,
height: 40,
child: CircularProgressIndicator(),
),
);
}
},
),
),
),
actions: [
TextButton(
onPressed: () {},
child: Obx(() {
return Text(
'有效期: ${_loginPageCtr.validSeconds.value}s',
style: Theme.of(context).textTheme.titleMedium,
);
}),
),
TextButton(
onPressed: () {},
child: Text(
'检查登录状态',
style: TextStyle(
fontSize: Theme.of(context)
.textTheme
.titleMedium!
.fontSize,
),
),
)
],
);
});
},
).then((value) {
_loginPageCtr.validTimer!.cancel();
});
},
onPressed: loginInByWebQrcode,
icon: const Icon(Icons.qr_code, size: 20),
),
const SizedBox(width: 22),

View File

@ -12,7 +12,6 @@ import 'package:pilipala/http/user.dart';
import 'package:pilipala/pages/dynamics/index.dart';
import 'package:pilipala/pages/home/index.dart';
import 'package:pilipala/pages/mine/index.dart';
import 'package:pilipala/utils/cookie.dart';
import 'package:pilipala/utils/global_data_cache.dart';
import 'package:pilipala/utils/storage.dart';
import 'package:uuid/uuid.dart';
@ -68,7 +67,6 @@ class LoginUtils {
content = '${content + url}; \n';
}
try {
await SetCookie.onSet();
final result = await UserHttp.userInfo();
if (result['status'] && result['data'].isLogin) {
SmartDialog.showToast('登录成功');