/[LeafOK_CVS]/fenglin/bbs/user_service_login.php
ViewVC logotype

Annotation of /fenglin/bbs/user_service_login.php

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.4 - (hide annotations)
Sun Sep 28 12:28:47 2025 UTC (5 months, 2 weeks ago) by sysadm
Branch: MAIN
Changes since 1.3: +8 -4 lines
Optimize account lock policy of failure logins

1 sysadm 1.1 <?php
2     require_once "../lib/db_open.inc.php";
3     require_once "../lib/lml.inc.php";
4     require_once "../lib/passwd.inc.php";
5     require_once "../lib/vn_gif.inc.php";
6     require_once "../lib/client_addr.inc.php";
7     require_once "../lib/ip_mask.inc.php";
8     require_once "./session_init.inc.php";
9     require_once "./user_login.inc.php";
10    
11     $data = json_decode(file_get_contents("php://input"), true);
12    
13     $username = (isset($data["username"]) ? trim($data["username"]) : "");
14     $password = (isset($data["password"]) ? trim($data["password"]) : "");
15     $ch_passwd = (isset($data["ch_passwd"]) && $data["ch_passwd"] == "1" ? 1 : 0);
16     $password_new = (isset($data["password_new"]) ? trim($data["password_new"]) : "");
17     $agreement = (isset($data["agreement"]) && $data["agreement"] == "1");
18     $mfa = (isset($data["mfa"]) && $data["mfa"] == "1" ? 1 : 0);
19     $vn_str = (isset($data["vn_str"]) ? trim($data["vn_str"]) : "");
20    
21     $result_set = array(
22     "return" => array(
23     "code" => 0,
24     "message" => "",
25     "errorFields" => array(),
26     )
27     );
28    
29     header("Content-Type:application/json; charset=utf-8");
30    
31     // Validate input data
32     if (!preg_match("/^[A-Za-z][A-Za-z0-9]{2,11}$/", $username))
33     {
34     $result_set["return"]["code"] = -1;
35     array_push($result_set["return"]["errorFields"], array(
36     "id" => "username",
37     "errMsg" => "不符合格式要求",
38     ));
39     }
40    
41     if (!preg_match("/^[A-Za-z0-9]{5,12}$/", $password))
42     {
43     $result_set["return"]["code"] = -1;
44     array_push($result_set["return"]["errorFields"], array(
45     "id" => "password",
46     "errMsg" => "不符合格式要求",
47     ));
48     }
49    
50     if ($ch_passwd)
51     {
52     if (!preg_match("/^[A-Za-z0-9]{6,12}$/", $password_new))
53     {
54     $result_set["return"]["code"] = -1;
55     array_push($result_set["return"]["errorFields"], array(
56     "id" => "password_new",
57     "errMsg" => "不符合格式要求",
58     ));
59     }
60    
61     if (!verify_pass_complexity($password_new, $username, 6))
62     {
63     $result_set["return"]["code"] = -1;
64     array_push($result_set["return"]["errorFields"], array(
65     "id" => "password_new",
66     "errMsg" => "不符合复杂性要求",
67     ));
68     }
69     }
70    
71     if ($mfa)
72     {
73     if ((!isset($_SESSION["BBS_vn_str"])) || $_SESSION["BBS_vn_str"] == "" || strcasecmp($_SESSION["BBS_vn_str"], $vn_str) != 0)
74     {
75     $result_set["return"]["code"] = -1;
76     array_push($result_set["return"]["errorFields"], array(
77     "id" => "vn_str",
78     "errMsg" => "验证码错误",
79     ));
80     }
81     }
82    
83     if ($result_set["return"]["code"] != 0)
84     {
85     mysqli_close($db_conn);
86     exit(json_encode($result_set));
87     }
88    
89     // Begin transaction
90     $rs = mysqli_query($db_conn, "SET autocommit=0");
91     if ($rs == false)
92     {
93     $result_set["return"]["code"] = -2;
94     $result_set["return"]["message"] = "Mysqli error: " . mysqli_error($db_conn);
95    
96     mysqli_close($db_conn);
97     exit(json_encode($result_set));
98     }
99 sysadm 1.2
100 sysadm 1.1 $rs = mysqli_query($db_conn, "BEGIN");
101     if ($rs == false)
102     {
103     $result_set["return"]["code"] = -2;
104     $result_set["return"]["message"] = "Mysqli error: " . mysqli_error($db_conn);
105    
106     mysqli_close($db_conn);
107     exit(json_encode($result_set));
108     }
109    
110     if (!$mfa)
111     {
112     // Failed login attempts from the same source (subnet /24) during certain time period
113     $sql = "SELECT COUNT(*) AS err_count FROM user_err_login_log
114     WHERE login_dt >= SUBDATE(NOW(), INTERVAL 10 MINUTE)
115     AND login_ip LIKE '" . client_addr(1) . "'";
116     $rs = mysqli_query($db_conn, $sql);
117     if ($rs == false)
118     {
119     $result_set["return"]["code"] = -2;
120     $result_set["return"]["message"] = "Query login log error: " . mysqli_error($db_conn);
121 sysadm 1.2
122 sysadm 1.1 mysqli_close($db_conn);
123     exit(json_encode($result_set));
124     }
125    
126     if ($row = mysqli_fetch_array($rs))
127     {
128 sysadm 1.4 if ($row["err_count"] >= 10)
129 sysadm 1.1 {
130     $result_set["return"]["code"] = 1;
131     $result_set["return"]["message"] = "来源存在多次失败登陆尝试,请输入验证码";
132    
133     mysqli_close($db_conn);
134     exit(json_encode($result_set));
135     }
136     }
137     mysqli_free_result($rs);
138    
139 sysadm 1.4 // Failed login attempts against the current username since last successful login
140 sysadm 1.1 $sql = "SELECT COUNT(*) AS err_count FROM user_err_login_log
141 sysadm 1.4 LEFT JOIN user_list ON user_err_login_log.username = user_list.username
142     LEFT JOIN user_pubinfo ON user_list.UID = user_pubinfo.UID
143     WHERE user_err_login_log.username = '$username'
144     AND (user_err_login_log.login_dt >= user_pubinfo.last_login_dt
145     OR user_pubinfo.last_login_dt IS NULL)";
146 sysadm 1.1 $rs = mysqli_query($db_conn, $sql);
147     if ($rs == false)
148     {
149     $result_set["return"]["code"] = -2;
150     $result_set["return"]["message"] = "Query login log error: " . mysqli_error($db_conn);
151 sysadm 1.2
152 sysadm 1.1 mysqli_close($db_conn);
153     exit(json_encode($result_set));
154     }
155    
156     if ($row = mysqli_fetch_array($rs))
157     {
158 sysadm 1.4 if ($row["err_count"] >= 3)
159 sysadm 1.1 {
160     $result_set["return"]["code"] = 1;
161     $result_set["return"]["message"] = "账户存在多次失败登陆尝试,请输入验证码";
162    
163     mysqli_close($db_conn);
164     exit(json_encode($result_set));
165     }
166     }
167     mysqli_free_result($rs);
168     }
169    
170     $sql = "SELECT UID, p_login, verified, temp_password,
171     password = MD5('$password') AS old_pass
172     FROM user_list WHERE username = '$username' AND
173     (password = MD5('$password') OR password = SHA2('$password', 256) OR
174     temp_password = '$password')
175     AND enable FOR UPDATE";
176    
177     $rs = mysqli_query($db_conn, $sql);
178     if ($rs == false)
179     {
180     $result_set["return"]["code"] = -2;
181     $result_set["return"]["message"] = "Query user list error: " . mysqli_error($db_conn);
182    
183     mysqli_close($db_conn);
184     exit(json_encode($result_set));
185     }
186    
187     $uid = 0;
188    
189     if ($row = mysqli_fetch_array($rs))
190     {
191     $uid = intval($row["UID"]);
192    
193     if ($password == $row["temp_password"] && !$ch_passwd)
194     {
195     $result_set["return"]["code"] = 2;
196     $result_set["return"]["message"] = "使用临时密码登录需设置新密码";
197    
198     mysqli_close($db_conn);
199     exit(json_encode($result_set));
200     }
201    
202     if ($ch_passwd)
203     {
204     if ($password == $row["temp_password"]) // New user first time login with temp password
205     {
206     $verified = 1;
207    
208     // Set life = 150 for verified user
209     $sql = "UPDATE user_pubinfo SET life = 150 WHERE UID = $uid";
210     $rs_life = mysqli_query($db_conn, $sql);
211     if ($rs_life == false)
212     {
213     $result_set["return"]["code"] = -2;
214     $result_set["return"]["message"] = "Update user life error: " . mysqli_error($db_conn);
215 sysadm 1.2
216 sysadm 1.1 mysqli_close($db_conn);
217     exit(json_encode($result_set));
218     }
219     }
220     else
221     {
222     $verified = $row["verified"];
223     }
224    
225     $sql = "UPDATE user_list SET password = SHA2('$password_new', 256),
226     temp_password = '', verified = $verified WHERE UID = $uid";
227     $rs_p = mysqli_query($db_conn, $sql);
228     if ($rs_p == false)
229     {
230     $result_set["return"]["code"] = -2;
231     $result_set["return"]["message"] = "Update password error: " . mysqli_error($db_conn);
232 sysadm 1.2
233 sysadm 1.1 mysqli_close($db_conn);
234     exit(json_encode($result_set));
235     }
236     }
237     else if ($row["old_pass"])
238     {
239     $sql = "UPDATE user_list SET password = SHA2('$password', 256) WHERE UID = $uid";
240     $rs_p = mysqli_query($db_conn, $sql);
241     if ($rs_p == false)
242     {
243     $result_set["return"]["code"] = -2;
244     $result_set["return"]["message"] = "Upgrade password error: " . mysqli_error($db_conn);
245 sysadm 1.2
246 sysadm 1.1 mysqli_close($db_conn);
247     exit(json_encode($result_set));
248     }
249     }
250    
251     mysqli_free_result($rs);
252    
253     // Add user login log
254     $sql = "INSERT INTO user_login_log(uid, login_dt, login_ip) VALUES($uid, NOW(), '" .
255     client_addr() . "')";
256     $rs = mysqli_query($db_conn, $sql);
257     if ($rs == false)
258     {
259     $result_set["return"]["code"] = -2;
260     $result_set["return"]["message"] = "Write log error: " . mysqli_error($db_conn);
261    
262     mysqli_close($db_conn);
263     exit(json_encode($result_set));
264     }
265    
266     // Commit transaction
267     $rs = mysqli_query($db_conn, "COMMIT");
268     if ($rs == false)
269     {
270     $result_set["return"]["code"] = -2;
271     $result_set["return"]["message"] = "Mysqli error: " . mysqli_error($db_conn);
272    
273     mysqli_close($db_conn);
274     exit(json_encode($result_set));
275     }
276 sysadm 1.2
277 sysadm 1.1 // Forbidden user
278     if (!$row["p_login"])
279     {
280     $result_set["return"]["code"] = 3;
281     $result_set["return"]["message"] = "您已被封禁全站登陆权限!";
282 sysadm 1.2
283 sysadm 1.1 mysqli_close($db_conn);
284     exit(json_encode($result_set));
285     }
286     }
287     else
288     {
289     // Log login failure
290     $sql = "INSERT INTO user_err_login_log(username, password, login_dt, login_ip)
291     VALUES('$username', '$password', NOW(), '" . client_addr() . "')";
292    
293     $rs = mysqli_query($db_conn, $sql);
294     if ($rs == false)
295     {
296     $result_set["return"]["code"] = -2;
297     $result_set["return"]["message"] = "Write log error: " . mysqli_error($db_conn);
298 sysadm 1.2
299 sysadm 1.1 mysqli_close($db_conn);
300     exit(json_encode($result_set));
301     }
302    
303     // Commit transaction
304     $rs = mysqli_query($db_conn, "COMMIT");
305     if ($rs == false)
306     {
307     $result_set["return"]["code"] = -2;
308     $result_set["return"]["message"] = "Mysqli error: " . mysqli_error($db_conn);
309    
310     mysqli_close($db_conn);
311     exit(json_encode($result_set));
312     }
313    
314     $_SESSION["BBS_vn_str"] = ""; // Force change vn_str
315    
316     $result_set["return"]["code"] = 3;
317     $result_set["return"]["message"] = "用户名或密码不正确";
318    
319     mysqli_close($db_conn);
320     exit(json_encode($result_set));
321     }
322    
323     // SET AUTOCOMMIT = 1
324     $rs = mysqli_query($db_conn, "SET autocommit=1");
325     if ($rs == false)
326     {
327     $result_set["return"]["code"] = -2;
328     $result_set["return"]["message"] = "Mysqli error: " . mysqli_error($db_conn);
329    
330     mysqli_close($db_conn);
331     exit(json_encode($result_set));
332     }
333 sysadm 1.2
334 sysadm 1.1 //Load User Information
335     $ret = load_user_info($uid, $db_conn);
336     switch($ret)
337     {
338     case -1:
339     $result_set["return"]["code"] = -2;
340     $result_set["return"]["message"] = "User data not found: " . mysqli_error($db_conn);
341 sysadm 1.2
342 sysadm 1.1 mysqli_close($db_conn);
343     exit(json_encode($result_set));
344     case -2:
345     if (!$agreement)
346     {
347     $buffer = file_get_contents("./doc/license/" . (new DateTime($BBS_license_dt))->format("Ymd") . ".txt");
348 sysadm 1.2
349 sysadm 1.1 $result_set["return"]["code"] = 4;
350     $result_set["return"]["message"] = LML(htmlspecialchars($buffer, ENT_HTML401, 'UTF-8'), false, false, 1024);
351 sysadm 1.2
352 sysadm 1.1 mysqli_close($db_conn);
353     exit(json_encode($result_set));
354     }
355     break;
356     case -3:
357     $result_set["return"]["code"] = 3;
358     $result_set["return"]["message"] = "很遗憾,您已经永远离开了我们的世界……";
359 sysadm 1.2
360 sysadm 1.1 mysqli_close($db_conn);
361     exit(json_encode($result_set));
362     }
363    
364     $sql = "UPDATE user_pubinfo SET visit_count = visit_count + 1,
365     last_login_dt = NOW() WHERE UID = $uid";
366     $rs = mysqli_query($db_conn, $sql);
367     if ($rs == false)
368     {
369     $result_set["return"]["code"] = -2;
370     $result_set["return"]["message"] = "Update login info error: " . mysqli_error($db_conn);
371    
372     mysqli_close($db_conn);
373     exit(json_encode($result_set));
374     }
375    
376     $_SESSION["BBS_uid"] = $uid;
377     $_SESSION["BBS_username"] = $username;
378     $_SESSION["BBS_login_tm"] = time();
379     $_SESSION["BBS_vn_str"] = "";
380    
381     if (!keep_alive($db_conn))
382     {
383     $result_set["return"]["code"] = -2;
384     $result_set["return"]["message"] = "Keep alive error: " . mysqli_error($db_conn);
385    
386     mysqli_close($db_conn);
387     exit(json_encode($result_set));
388     }
389    
390     mysqli_close($db_conn);
391     exit(json_encode($result_set));

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1