<?php
namespace tools;
use crypt\Crypt;
use crypt\SafeCookie;
use think\Db;
use think\Config;
use think\Session;
use think\Cookie;
use think\Request;
use think\Loader;
use app\admin\model\AdminLogs;
class AdminAuth
{
protected $request;
protected $config = [
'auth_on' => 1, 'auth_type' => 1, 'auth_group' => 'admin_groups', 'auth_group_access' => 'auth_group_access', 'auth_rule' => 'admin_menus', 'auth_user' => 'admin_users', ];
static $crypt_key;
public function __construct()
{
if ($auth = Config::get('admin_auth')) {
$this->config = array_merge($this->config, $auth);
}
$this->request = Request::instance();
$this->param = $this->request->param();
$this->module = $this->request->module();
$this->controller = $this->request->controller();
$this->action = $this->request->action();
self::$crypt_key = Config::get('app_key') != null ? Config::get('app_key') : 'beautiful_taoqi';
}
public function check($name, $uid, $relation = 'or', $type = 1, $mode = 'url')
{
if (Session::get('user.user_id') == 1) {
return true;
}
if (!$this->config['auth_on']) {
return true;
}
$authList = $this->getAuthList($uid, $type);
if (is_string($name)) {
$name = strtolower($name);
if (strpos($name, ',') !== false) {
$name = explode(',', $name);
} else {
$name = [$name];
}
}
$list = []; $REQUEST = '';
if ('url' == $mode) {
$REQUEST = unserialize(strtolower(serialize($this->request->param())));
}
foreach ($authList as $auth) {
$query = preg_replace('/^.+\?/U', '', $auth);
if ('url' == $mode && $query != $auth) {
parse_str($query, $param); $intersect = array_intersect_assoc($REQUEST, $param);
$auth = preg_replace('/\?.*$/U', '', $auth);
if (in_array($auth, $name) && $intersect == $param) {
$list[] = $auth;
}
} else {
if (in_array($auth, $name)) {
$list[] = $auth;
}
}
}
if ('or' == $relation && !empty($list)) {
return true;
}
$diff = array_diff($name, $list);
if ('and' == $relation && empty($diff)) {
return true;
}
return false;
}
public function getGroups($uid)
{
static $groups = [];
if (isset($groups[$uid])) {
return $groups[$uid];
}
$type = Config::get('database.prefix') ? 1 : 0;
$auth_group_access = Loader::parseName($this->config['auth_group_access'], $type);
$auth_group = Loader::parseName($this->config['auth_group'], $type);
$user_groups = Db::view($auth_group_access, 'uid,group_id')
->view($auth_group, 'name,rules', "{$auth_group_access}.group_id={$auth_group}.id", 'LEFT')
->where("{$auth_group_access}.uid='{$uid}' and {$auth_group}.status=1")
->select();
$groups[$uid] = $user_groups ?: [];
return $groups[$uid];
}
protected function getAuthList($uid, $type)
{
static $_authList = []; $t = implode(',', (array)$type);
if (isset($_authList[$uid . $t])) {
return $_authList[$uid . $t];
}
if (2 == $this->config['auth_type'] && Session::has('_auth_list_' . $uid . $t)) {
return Session::get('_auth_list_' . $uid . $t);
}
$groups = $this->getGroups($uid);
$ids = []; foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authList[$uid . $t] = [];
return [];
}
$map = array(
'id' => ['in', $ids],
'type' => $type,
'status' => 1,
);
$rules = Db::name($this->config['auth_rule'])->where($map)->field('condition,url')->select();
$authList = []; foreach ($rules as $rule) {
if (!empty($rule['condition'])) {
$user = $this->getUserInfo($uid); $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
$condition = '';
@(eval('$condition=(' . $command . ');'));
if ($condition) {
$authList[] = strtolower($rule['url']);
}
} else {
$authList[] = strtolower($rule['url']);
}
}
$_authList[$uid . $t] = $authList;
if (2 == $this->config['auth_type']) {
Session::set('_auth_list_' . $uid . $t, $authList);
}
return array_unique($authList);
}
protected function getUserInfo($id)
{
static $userinfo = [];
$user = Db::name($this->config['auth_user']);
$_pk = is_string($user->getPk()) ? $user->getPk() : 'id';
if (!isset($userinfo[$id])) {
$userinfo[$id] = $user->where($_pk, $id)->find();
}
return $userinfo[$id];
}
public static function login($id, $name, $remember = false)
{
if (empty($id) && empty($name)) {
return false;
}
$user = [
'id' => $id,
'name' => $name,
'timestamp' => time()
];
Session::set('user', $user);
Session::set('user_sign', self::data_auth_sign($user));
if ($remember == true) {
SafeCookie::set('user', $user);
SafeCookie::set('user_sign', self::data_auth_sign($user));
} else {
if (Cookie::has('user') || Cookie::has('user_sign')) {
Cookie::delete('user');
Cookie::delete('user_sign');
}
}
return true;
}
public static function logout()
{
Session::delete('user');
Session::delete('user_sign');
if (Cookie::has('user')) {
Cookie::delete('user');
Cookie::delete('user_sign');
}
return true;
}
public static function is_login()
{
$user = Session::get('user');
if (empty($user)) {
if (Cookie::has('user') && Cookie::has('user_sign')) {
$user = SafeCookie::get('user');
$user_sign = SafeCookie::get('user_sign');
$is_sin = $user_sign == self::data_auth_sign($user) ? $user : false;
if ($is_sin) {
Session::set('user', $user);
Session::set('user_sign', $user_sign);
return true;
}
}
return false;
}
return Session::get('user_sign') == self::data_auth_sign($user) ? $user : false;
}
public function createLog($title, $log_type, $resource_id=0)
{
$user_id = Session::get('user.id');
$data = [
'user_id' => $user_id,
'title' => $title,
'resource_id' => $resource_id,
'log_type' => $log_type,
'log_url' => $this->request->pathinfo(),
'log_ip' => ip2long($this->request->ip())
];
$crypt_data = Crypt::encrypt(serialize($this->request->param()), self::$crypt_key);
$log_data = [
'data' => $crypt_data
];
$log = AdminLogs::create($data);
if ($log) {
return $log->adminLogData()->save($log_data);
}
return false;
}
private static function data_auth_sign($data)
{
$code = http_build_query($data); $sign = sha1($code); return $sign;
}
public function getMenuList($uid, $type)
{
static $_authList = []; $t = implode(',', (array)$type);
if (isset($_authList[$uid . $t])) {
return $_authList[$uid . $t];
}
if (2 == $this->config['auth_type'] && Session::has('_auth_list_' . $uid . $t)) {
return Session::get('_auth_list_' . $uid . $t);
}
$groups = $this->getGroups($uid);
$ids = []; foreach ($groups as $g) {
$ids = array_merge($ids, explode(',', trim($g['rules'], ',')));
}
$ids = array_unique($ids);
if (empty($ids)) {
$_authList[$uid . $t] = [];
return [];
}
$map = array(
'id' => ['in', $ids],
'type' => $type,
'status' => 1,
);
$rules = Db::name($this->config['auth_rule'])->where($map)->field('condition,url,id')->select();
$authList = []; foreach ($rules as $rule) {
if (!empty($rule['condition'])) {
$user = $this->getUserInfo($uid); $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']);
$condition = '';
@(eval('$condition=(' . $command . ');'));
if ($condition) {
$authList[] = strtolower($rule['id']);
}
} else {
$authList[] = strtolower($rule['id']);
}
}
$_authList[$uid . $t] = $authList;
if (2 == $this->config['auth_type']) {
Session::set('_auth_list_' . $uid . $t, $authList);
}
$authList = array_unique($authList);
$idss = []; foreach ($authList as $gg) {
$idss = array_merge($idss, explode(',', trim($gg, ',')));
}
$map_menu = ['is_show' => 1];
$uid = Session::get('user.id');
if($uid<>1){
$map_menu['id'] = ['in', $idss];
}
return Db::name('admin_menus')->where($map_menu)->order('sort_id asc,id asc')->field('id,title,url,icon,is_show,parent_id')->column('*', 'id');
}
}