From 45b84424e8e1e57ee13d7bca7d32073f1693a956 Mon Sep 17 00:00:00 2001 From: Karson Date: Sat, 10 Mar 2018 00:54:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E9=82=AE=E7=AE=B1=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E7=A0=81=E5=8A=9F=E8=83=BD=20=E6=96=B0=E5=A2=9EToken?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E6=9C=89=E6=95=88=E6=9C=9F=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9EToken=E6=A3=80=E6=B5=8B=E5=92=8C=E5=88=B7=E6=96=B0API?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=20=E6=96=B0=E5=A2=9E=E5=89=8D=E5=8F=B0?= =?UTF-8?q?=E5=8F=91=E9=80=81=E9=AA=8C=E8=AF=81=E7=A0=81=E4=BA=8B=E4=BB=B6?= =?UTF-8?q?=E7=9B=91=E5=90=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复修改个人资料时跳转的BUG 修复API文档Token设置无效的BUG 修复后台移除左侧链接后菜单消失的BUG 优化前台样式CSS,精简多余的CSS 优化会员登录注册视图模板 --- .../admin/command/Api/template/index.html | 2 +- .../admin/command/Install/fastadmin.sql | 19 +- application/api/controller/Ems.php | 123 ++ application/api/controller/Sms.php | 2 +- application/api/controller/Token.php | 45 + application/api/controller/User.php | 69 +- application/api/controller/Validate.php | 59 +- application/common/library/Auth.php | 7 +- application/common/library/Ems.php | 144 ++ application/common/library/Sms.php | 5 +- application/common/model/Ems.php | 22 + application/common/model/Token.php | 10 + application/config.php | 2 +- application/index/controller/User.php | 42 +- application/index/lang/zh-cn/user.php | 3 +- application/index/view/layout/common.html | 5 +- application/index/view/layout/default.html | 7 +- application/index/view/user/login.html | 86 +- application/index/view/user/profile.html | 128 +- application/index/view/user/register.html | 10 +- public/api.html | 1956 +++++++++++------ public/assets/css/backend.css | 29 + public/assets/css/backend.min.css | 2 +- public/assets/css/frontend.css | 275 +-- public/assets/css/frontend.min.css | 2 +- public/assets/js/backend/index.js | 2 +- public/assets/js/fast.js | 2 +- public/assets/js/frontend.js | 42 +- public/assets/js/frontend/user.js | 64 +- public/assets/js/require-backend.min.js | 2 +- public/assets/js/require-frontend.min.js | 44 +- public/assets/less/backend.less | 28 + public/assets/less/frontend.less | 288 +-- 33 files changed, 2288 insertions(+), 1238 deletions(-) create mode 100644 application/api/controller/Ems.php create mode 100644 application/api/controller/Token.php create mode 100644 application/common/library/Ems.php create mode 100644 application/common/model/Ems.php diff --git a/application/admin/command/Api/template/index.html b/application/admin/command/Api/template/index.html index 4a433b04..264eae1c 100644 --- a/application/admin/command/Api/template/index.html +++ b/application/admin/command/Api/template/index.html @@ -413,7 +413,7 @@ var token = $('#token').val(); if (token.length > 0) { - headers[token] = token; + headers['token'] = token; } $("#sandbox" + theId + " .headers input[type=text]").each(function () { diff --git a/application/admin/command/Install/fastadmin.sql b/application/admin/command/Install/fastadmin.sql index cffeab3a..8ec0f2f5 100755 --- a/application/admin/command/Install/fastadmin.sql +++ b/application/admin/command/Install/fastadmin.sql @@ -337,6 +337,21 @@ INSERT INTO `fa_config` VALUES (16, 'mail_verify_type', 'email', 'Mail vertify t INSERT INTO `fa_config` VALUES (17, 'mail_from', 'email', 'Mail from', '', 'string', '10000@qq.com', '', '', ''); COMMIT; +-- ---------------------------- +-- Table structure for fa_ems +-- ---------------------------- +DROP TABLE IF EXISTS `fa_ems`; +CREATE TABLE `fa_ems` ( + `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'ID', + `event` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '事件', + `email` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '邮箱', + `code` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '验证码', + `times` int(10) UNSIGNED NOT NULL DEFAULT 0 COMMENT '验证次数', + `ip` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT 'IP', + `createtime` int(10) UNSIGNED NULL DEFAULT 0 COMMENT '创建时间', + PRIMARY KEY (`id`) USING BTREE +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='邮箱验证码表'; + -- ---------------------------- -- Table structure for fa_sms -- ---------------------------- @@ -412,8 +427,8 @@ CREATE TABLE `fa_user` ( `avatar` varchar(255) NOT NULL DEFAULT '' COMMENT '头像', `level` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '等级', `gender` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '性别', - `birthday` date NOT NULL COMMENT '生日', - `bio` varchar(100) NOT NULL COMMENT '格言', + `birthday` date COMMENT '生日', + `bio` varchar(100) NOT NULL DEFAULT '' COMMENT '格言', `score` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '积分', `successions` int(10) unsigned NOT NULL DEFAULT '1' COMMENT '连续登录天数', `maxsuccessions` int(10) unsigned NOT NULL DEFAULT '1' COMMENT '最大连续登录天数', diff --git a/application/api/controller/Ems.php b/application/api/controller/Ems.php new file mode 100644 index 00000000..b9c772ba --- /dev/null +++ b/application/api/controller/Ems.php @@ -0,0 +1,123 @@ +to($params->email) + ->subject('验证码') + ->message("你的验证码是:" . $params->code) + ->send(); + return $result; + }); + } + + /** + * 发送验证码 + * + * @param string $email 邮箱 + * @param string $event 事件名称 + */ + public function send() + { + $email = $this->request->request("email"); + $event = $this->request->request("event"); + $event = $event ? $event : 'register'; + + $last = Emslib::get($email, $event); + if ($last && time() - $last['createtime'] < 60) + { + $this->error(__('发送频繁')); + } + if ($event) + { + $userinfo = User::getByEmail($email); + if ($event == 'register' && $userinfo) + { + //已被注册 + $this->error(__('已被注册')); + } + else if (in_array($event, ['changeemail']) && $userinfo) + { + //被占用 + $this->error(__('已被占用')); + } + else if (in_array($event, ['changepwd', 'resetpwd']) && !$userinfo) + { + //未注册 + $this->error(__('未注册')); + } + } + $ret = Emslib::send($email, NULL, $event); + if ($ret) + { + $this->success(__('发送成功')); + } + else + { + $this->error(__('发送失败')); + } + } + + /** + * 检测验证码 + * + * @param string $email 邮箱 + * @param string $event 事件名称 + * @param string $captcha 验证码 + */ + public function check() + { + $email = $this->request->request("email"); + $event = $this->request->request("event"); + $event = $event ? $event : 'register'; + $captcha = $this->request->request("captcha"); + + if ($event) + { + $userinfo = User::getByEmail($email); + if ($event == 'register' && $userinfo) + { + //已被注册 + $this->error(__('已被注册')); + } + else if (in_array($event, ['changeemail']) && $userinfo) + { + //被占用 + $this->error(__('已被占用')); + } + else if (in_array($event, ['changepwd', 'resetpwd']) && !$userinfo) + { + //未注册 + $this->error(__('未注册')); + } + } + $ret = Emslib::check($email, $captcha, $event); + if ($ret) + { + $this->success(__('成功')); + } + else + { + $this->error(__('验证码不正确')); + } + } + +} diff --git a/application/api/controller/Sms.php b/application/api/controller/Sms.php index 5e558c42..5fc2e348 100644 --- a/application/api/controller/Sms.php +++ b/application/api/controller/Sms.php @@ -7,7 +7,7 @@ use app\common\library\Sms as Smslib; use app\common\model\User; /** - * 短信接口 + * 手机短信接口 */ class Sms extends Api { diff --git a/application/api/controller/Token.php b/application/api/controller/Token.php new file mode 100644 index 00000000..fb6f4e42 --- /dev/null +++ b/application/api/controller/Token.php @@ -0,0 +1,45 @@ +auth->getToken(); + $tokenInfo = \app\common\library\Token::get($token); + $this->success('', ['token' => $tokenInfo['token'], 'expires_in' => $tokenInfo['expires_in']]); + } + + /** + * 刷新Token + * + */ + public function refresh() + { + $token = $this->auth->getToken(); + $tokenInfo = \app\common\library\Token::get($token); + $tokenInfo->expiretime = time() + 2592000; + $tokenInfo->save(); + $this->success('', ['token' => $tokenInfo['token'], 'expires_in' => $tokenInfo['expires_in']]); + } + +} diff --git a/application/api/controller/User.php b/application/api/controller/User.php index c2ec2652..bd539a05 100644 --- a/application/api/controller/User.php +++ b/application/api/controller/User.php @@ -3,7 +3,7 @@ namespace app\api\controller; use app\common\controller\Api; -use app\common\library\Email; +use app\common\library\Ems; use app\common\library\Sms; use fast\Random; use think\Validate; @@ -179,12 +179,14 @@ class User extends Api * 修改邮箱 * * @param string $email 邮箱 + * @param string $captcha 验证码 */ public function changeemail() { $user = $this->auth->getUser(); $email = $this->request->post('email'); - if (!$email) + $captcha = $this->request->request('captcha'); + if (!$email || !$captcha) { $this->error(__('Invalid parameters')); } @@ -196,17 +198,18 @@ class User extends Api { $this->error(__('Email already exists')); } + $result = Ems::check($email, $captcha, 'changeemail'); + if (!$result) + { + $this->error(__('Captcha is incorrect')); + } $verification = $user->verification; - $verification->email = 0; + $verification->email = 1; $user->verification = $verification; $user->email = $email; $user->save(); - $time = time(); - $code = ['id' => $user->id, 'time' => $time, 'key' => md5(md5($user->id . $user->email . $time) . $user->salt)]; - $code = base64_encode(http_build_query($code)); - $url = url("index/user/activeemail", ['code' => $code], true, true); - $message = __('Verify email') . ":{$url}"; - Email::instance()->to($email)->subject(__('Verify email'))->message($message)->send(); + + Ems::flush($email, 'changeemail'); $this->success(); } @@ -291,29 +294,51 @@ class User extends Api */ public function resetpwd() { + $type = $this->request->request("type"); $mobile = $this->request->request("mobile"); + $email = $this->request->request("email"); $newpassword = $this->request->request("newpassword"); $captcha = $this->request->request("captcha"); - if (!$mobile || !$newpassword || !$captcha) + if (!$newpassword || !$captcha) { $this->error(__('Invalid parameters')); } - if ($mobile && !Validate::regex($mobile, "^1\d{10}$")) + if ($type == 'mobile') { - $this->error(__('Mobile is incorrect')); + if (!Validate::regex($mobile, "^1\d{10}$")) + { + $this->error(__('Mobile is incorrect')); + } + $user = \app\common\model\User::getByMobile($mobile); + if (!$user) + { + $this->error(__('User not found')); + } + $ret = Sms::check($mobile, $captcha, 'resetpwd'); + if (!$ret) + { + $this->error(__('Captcha is incorrect')); + } + Sms::flush($mobile, 'resetpwd'); } - $user = \app\common\model\User::getByMobile($mobile); - if (!$user) + else { - $this->error(__('User not found')); + if (!Validate::is($email, "email")) + { + $this->error(__('Email is incorrect')); + } + $user = \app\common\model\User::getByEmail($email); + if (!$user) + { + $this->error(__('User not found')); + } + $ret = Ems::check($email, $captcha, 'resetpwd'); + if (!$ret) + { + $this->error(__('Captcha is incorrect')); + } + Ems::flush($email, 'resetpwd'); } - $ret = Sms::check($mobile, $captcha, 'resetpwd'); - if (!$ret) - { - $this->error(__('Captcha is incorrect')); - } - Sms::flush($mobile, 'resetpwd'); - //模拟一次登录 $this->auth->direct($user->id); $ret = $this->auth->changepwd($newpassword, '', true); diff --git a/application/api/controller/Validate.php b/application/api/controller/Validate.php index c8a7a017..c950eda4 100644 --- a/application/api/controller/Validate.php +++ b/application/api/controller/Validate.php @@ -24,7 +24,7 @@ class Validate extends Api * 检测邮箱 * * @param string $email 邮箱 - * @param string $id 会员ID + * @param string $id 排除会员ID */ public function check_email_available() { @@ -42,7 +42,7 @@ class Validate extends Api * 检测用户名 * * @param string $username 用户名 - * @param string $id 会员ID + * @param string $id 排除会员ID */ public function check_username_available() { @@ -60,16 +60,16 @@ class Validate extends Api * 检测手机 * * @param string $mobile 手机号 - * @param string $id 会员ID + * @param string $id 排除会员ID */ public function check_mobile_available() { - $email = $this->request->request('mobile'); + $mobile = $this->request->request('mobile'); $id = (int) $this->request->request('id'); - $count = User::where('mobile', '=', $email)->where('id', '<>', $id)->count(); + $count = User::where('mobile', '=', $mobile)->where('id', '<>', $id)->count(); if ($count > 0) { - $this->error(__('已经使用该手机号注册')); + $this->error(__('该手机号已经占用')); } $this->success(); } @@ -81,8 +81,8 @@ class Validate extends Api */ public function check_mobile_exist() { - $email = $this->request->request('mobile'); - $count = User::where('mobile', '=', $email)->count(); + $mobile = $this->request->request('mobile'); + $count = User::where('mobile', '=', $mobile)->count(); if (!$count) { $this->error(__('手机号不存在')); @@ -91,11 +91,27 @@ class Validate extends Api } /** - * 检测验证码 + * 检测邮箱 * - * @param string $mobile 手机号 - * @param string $captcha 验证码 - * @param string $event 事件 + * @param string $mobile 邮箱 + */ + public function check_email_exist() + { + $email = $this->request->request('email'); + $count = User::where('email', '=', $email)->count(); + if (!$count) + { + $this->error(__('邮箱不存在')); + } + $this->success(); + } + + /** + * 检测手机验证码 + * + * @param string $mobile 手机号 + * @param string $captcha 验证码 + * @param string $event 事件 */ public function check_sms_correct() { @@ -109,4 +125,23 @@ class Validate extends Api $this->success(); } + /** + * 检测邮箱验证码 + * + * @param string $email 邮箱 + * @param string $captcha 验证码 + * @param string $event 事件 + */ + public function check_ems_correct() + { + $email = $this->request->request('email'); + $captcha = $this->request->request('captcha'); + $event = $this->request->request('event'); + if (!\app\common\library\Ems::check($email, $captcha, $event)) + { + $this->error(__('验证码不正确')); + } + $this->success(); + } + } diff --git a/application/common/library/Auth.php b/application/common/library/Auth.php index 02c2a068..b4bb7a5d 100644 --- a/application/common/library/Auth.php +++ b/application/common/library/Auth.php @@ -19,7 +19,8 @@ class Auth protected $_logined = FALSE; protected $_user = NULL; protected $_token = ''; - protected $keeptime = 0; + //Token默认有效时长 + protected $keeptime = 2592000; protected $requestUri = ''; protected $rules = []; //默认配置 @@ -203,7 +204,7 @@ class Auth //设置Token $this->_token = Random::uuid(); - Token::set($this->_token, $user->id); + Token::set($this->_token, $user->id, $this->keeptime); //注册成功的事件 Hook::listen("user_register_successed", $this->_user); @@ -349,7 +350,7 @@ class Auth $this->_user = $user; $this->_token = Random::uuid(); - Token::set($this->_token, $user->id); + Token::set($this->_token, $user->id, $this->keeptime); $this->_logined = TRUE; diff --git a/application/common/library/Ems.php b/application/common/library/Ems.php new file mode 100644 index 00000000..a0ed193e --- /dev/null +++ b/application/common/library/Ems.php @@ -0,0 +1,144 @@ + $email, 'event' => $event]) + ->order('id', 'DESC') + ->find(); + Hook::listen('ems_get', $ems, null, true); + return $ems ? $ems : NULL; + } + + /** + * 发送验证码 + * + * @param int $email 邮箱 + * @param int $code 验证码,为空时将自动生成4位数字 + * @param string $event 事件 + * @return boolean + */ + public static function send($email, $code = NULL, $event = 'default') + { + $code = is_null($code) ? mt_rand(1000, 9999) : $code; + $time = time(); + $ip = request()->ip(); + $ems = \app\common\model\Ems::create(['event' => $event, 'email' => $email, 'code' => $code, 'ip' => $ip, 'createtime' => $time]); + $result = Hook::listen('ems_send', $ems, null, true); + if (!$result) + { + $ems->delete(); + return FALSE; + } + return TRUE; + } + + /** + * 发送通知 + * + * @param mixed $email 邮箱,多个以,分隔 + * @param string $msg 消息内容 + * @param string $template 消息模板 + * @return boolean + */ + public static function notice($email, $msg = '', $template = NULL) + { + $params = [ + 'email' => $email, + 'msg' => $msg, + 'template' => $template + ]; + $result = Hook::listen('ems_notice', $params, null, true); + return $result ? TRUE : FALSE; + } + + /** + * 校验验证码 + * + * @param int $email 邮箱 + * @param int $code 验证码 + * @param string $event 事件 + * @return boolean + */ + public static function check($email, $code, $event = 'default') + { + $time = time() - self::$expire; + $ems = \app\common\model\Ems::where(['email' => $email, 'event' => $event]) + ->order('id', 'DESC') + ->find(); + if ($ems) + { + if ($ems['createtime'] > $time && $ems['times'] <= self::$maxCheckNums) + { + $correct = $code == $ems['code']; + if (!$correct) + { + $ems->times = $ems->times + 1; + $ems->save(); + return FALSE; + } + else + { + $result = Hook::listen('ems_check', $ems, null, true); + return TRUE; + } + } + else + { + // 过期则清空该邮箱验证码 + self::flush($email, $event); + return FALSE; + } + } + else + { + return FALSE; + } + } + + /** + * 清空指定邮箱验证码 + * + * @param int $email 邮箱 + * @param string $event 事件 + * @return boolean + */ + public static function flush($email, $event = 'default') + { + \app\common\model\Ems:: + where(['email' => $email, 'event' => $event]) + ->delete(); + Hook::listen('ems_flush'); + return TRUE; + } + +} diff --git a/application/common/library/Sms.php b/application/common/library/Sms.php index 39d3a4b5..7204530a 100644 --- a/application/common/library/Sms.php +++ b/application/common/library/Sms.php @@ -5,7 +5,7 @@ namespace app\common\library; use think\Hook; /** - * 验证码类 + * 短信验证码类 */ class Sms { @@ -51,7 +51,8 @@ class Sms { $code = is_null($code) ? mt_rand(1000, 9999) : $code; $time = time(); - $sms = \app\common\model\Sms::create(['event' => $event, 'mobile' => $mobile, 'code' => $code, 'createtime' => $time]); + $ip = request()->ip(); + $sms = \app\common\model\Sms::create(['event' => $event, 'mobile' => $mobile, 'code' => $code, 'ip' => $ip, 'createtime' => $time]); $result = Hook::listen('sms_send', $sms, null, true); if (!$result) { diff --git a/application/common/model/Ems.php b/application/common/model/Ems.php new file mode 100644 index 00000000..33a32e27 --- /dev/null +++ b/application/common/model/Ems.php @@ -0,0 +1,22 @@ + false, //版本号 - 'version' => '1.0.0.20180308_beta', + 'version' => '1.0.0.20180310_beta', 'api_url' => 'http://api.fastadmin.net', ], ]; diff --git a/application/index/controller/User.php b/application/index/controller/User.php index 265c87f5..b5c4902f 100644 --- a/application/index/controller/User.php +++ b/application/index/controller/User.php @@ -31,8 +31,9 @@ class User extends Frontend //监听注册登录注销的事件 Hook::add('user_login_successed', function($user) use($auth) { - Cookie::set('uid', $user->id); - Cookie::set('token', $auth->getToken()); + $expire = input('post.keeplogin') ? 30 * 86400 : 0; + Cookie::set('uid', $user->id, $expire); + Cookie::set('token', $auth->getToken(), $expire); }); Hook::add('user_register_successed', function($user) use($auth) { Cookie::set('uid', $user->id); @@ -139,7 +140,7 @@ class User extends Frontend { $account = $this->request->post('account'); $password = $this->request->post('password'); - $keeptime = (int) $this->request->post('keeptime'); + $keeplogin = (int) $this->request->post('keeplogin'); $token = $this->request->post('__token__'); $rule = [ 'account' => 'require|length:3,50', @@ -165,7 +166,7 @@ class User extends Frontend $this->error(__($validate->getError())); return FALSE; } - if ($this->auth->login($account, $password, $keeptime)) + if ($this->auth->login($account, $password)) { $synchtml = ''; ////////////////同步到Ucenter//////////////// @@ -262,39 +263,6 @@ class User extends Frontend return $this->view->fetch(); } - /** - * 激活邮箱 - */ - public function activeemail() - { - $code = $this->request->request('code'); - $code = base64_decode($code); - parse_str($code, $params); - if (!isset($params['id']) || !isset($params['time']) || !isset($params['key'])) - { - $this->error(__('Invalid parameters')); - } - $user = \app\common\model\User::get($params['id']); - if (!$user) - { - $this->error(__('User not found')); - } - if ($user->verification->email) - { - $this->error(__('Email already activation')); - } - if ($key !== md5(md5($user->id . $user->email . $time) . $user->salt) || time() - $params['time'] > 1800) - { - $this->error(__('Secrity code already invalid')); - } - $verification = $user->verification; - $verification->email = 1; - $user->verification = $verification; - $user->save(); - $this->success(__('Active email successful'), url('user/index')); - return; - } - /** * 修改密码 */ diff --git a/application/index/lang/zh-cn/user.php b/application/index/lang/zh-cn/user.php index 8eae30b0..ff9eba74 100644 --- a/application/index/lang/zh-cn/user.php +++ b/application/index/lang/zh-cn/user.php @@ -22,7 +22,8 @@ return [ 'Sign up successful' => '注册成功', 'Email active successful' => '邮箱激活成功', 'Username can not be empty' => '用户名不能为空', - 'Username must be 6 to 30 characters' => '用户名必须6-30个字符', + 'Username must be 3 to 30 characters' => '用户名必须3-30个字符', + 'Account must be 3 to 50 characters' => '账户必须3-50个字符', 'Password can not be empty' => '密码不能为空', 'Password must be 6 to 30 characters' => '密码必须6-30个字符', 'Email is incorrect' => '邮箱格式不正确', diff --git a/application/index/view/layout/common.html b/application/index/view/layout/common.html index f833a835..ec235c23 100644 --- a/application/index/view/layout/common.html +++ b/application/index/view/layout/common.html @@ -65,8 +65,9 @@ - - {__CONTENT__} +
+ {__CONTENT__} +