lnu_elytra/method/
login.rs1use std::time::{SystemTime, UNIX_EPOCH};
2
3use serde::Serialize;
4
5use crate::{
6 Client,
7 error::{Error, R},
8 utils::{
9 EncPwd, PublicKey, ToHtml, UseInputValue,
10 macros::{debug, error, info, trace},
11 },
12};
13
14impl Client {
15 pub async fn login(&mut self, username: &str, password: &str) -> R {
17 info!("正在登录...");
18
19 trace!("加载登录页");
20
21 let doc = self.get(&Client::LOGIN_URL).send().await?._doc().await?;
22
23 trace!("解析登录页,获取csrftoken");
24
25 let csrftoken = doc.use_val(&Client::S_CSRFTOKEN)?;
26
27 debug!("csrftoken: {}", csrftoken);
28
29 use std::borrow::Cow;
30 let mm = if let Ok(mmsfjm) = doc.use_val(&Client::S_INPUT_MMSFJM)
31 && mmsfjm == "0"
32 {
33 trace!("mmsfjm == '0'");
34 Cow::Borrowed(password)
35 } else {
36 trace!("获取公钥,使用公钥加密密码");
37 Cow::Owned(
38 self.get(&Client::PUBLIC_KEY_URL)
39 .send()
40 .await?
41 .json::<PublicKey>()
42 .await?
43 .into_rsa_key()?
44 .enc_pwd(password)?,
45 )
46 };
47
48 #[derive(Serialize, Debug)]
49 struct LoginData<'a> {
50 csrftoken: &'a str,
51 yhm: &'a str,
52 mm: &'a str,
53 language: &'a str,
54 }
55
56 let login_data = LoginData {
57 csrftoken: csrftoken,
58 yhm: username,
59 mm: &mm,
60 language: "zh_CN",
61 };
62
63 debug!("登录数据: {:?}", login_data);
64
65 let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
66
67 trace!("发送登录请求");
68
69 let doc = self
70 .post(&Client::LOGIN_URL)
71 .query(&[("time", timestamp)])
72 .form(&login_data)
73 .send()
74 .await?
75 ._doc()
76 .await?;
77
78 let u = doc.use_val(&Client::S_SESSION_USER_KEY).or_else(|_| {
79 error!("登录失败,未找到 SESSION_USER_KEY");
80 return Err(Error::LoginFailed);
81 })?;
82
83 debug!("SESSION_USER_KEY: {}", u);
84
85 if u != username {
86 error!("登录失败,SESSION_USER_KEY 不匹配");
87 return Err(Error::LoginFailed);
88 }
89
90 info!("登录成功");
91
92 Ok(())
93 }
94}