05 | 后台登录:基于账号密码的登录方式(下)

你好, 我是程序猿零壹。

上一篇中,我们一起制作了登录页面,并使用ajax进行数据提交,那提交过来的参数应该怎么接受、处理呢。

Route::get('/login', 'Admin\AuthController@login');
Route::post('/login', 'Admin\AuthController@loginPost');

在routes/web.php文件中,我们定义了上面两条路由。第一条是get方式,用来展示登录页面;第二条是post方式,用来接收用户提交过来的数据。

编辑app/Http/Controllers/Admin/AuthController.php,添加loginPost方方法,内容如下:

<?php
namespace App\Http\Controllers\Admin;
use App\Services\Admin\AuthService;
class AuthController extends BaseController
{
    private $authService;
    public function __construct(AuthService $authService)
    {
        $this->authService = $authService;
    }
​
    public function login(){
        return $this->view('admin/auth/login');
    }
​
    public function loginPost(){
        $params = [
            'username' => request()->input('username',''),
            'password' => request()->input('password',''),
        ];
​
        $response = $this->authService->login($params);
        return $response;
    }
}

这里我们引入了app/Services/AuthService.php这个业务文件,专门用来处理相对应的业务逻辑。AuthService文件的内容如下:

<?php
namespace App\Services\Admin;
use App\Tools\Response\JsonResponse;
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2022/7/26
 * Time: 20:40
 */
class AuthService
{
    public function login($params){
        return JsonResponse::success();
    }
}

现在login函数只有一行代码,用来返回一个json数据给前端页面,以后所有的接口请求,我们都会使用这样的方式来返回数据。新建app/Tools/Resonse/JsonResponse.php文件,内容如下:

<?php
namespace App\Tools\Response;
use App\Constants\ResponseCode;
class JsonResponse
{
    public static function success($data=[],$msg = '操作成功'){
        return response()->json(['code'=> ResponseCode::SUCCESS,'msg'=>$msg,'data'=>$data])->setEncodingOptions(JSON_UNESCAPED_UNICODE);
    }
    public static function fail($msg = ''){
        return response()->json(['code'=> ResponseCode::FAIL,'msg'=>$msg])->setEncodingOptions(JSON_UNESCAPED_UNICODE);
    }
}

新建app/Constants/ResponseCode.php,内容如下:

<?php
declare(strict_types=1);
namespace App\Constants;
class ResponseCode
{
    const SUCCESS = 'success';
    const FAIL = 'fail';
    const ADMIN_LOGOUT = 'admin_logout';
}

到这里,当我们点击登录页面的提交按钮后,会登录成功并跳转到/admin/home/index这个页面,也就是后台首页。

但是上面的步骤中,我们并没有对账号密码进行校验。现在我们就要添加这一步骤了。在这之前,我们先来了解下在laravel框架中,如何与数据库进行交互。

在laravel中,给我们提供一个强大的工具来与数据库进行交互,这就是ORM。每个数据库表都有一个对应的ORM模型用来与之交互,可以通过模型来查询数据库中的数据,以及在数据表中插入和更新数据。

在开始使用ORM之前,我们需要修改.env文件并配置其中跟数据库有关的配置。

配置完上图的数据库配置之后,我们就可以使用ORM与数据库交互了。

不过在这之前,我们需要先完成数据库表的创建。我们需要两张表,一张表取名为accounts,用来存储账号基本信息,例如昵称,头像,性别等信息;另外一张表取名为account_password,用来存储账号密码等信息。创建及插入数据的sql语句如下:

CREATE TABLE `accounts` (
  `account_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `nickname` VARCHAR(50) NOT NULL COMMENT '昵称' COLLATE 'utf8mb4_general_ci',
  `avatar` VARCHAR(255) NOT NULL COMMENT '头像' COLLATE 'utf8mb4_general_ci',
  `sex` TINYINT(3) NOT NULL DEFAULT '3' COMMENT '性别 1-男 2-女 3-未知',
  `status` TINYINT(3) NOT NULL DEFAULT '1' COMMENT '状态  1-启用 2-禁用',
  `created_at` INT(10) NOT NULL DEFAULT '0',
  `updated_at` INT(10) NOT NULL DEFAULT '0',
  PRIMARY KEY (`account_id`) USING BTREE
)
COMMENT='账号表'
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
;
INSERT INTO `accounts` (`account_id`, `nickname`, `avatar`, `sex`, `status`, `created_at`, `updated_at`) VALUES
  (1, '零壹', '/static/admin/imgs/avatar.jpg', 3, 1, 1653533903, 1653533903);

CREATE TABLE `account_password` (
  `id` INT(10) NOT NULL AUTO_INCREMENT,
  `account_id` INT(10) NOT NULL DEFAULT '0',
  `name` VARCHAR(50) NOT NULL COLLATE 'utf8mb4_general_ci',
  `passwd` VARCHAR(64) NOT NULL COLLATE 'utf8mb4_general_ci',
  `salt` CHAR(6) NOT NULL DEFAULT '' COLLATE 'utf8mb4_general_ci',
  `created_at` INT(10) NOT NULL DEFAULT '0',
  `updated_at` INT(10) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `name` (`name`) USING BTREE,
  INDEX `account_id` (`account_id`) USING BTREE
)
COMMENT='账号密码'
COLLATE='utf8mb4_general_ci'
ENGINE=InnoDB
;
INSERT INTO `account_password` (`id`, `account_id`, `name`, `passwd`, `salt`, `created_at`, `updated_at`) VALUES
  (1, 1, 'admin', 'b3de394180907ace8d94611486b0d9aab5f110a8dbda1b28a83277117fa89b30', 'prz6g9', 1653533903, 1653533903);

数据库表现在已经创建好并插入了测试数据

账号:admin 密码:123456

画外音:这个密码简直不要太简单,正式环境建议设置为复杂密码。

接下来我们来创建ORM模型文件。

新建app/Models/BaseModel.php文件,内容如下:

<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class BaseModel extends Model
{
    public $casts = [];
    public $guarded=[];
​
    public $dateFormat = 'U';
    public $timestamps = true;
}

新建app/Models/AccountModel.php文件,内容如下:

<?php
namespace App\Models;
class AccountModel extends BaseModel
{
    public $table = 'accounts';
    public $primaryKey = 'account_id';
}

新建app/Models/AccountPasswordModel.php文件,内容如下:

<?php
namespace App\Models;
class AccountPasswordModel extends BaseModel
{
    public $table = 'account_password';
    public $primaryKey = 'id';
}

好了,现在ORM模型文件都已经创建完毕了。那要怎么使用呢?我们接着往下看。

新建app/Tools/Common/AuthTool.php,内容如下:

<?php
namespace App\Tools\Common;
​
class AuthTool
{
    public static function generateSalt($saltLength=6){
        $str = '23456789abcdefghijkmnpqrstuvwxyz';
        $length = strlen($str);
        $str = str_split($str);
        $lastPosition = $length-1;
        $salt = '';
        for($i=0;$i<$saltLength;$i++) {
            $rand = rand(0, $lastPosition);
            $salt .= $str[$rand] ?? 'a';
        }
        return $salt;
    }
​
    public static function encryptPassword($pwd, $salt=''){
        $password = hash('sha256',md5($pwd).$salt);
        return $password;
    }
}

修改app/Services/AuthService.php的login函数,内容如下:

<?php
namespace App\Services\Admin;
use App\Models\AccountModel;
use App\Models\AccountPasswordModel;
use App\Tools\Common\AuthTool;
use App\Tools\Response\JsonResponse;
​
class AuthService
{
    public function login($params){
        if(empty($params['username']) || empty($params['password'])) {
            return JsonResponse::fail('登录失败,账号不存在或者密码错误');
        }
        $accountPassword = AccountPasswordModel::query()
            ->select(['name','passwd','salt','account_id'])
            ->where(['name'=>$params['username']])
            ->first();
        if(empty($accountPassword)) {
            return JsonResponse::fail('登录失败,账号不存在或者密码错误');
        }
        $encryptPassword = AuthTool::encryptPassword($params['password'], $accountPassword['salt']);
        if($encryptPassword != $accountPassword['passwd']) {
            return JsonResponse::fail('登录失败,账号不存在或者密码错误');
        }
​
        $account = AccountModel::query()
            ->select(['account_id'])
            ->where(['account_id'=>$accountPassword['account_id']])
            ->first();
        if(empty($account)) {
            return JsonResponse::fail('登录失败,账号不存在或者密码错误');
        }
        request()->session()->put('admin_login_user_id',$account['account_id']);
        return JsonResponse::success();
    }
}

下面,我们对login这个函数来做一个拆解说明。

$accountPassword = AccountPasswordModel::query()
            ->select(['name','passwd','salt','account_id'])
            ->where(['name'=>$params['username']])
            ->first();

上面语句使用的是连贯操作,从account_password表查询一条name为admin的记录,相当于mysql语句:

select name,passwd,salt,account_id from account_password where name='admin' limit 1;

如果没有查找到记录,说明账号不存在,返回错误提示;如果查找到记录,说明账号存在,获取到$accountPassword ,需要进行密码校验。

将用户提交的密码123456使用AuthTool的encryptPassword函数进行加密后得到$encryptPassword变量,将$encryptPassword 与 $accountPassword['passwd']进行对比,如果相同,则表示密码校验通过;如果不同,则表示密码校验不通过,返回错误提示。

然后根据$accountPassword['account_id']到account表查找对应账号信息。

如果账号信息存在,则登录成功,否则返回错误提示。

// select account_id,name,avatar from accounts where account_id = 1 limit 1;
$account = AccountModel::query()
            ->select(['account_id','nickname','avatar'])
            ->where(['account_id'=>$accountPassword['account_id']])
            ->first();

将下来,我们需要将账号信息保存到session,并返回操作成功给前端页面,前端接收到后端返回的数据后,判断登录成功,将跳转到后台首页,否则弹窗提示错误信息。到此,登录操作完成。

 request()->session()->put('admin_login_user_id',$account['account_id']);

session,也叫会话控制,用来存储特定用户会话所需要的属性及配置信息。当用户在不同的页面跳转的时候,存储在session对象中的变量或者数据将不会丢失,而是在整个会话中一直存在下去。有关session的详细信息,请自行百度查阅,或者在关注公众号菜单回复session,即可查看相关文章。

今天我们一起完成了整个登录操作,有点意犹未尽的感觉。下一篇我们将来创建一个带有头部和左侧菜单栏的公共页面。

敬请期待!

欢迎关注

最后,欢迎大家关注我的公众号呀 。打开微信搜索程序猿零壹公众号即可关注,希望能与大家共同进步。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值