基于 ThinkPHP5.1 实现的海豚后台登录源码分析

发布时间 - 2019-09-18 00:00:00    点击率:

基于 thinkphp5.1 实现的海豚后台登录源码分析

一、 首先来到登录代码处,部分代码截图,大家有兴趣可以自己去看源码

登录处开始

public function signin()
{
    if ($this->request->isPost()) {
        // 获取post数据
        $data = $this->request->post();   
        $rememberme = isset($data['remember-me']) ? true : false;
        // 登录钩子, 做一些登录前动作, 这里暂时没有实现
        $hook_result = Hook::listen('signin', $data);
        if (!empty($hook_result) && true !== $hook_result[0]) {
            $this->error($hook_result[0]);
        }
        // 验证数据 
        $result = $this->validate($data, 'User.signin');
        if(true !== $result){
            // 验证失败 输出错误信息
            $this->error($result);
        }
        // 验证码  
        if (config('captcha_signin')) {
            $captcha = $this->request->post('captcha', '');
            $captcha == '' && $this->error('请输入验证码');
            if(!captcha_check($captcha, '')){
                //验证失败
                $this->error('验证码错误或失效');
            };
        }
        // 登录
        $UserModel = new UserModel模型分析;   // 进去模型逻辑
        $uid = $UserModel->login($data['username'], $data['password'], $rememberme);
        if ($uid) {
            // 记录行为
            action_log('user_signin', 'admin_user', $uid, $uid);
            $this->jumpUrl();
        } else {
            $this->error($UserModel->getError());
        }
    } else {   // 下面是单点登录的钩子,目前后台不支持
         $hook_result = Hook::listen('signin_sso');
          if (!empty($hook_result) && true !== $hook_result[0]) {
              if (isset($hook_result[0]['url'])) {
                  $this->redirect($hook_result[0]['url']);
              }  if (isset($hook_result[0]['error'])) {
                  $this->error($hook_result[0]['error']);
             } }
          if (is_signin()) {
          $this->jumpUrl();
         } else {
          return $this->fetch();
         }}
}

进入 UserModel 模型分析

$UserModel = new UserModel;   
// 调用模型中的Login登录, 账号 密码 是否记住我
$uid = $UserModel->login($data['username'], $data['password'], $rememberme);
public function login($username = '', $password = '', $rememberme = false)\
{
$username = trim($username); 
$password = trim($password);
// 匹配登录方式
if (preg_match("/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/", $username)) {
// 邮箱登录
$map['email'] = $username;
} elseif (preg_match("/^1\d{10}$/", $username)) {
// 手机号登录
$map['mobile'] = $username;
} else {
// 用户名登录
$map['username'] = $username;
}
$map['status'] = 1;
// 查找用户
$user = $this::get($map);
if (!$user) {
$this->error = '用户不存在或被禁用!';
} else {
// 检查是否分配用户组
if ($user['role'] == 0) {
$this->error = '禁止访问,原因:未分配角色!';
return false;
}  // 检查是可登录后台
if (!RoleModel::where(['id' => $user['role'], 'status' => 1])->value('access')) {
$this->error = '禁止访问,用户所在角色未启用或禁止访问后台!';
return false;
}  if (!Hash::check((string)$password, $user['password'])) {
$this->error = '账号或者密码错误!';
} else {
$uid = $user['id'];
// 更新登录信息
$user['last_login_time'] = request()->time();
$user['last_login_ip']   = request()->ip(1);
if ($user->save()) {
// 自动登录
return $this->autoLogin($this::get($uid), $rememberme);
} else {
// 更新登录信息失败
$this->error = '登录信息更新失败,请重新登录!';
return false;
} } }  return false;
}

检查各种权限没有问题后开始登录

public function autoLogin($user, $rememberme = false)
{
    // 记录登录SESSION和COOKIES
    $auth = array(
        'uid'             => $user->id,
        'group'           => $user->group,
        'role'            => $user->role,
        'role_name'       => Db::name('admin_role')->where('id', $user->role)->value('name'),
        'avatar'          => $user->avatar,
        'username'        => $user->username,
        'nickname'        => $user->nickname,
        'last_login_time' => $user->last_login_time,
        'last_login_ip'   => get_client_ip(1),
    );
    session('user_auth', $auth);   // 默认保存session 
    session('user_auth_sign', data_auth_sign($auth));  //参数进行加密
    // 保存用户节点权限, 方面后期直接用
    if ($user->role != 1) {
        $menu_auth = Db::name('admin_role')->where('id', session('user_auth.role'))->value('menu_auth');
        $menu_auth = json_decode($menu_auth, true);
        if (!$menu_auth) {
            session('user_auth', null);
            session('user_auth_sign', null);
            $this->error = '未分配任何节点权限!';
            return false;
        }
    }
    // 记住登录
    if ($rememberme) {   // 存储的cookie  data_auth_sign 对signin 进行加密
        $signin_token = $user->username.$user->id.$user->last_login_time;
        cookie('uid', $user->id, 24 * 3600 * 7);
        cookie('signin_token', data_auth_sign($signin_token), 24 * 3600 * 7);
    }
    return $user->id;   //登录成功返回uid 
}

关于 data_auth_sign 加密方法

 function data_auth_sign($data = [])
{
    // 数据类型检测
    if(!is_array($data)){
        $data = (array)$data;
    }
    // 排序
    ksort($data);
    // url编码并生成query字符串
    $code = http_build_query($data);
    // 生成签名
    $sign = sha1($code);
    return $sign;
}
登录后进行登录行为记录,大家可以根据自己需求选择是否记录
最后进行登陆后跳转,分析用户可以跳转的 url
private function jumpUrl()
{
    if (session('user_auth.role') == 1) {  // 判断是否管理员
        $this->success('登录成功', url('admin/index/index'));
    }
    // 是否有指定默认跳转模块
    $default_module = RoleModel::where('id', session('user_auth.role'))->value('default_module');
    $menu = MenuModel::get($default_module);
    if (!$menu) {
        $this->error('当前角色未指定默认跳转模块!');
    }
    if ($menu['url_type'] == 'link') {
        $this->success('登录成功', $menu['url_value']);
    }
    $menu_url = explode('/', $menu['url_value']);
    role_auth();
    $url = action('admin/ajax/getSidebarMenu', ['module_id' => $default_module, 'module' => $menu['module'], 'controller' => $menu_url[1]]);
    if ($url == '') {
        $this->error('权限不足');
    } else {
        $this->success('登录成功', $url);
    }
}


# 跳转  # 验证码  # 单点  # 去看  # 请输入  # 不存在  # 有兴趣  # 暂时没有  # 不支持  # 用户可以 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 微信小程序 input输入框控件详解及实例(多种示例)  Laravel如何与Pusher实现实时通信?(WebSocket示例)  C#如何调用原生C++ COM对象详解  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  标准网站视频模板制作软件,现在有哪个网站的视频编辑素材最齐全的,背景音乐、音效等?  EditPlus中的正则表达式 实战(2)  深圳网站制作平台,深圳市做网站好的公司有哪些?  javascript基于原型链的继承及call和apply函数用法分析  浅谈redis在项目中的应用  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控  JS去除重复并统计数量的实现方法  如何在IIS管理器中快速创建并配置网站?  音乐网站服务器如何优化API响应速度?  消息称 OpenAI 正研发的神秘硬件设备或为智能笔,富士康代工  宙斯浏览器怎么屏蔽图片浏览 节省手机流量使用设置方法  Laravel如何优雅地处理服务层_在Laravel中使用Service层和Repository层  Linux安全能力提升路径_长期防护思维说明【指导】  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  java ZXing生成二维码及条码实例分享  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  Bootstrap整体框架之JavaScript插件架构  Laravel如何实现API资源集合?(Resource Collection教程)  弹幕视频网站制作教程下载,弹幕视频网站是什么意思?  Laravel项目如何进行性能优化_Laravel应用性能分析与优化技巧大全  如何在景安服务器上快速搭建个人网站?  php结合redis实现高并发下的抢购、秒杀功能的实例  网站建设整体流程解析,建站其实很容易!  Laravel如何使用Eloquent ORM进行数据库操作?(CRUD示例)  b2c电商网站制作流程,b2c水平综合的电商平台?  google浏览器怎么清理缓存_谷歌浏览器清除缓存加速详细步骤  Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  如何快速搭建高效香港服务器网站?  如何用花生壳三步快速搭建专属网站?  Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制  Laravel怎么使用Blade模板引擎_Laravel模板继承与Component组件复用【手册】  Windows11怎样设置电源计划_Windows11电源计划调整攻略【指南】  Laravel如何集成微信支付SDK_Laravel使用yansongda-pay实现扫码支付【实战】  Laravel广播系统如何实现实时通信_Laravel Reverb与WebSockets实战教程  浅谈javascript alert和confirm的美化  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  Laravel API资源(Resource)怎么用_格式化Laravel API响应的最佳实践  Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  浅谈Javascript中的Label语句  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  中山网站制作网页,中山新生登记系统登记流程?  微信小程序 canvas开发实例及注意事项  香港服务器租用每月最低只需15元?