基于 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);
}
}