## 创建用户表
利用migration创建一个用户表
```
php think migrate:create Users
```
## 编写 migration
```
public function change()
{
$table = $this->table('users', ['engine' => 'InnoDB']);
$table->addColumn('name', 'string',['limit' => 50, 'default'=>'','comment'=>'用户名'])
->addColumn('email', 'string',['limit' => 255, 'default'=>'','comment'=>'邮箱'])
->addColumn('password', 'string',['limit' => 255, 'default'=>'','comment'=>'密码'])
->addColumn('remember_token', 'string',['limit' => 255, 'default'=>'','comment'=>'记住token'])
->addColumn('login_ip', 'string',['limit' => 50, 'default'=>'','comment'=>'登录IP'])
->addColumn('login_at', 'timestamp', [ 'comment' => '最近登录时间'])
->addColumn('created_at', 'timestamp', [ 'comment' => '更新时间'])
->addIndex(['name'], ['unique' => true])
->create();
}
```
## 创建用户表
```
php think migrate:run
```
以上步骤可以成功创建用户表了
## 创建User模型
```
namespace app\model;
class UserModel extends AbstractBase
{
public function store($data)
{
// TODO: Implement store() method.
$this->data($data);
return $this->save();
}
public function deleteBy($id)
{
// TODO: Implement deleteBy() method.
return $this->where('id', $id)->delete();
}
public function updateBy($id, $data)
{
// TODO: Implement updateBy() method.
return $this->where('id', $id)->update($data);
}
public function findBy($id)
{
// TODO: Implement findBy() method.
return $this->where('id', $id)->findOrEmpty();
}
/**
* 根据 NAME 查找
* @param $name
* @return array|null|\PDOStatement|string|\think\Model
*/
public function findByName($name, $id = null)
{
$where = [
'name' => $name,
];
if ($id) {
$where['id'] = ['<>', $id];
return self::where($this->conditions($where))->find();
}
return self::where($where)->find();
}
/**
* 根据 EMAIL 查找
* @param $email
* @param null $id
* @return array|null|\PDOStatement|string|\think\Model
*/
public function findByEmail($email, $id = null)
{
$where = [
'email' => $email,
];
if ($id) {
$where['id'] = ['<>', $id];
return self::where($this->conditions($where))->find();
}
return self::where($where)->find();
}
}
```
模型创建成功之后了,下面开始实现登录。
## 登录的实现
创建 app\traits\Auth.php 认证文件,简化一下实现思路。以及几个功能点。
> 1.必须登录成功
2.需要记住功能
记住的实现,肯定利用到了Cookie,需要对remember_token进行认证便可以了。
下面看一下代码的实现。
```
namespace app\traits;
use think\Request;
use think\Validate;
use think\facade\Session;
use think\facade\Cookie;
use app\model\UserModel as User;
trait Auth
{
public function authLogin(Request $request)
{
$err = $this->validateLogin($request);
if ($err) {
$this->error($err);
}
// 正常输入登录
$userModel = new User();
$filed = explode('|', $this->name());
$user = $userModel::where($filed[0], $request->param($filed[0]))->findOrEmpty();
if (!$user) {
$this->error('登录失败');
}
if (password_verify($request->param('password'), $user->password)) {
Session::set('user', $user);
// 记住登录
$this->LoginRemember($user, $request);
$this->success('登录成功', url($this->redirect));
}
$this->error('登录失败');
}
/**
* 记住登录
* @return bool
*/
public function rememberLogin()
{
// 如果记住登录
if (!Session::get('user') && Cookie::get('remember_token') && $this->checkRememberToken()) {
return true;
}
return false;
}
/**
* 退出
* @return void
*/
public function authLogout()
{
$user = Session::get('user');
$user->remember_token = null;
$user->save();
Cookie::delete('remember_token');
Session::delete('user');
}
/**
* 验证
* @param Request $request
* @return array|bool
*/
protected function validateLogin(Request $request)
{
$validate = new Validate($this->rule());
if (!$validate->check($request->except(['remember']))) {
return $validate->getError();
}
return false;
}
/**
* 登录验证规则
* @return array
*/
protected function rule()
{
return [
$this->name() => 'require|token|alphaDash',
'password|密码' => 'require|alphaDash',
//'captcha|验证码' => 'require|captcha'
];
}
/**
* 设置登录字段
*
* @return string
*/
protected function name()
{
return 'name|用户名';
}
/**
* Remember Token
*
* @return string
*/
public function generateRememberToken()
{
return uniqid(md5(time()+rand(10000, 99999)));
}
/**
* 加密 TOKEN
*
* @param $user_id
* @param $remember_token
* @return string
*/
protected function secretRememberToken($user_id, $remember_token)
{
list($key, $method, $iv) = $this->getSecret();
return base64_encode(openssl_encrypt($user_id . ':' . $remember_token, $method, $key, OPENSSL_RAW_DATA, $iv));
}
/**
* 检查remember token 是否正确
*
* @return bool
*/
protected function checkRememberToken()
{
if (!Cookie::has('remember_token')) {
return false;
}
$rememberToken = Cookie::get('remember_token');
// 解密
list($key, $method, $iv) = $this->getSecret();
list($userID) = explode(':', (openssl_decrypt(base64_decode($rememberToken), $method, $key, OPENSSL_RAW_DATA, $iv)));
// 校验
$user = (new User())->findBy($userID);
Session::set('user', $user);
return $user->remember_token == $rememberToken;
}
/**
* 加密
*
* @return array
*/
protected function getSecret()
{
return ['admin_auth', 'AES-128-CBC', '1234567890123412'];
}
/**
* 记住
*
* @param $user
* @return void
*/
protected function LoginRemember($user, Request $request)
{
if ($request->has('remember')) {
$rememberToken = $this->secretRememberToken($user->id, $this->generateRememberToken());
$user->remember_token = $rememberToken;
Cookie::forever('remember_token', $rememberToken);
}
$user->login_at = date('Y-m-d h:i:s', time());
$user->login_ip = request()->ip();
$user->save();
}
}
```
Auth实现之后登录就很方便了。
## login 实现
创建 application\admin\controller\Login.php
```
namespace app\admin\controller;
use think\Controller;
use app\traits\Auth;
class Login extends Controller
{
use Auth;
protected $redirect = 'admin/index/index';
/**
* Login Page
*
* @return mixed
*/
public function login()
{
// 登录逻辑
if ($this->request->isPost()) {
$this->authLogin($this->request);
}
// 记住登录的话, 直接登录
if ($this->rememberLogin()) {
return redirect($this->redirect);
}
return $this->fetch('admin/login/login');
}
/**
* 登出
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\think\response\Redirect
*/
public function logout()
{
$this->authLogout();
return redirect('admin/login/login');
}
}
```
## 页面效果