注冊(cè)和登錄
1.前言
由于 HTTP
請(qǐng)求是一種無狀態(tài)的請(qǐng)求,所以服務(wù)器不知道是誰在操作,所以服務(wù)器為用戶創(chuàng)建了指定的 SESSION
,主要作用是用來標(biāo)識(shí)并且跟蹤用戶的,當(dāng)某個(gè)用戶向服務(wù)器發(fā)起請(qǐng)求時(shí),服務(wù)器會(huì)首先檢查這個(gè)用戶的請(qǐng)求里是否已包含了一個(gè) SESSION
標(biāo)識(shí)(SESSION ID
),如果已包含則說明以前已經(jīng)為此客戶端創(chuàng)建過 SESSION
,服務(wù)器就按照 SESSION ID
把這個(gè) SESSION
檢索出來使用,如果用戶的請(qǐng)求不包含 SESSION ID
,就會(huì)為該用戶創(chuàng)建一個(gè) SESSION
,并且生成一個(gè)與該 SESSION
關(guān)聯(lián)的 SESSION ID
。COOKIE
是服務(wù)器在用戶本地機(jī)器上存儲(chǔ)的小段文本并隨每一個(gè)請(qǐng)求發(fā)送至同一個(gè)服務(wù)器,COOKIE
也可以用來保存用戶信息,和 SESSION
相比,COOKIE
是保存在用戶端的(如瀏覽器),下面通過登錄注冊(cè)的例子來說明 SESSION
和 COOKIE
的作用。
2.新建登錄注冊(cè)表
2.1 確定字段
字段名稱 | 含義 |
---|---|
id | 自增主鍵 |
sex | 性別,0-保密,1-男,2-女 |
birthday | 生日 |
last_login_time | 最后登錄時(shí)間 |
create_time | 注冊(cè)時(shí)間 |
user_status | 用戶狀態(tài),0-禁用,1-正常,2-未驗(yàn)證 |
username | 用戶名 |
password | 密碼 |
nickname | 昵稱 |
last_login_ip | 最后登錄ip |
2.2 選擇字段的數(shù)據(jù)類型
字段名稱 | 數(shù)據(jù)類型 |
---|---|
id | BIGINT(20) |
sex | TINYINT(2) |
birthday | INT(11) |
last_login_time | INT(11) |
create_time | INT(11) |
user_status | TINYINT(2) |
username | VARCHAR(60) |
password | VARCHAR(64) |
nickname | VARCHAR(50) |
last_login_ip | VARCHAR(15) |
2.3 新建數(shù)據(jù)表
CREATE TABLE `login` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`sex` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '性別,0-保密,1-男,2-女',
`birthday` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '生日',
`last_login_time` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '最后登錄時(shí)間',
`create_time` int(11) NOT NULL COMMENT '注冊(cè)時(shí)間',
`user_status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '用戶狀態(tài),0-禁用,1-正常',
`username` varchar(60) NOT NULL DEFAULT '' COMMENT '用戶名',
`password` varchar(64) NOT NULL DEFAULT '' COMMENT '密碼',
`nickname` varchar(50) NOT NULL DEFAULT '' COMMENT '昵稱',
`last_login_ip` varchar(15) NOT NULL DEFAULT '' COMMENT '最后登錄ip',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
3.注冊(cè)
3.1 新建注冊(cè)路由
//注冊(cè)界面
Route::get('register','login/register');
如下圖所示:
3.2 新建控制器和注冊(cè)界面方法
/**
* 用戶注冊(cè)界面
* @return string
*/
public function register(){
return View::fetch('login/register');
}
如下圖所示:
Tips: 其中
View::fetch
表示調(diào)用模板引擎。
3.3 新建 html 模板
如下圖所示,在 view\login
目錄中新建 register.html
模板文件:
Tips: 模板文件可根據(jù)自己需求定義,
css
、js
文件可以按照?qǐng)D中格式引入,從圖中可以看到注冊(cè)信息提交至login/do_register
中。
3.4 定義信息注冊(cè)數(shù)據(jù)處理方法
/**
* 用戶注冊(cè)信息校驗(yàn)入庫
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function do_register(){
$captcha = $this->request->param('captcha'); //驗(yàn)證碼
$password = $this->request->param('password'); //密碼
$re_password = $this->request->param('re_password'); //重復(fù)密碼
$username = $this->request->param('username'); //用戶名
if(empty($captcha) ||empty($password) || empty($re_password) || empty($username)){
throw new HttpException(400,"必要參數(shù)不能為空");
}
// //校驗(yàn)驗(yàn)證碼是否正確
// if(!captcha_check($captcha)){
// throw new HttpException(400,"驗(yàn)證碼不正確");
// };
//校驗(yàn)兩次密碼書否輸入一致
if($password != $re_password){
throw new HttpException(400,"兩次輸入密碼不一致");
}
//檢查用戶名是否已經(jīng)被注冊(cè)過
if(!empty(LoginModel::where('username',$username)->find())){
throw new HttpException(400,"用戶名已經(jīng)存在");
}
try {
$login = new LoginModel();
$login->sex = $this->request->param('sex',0);//性別賦值,默認(rèn)值保密
$login->birthday = strtotime($this->request->param('birthday'));//生日轉(zhuǎn)化為時(shí)間戳賦值
$login->create_time = time();//注冊(cè)時(shí)間為當(dāng)前時(shí)間
$login->user_status = 1;//用戶狀態(tài) 0-禁用 1-正常
$login->username = $username;
$login->password = md5($password."test");//密碼加密
$login->nickname = $this->request->param('nickname');//用戶昵稱
$login->save();//保存
}catch(\Exception $exception){
throw new HttpException(400,"注冊(cè)失敗");
}
return json("請(qǐng)求成功");
}
用戶注冊(cè)界面如下:
3.5 視頻演示
4.用戶登錄
4.1 開啟 SESSION
打開 app\middleware.php
文件,將 \think\middleware\SessionInit::class
注釋去掉,如下圖所示:
4.2 新建注冊(cè)路由
//用戶登錄界面
Route::get('login','login/login');
//獲取用戶登錄信息
Route::get('userinfo','login/userinfo');
如下圖所示:
4.3 新建控制器和注冊(cè)界面方法
/**
* 用戶登錄界面
* @return string
*/
public function login(){
//若存在seesion信息則直接跳過
if(session('user_info')){
return json("登錄成功");
}
//若存在cookie信息則直接跳過
if(cookie("user_info")){
return json("登錄成功");
}
return View::fetch('login/login');
}
如下圖所示:
Tips: 其中
View::fetch
表示調(diào)用模板引擎。
4.4 新建 html 模板
如下圖所示,在 view\login
目錄中新建 login.html
模板文件:
Tips: 模板文件可根據(jù)自己需求定義,
css
、js
文件可以按照?qǐng)D中格式引入,從圖中可以看到登錄信息提交至login/do_login
中。
4.5 定義用戶登錄邏輯方法
/**
* 用戶登錄邏輯
* @return \think\response\Redirect
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function do_login(){
$password = $this->request->param('password'); //密碼
$username = $this->request->param('username'); //用戶名
//根據(jù)用戶名獲取用戶信息
$user = LoginModel::where('username',$username)->where('user_status',1)->find();
if(empty($user)){
throw new HttpException(400,"用戶信息不存在");
}
//校驗(yàn)密碼是否正確
if(md5($password."test") != $user->password){
throw new HttpException(400,"密碼不正確");
}
//登錄成功之后向 SESSION 保存用戶信息
session("user_info",$user);//瀏覽器關(guān)閉斷開失效
//登錄成功之后向 COOKIE 保存用戶信息
// cookie("user_info_",$user,7*24*3600);//7天之后過期
return redirect('/userinfo');
}
4.6 獲取用戶信息方法
/**
* 獲取用戶 SESSION 和 COOKIE 信息
*/
public function userinfo(){
halt(["cookie"=>cookie("user_info"),"session"=>session("user_info")]);
}
登錄界面如下圖所示
用戶信息如下圖所示:
4.7 視頻演示
5.小結(jié)
本小節(jié)主要介紹登錄注冊(cè)的邏輯,使用的是 ThinkPHP
框架支持的模板引擎,SESSION
信息時(shí)保存在服務(wù)器端的,每次瀏覽器關(guān)閉(或服務(wù)器端設(shè)置了 SESSION 過期時(shí)間)之后失效,而 COOKIE
則是保存在用戶端瀏覽器中的,瀏覽器關(guān)閉之后在有效期內(nèi),信息依然存在,它的缺點(diǎn)是 COOKIE
泄漏會(huì)造成盜號(hào)現(xiàn)象,需要注意的是現(xiàn)在大多數(shù) api
接口登錄不使用 SESSION
了,而是在每次的請(qǐng)求頭部帶上 token
信息。
Tips: 代碼倉庫:https://gitee.com/love-for-poetry/tp6