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 trace!("获取公钥,使用公钥加密密码");
30
31 let mm = self
32 .get(&Client::PUBLIC_KEY_URL)
33 .send()
34 .await?
35 .json::<PublicKey>()
36 .await?
37 .into_rsa_key()?
38 .enc_pwd(password)?;
39
40 #[derive(Serialize, Debug)]
41 struct LoginData<'a> {
42 csrftoken: &'a str,
43 yhm: &'a str,
44 mm: &'a str,
45 language: &'a str,
46 }
47
48 let login_data = LoginData {
49 csrftoken: csrftoken,
50 yhm: username,
51 mm: &mm,
52 language: "zh_CN",
53 };
54
55 debug!("登录数据: {:?}", login_data);
56
57 let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis();
58
59 trace!("发送登录请求");
60
61 let login_res = self
62 .post(&Client::LOGIN_URL)
63 .query(&[("time", timestamp)])
64 .form(&login_data)
65 .send()
66 .await?;
67
68 let doc = login_res.doc().await?;
69
70 let u = doc.use_val(&Client::S_SESSION_USER_KEY)?;
71
72 debug!("SESSION_USER_KEY: {}", u);
73
74 if u != username {
75 error!("登录失败,用户名不匹配");
76 return Err(Error::LoginFailed);
77 }
78
79 info!("登录成功");
80
81 Ok(())
82 }
83}