注册和登录
1.前言
由于 HTTP 请求是一种无状态的请求,所以服务器不知道是谁在操作,所以服务器为用户创建了指定的 SESSION,主要作用是用来标识并且跟踪用户的,当某个用户向服务器发起请求时,服务器会首先检查这个用户的请求里是否已包含了一个 SESSION 标识(SESSION ID),如果已包含则说明以前已经为此客户端创建过 SESSION,服务器就按照 SESSION ID 把这个 SESSION 检索出来使用,如果用户的请求不包含 SESSION ID,就会为该用户创建一个 SESSION,并且生成一个与该 SESSION 关联的 SESSION ID。COOKIE 是服务器在用户本地机器上存储的小段文本并随每一个请求发送至同一个服务器,COOKIE 也可以用来保存用户信息,和 SESSION 相比,COOKIE 是保存在用户端的(如浏览器),下面通过登录注册的例子来说明 SESSION 和 COOKIE 的作用。
2.新建登录注册表
2.1 确定字段
| 字段名称 | 含义 | 
|---|---|
| id | 自增主键 | 
| sex | 性别,0-保密,1-男,2-女 | 
| birthday | 生日 | 
| last_login_time | 最后登录时间 | 
| create_time | 注册时间 | 
| user_status | 用户状态,0-禁用,1-正常,2-未验证 | 
| username | 用户名 | 
| password | 密码 | 
| nickname | 昵称 | 
| last_login_ip | 最后登录ip | 
2.2 选择字段的数据类型
| 字段名称 | 数据类型 | 
|---|---|
| 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 新建数据表
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 '最后登录时间',
  `create_time` int(11) NOT NULL COMMENT '注册时间',
  `user_status` tinyint(2) unsigned NOT NULL DEFAULT '0' COMMENT '用户状态,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.注册
3.1 新建注册路由
//注册界面
Route::get('register','login/register');
如下图所示:

3.2 新建控制器和注册界面方法
    /**
     * 用户注册界面
     * @return string
     */
    public function register(){
        return View::fetch('login/register');
    }
如下图所示:

Tips: 其中
View::fetch表示调用模板引擎。
3.3 新建 html 模板
如下图所示,在 view\login 目录中新建 register.html 模板文件:

Tips: 模板文件可根据自己需求定义,
css、js文件可以按照图中格式引入,从图中可以看到注册信息提交至login/do_register中。
3.4 定义信息注册数据处理方法
    /**
     * 用户注册信息校验入库
     * @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'); //验证码
        $password = $this->request->param('password'); //密码
        $re_password = $this->request->param('re_password'); //重复密码
        $username = $this->request->param('username'); //用户名
        if(empty($captcha) ||empty($password) || empty($re_password) || empty($username)){
            throw new HttpException(400,"必要参数不能为空");
        }
//        //校验验证码是否正确
//        if(!captcha_check($captcha)){
//            throw new HttpException(400,"验证码不正确");
//        };
        //校验两次密码书否输入一致
        if($password != $re_password){
            throw new HttpException(400,"两次输入密码不一致");
        }
        //检查用户名是否已经被注册过
        if(!empty(LoginModel::where('username',$username)->find())){
            throw new HttpException(400,"用户名已经存在");
        }
        try {
            $login = new LoginModel();
            $login->sex = $this->request->param('sex',0);//性别赋值,默认值保密
            $login->birthday = strtotime($this->request->param('birthday'));//生日转化为时间戳赋值
            $login->create_time = time();//注册时间为当前时间
            $login->user_status = 1;//用户状态 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,"注册失败");
        }
        return json("请求成功");
    }
用户注册界面如下:

3.5 视频演示
4.用户登录
4.1 开启 SESSION
打开 app\middleware.php 文件,将 \think\middleware\SessionInit::class 注释去掉,如下图所示:

4.2 新建注册路由
//用户登录界面
Route::get('login','login/login');
//获取用户登录信息
Route::get('userinfo','login/userinfo');
如下图所示:

4.3 新建控制器和注册界面方法
    /**
     * 用户登录界面
     * @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表示调用模板引擎。
4.4 新建 html 模板
如下图所示,在 view\login 目录中新建 login.html 模板文件:

Tips: 模板文件可根据自己需求定义,
css、js文件可以按照图中格式引入,从图中可以看到登录信息提交至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'); //用户名
        //根据用户名获取用户信息
        $user = LoginModel::where('username',$username)->where('user_status',1)->find();
        if(empty($user)){
            throw new HttpException(400,"用户信息不存在");
        }
        //校验密码是否正确
        if(md5($password."test") != $user->password){
            throw new HttpException(400,"密码不正确");
        }
        //登录成功之后向 SESSION 保存用户信息
        session("user_info",$user);//浏览器关闭断开失效
        //登录成功之后向 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.小结
本小节主要介绍登录注册的逻辑,使用的是 ThinkPHP 框架支持的模板引擎,SESSION 信息时保存在服务器端的,每次浏览器关闭(或服务器端设置了 SESSION 过期时间)之后失效,而 COOKIE 则是保存在用户端浏览器中的,浏览器关闭之后在有效期内,信息依然存在,它的缺点是 COOKIE 泄漏会造成盗号现象,需要注意的是现在大多数 api 接口登录不使用 SESSION 了,而是在每次的请求头部带上 token 信息。
Tips: 代码仓库:https://gitee.com/love-for-poetry/tp6