Files
BESCMS/dayrui/App/Member/Controllers/Login.php
T

495 lines
24 KiB
PHP

<?php namespace Phpcmf\Controllers;
class Login extends \Phpcmf\Common
{
/**
* 初始化
*/
public function __construct($object = NULL)
{
parent::__construct();
if ($object) {
foreach ($object as $var => $value) {
$this->$var = $value;
}
}
}
// 正常登录
public function index() {
// 获取返回页面
$url = dr_safe_url($_GET['back'] ? urldecode((string)\Phpcmf\Service::L('input')->get('back')) : $_SERVER['HTTP_REFERER']);
if (strpos($url, 'login') !== false || strpos($url, 'register') !== false) {
$url = MEMBER_URL; // 当来自登录或注册页面时返回到用户中心去
} else {
$url = str_ireplace(['<iframe', '<', '/>'], '', $url);
}
// 判断重复登录
if ($this->uid) {
if (IS_POST) {
$this->_json(0, dr_lang('请退出登录账号再操作'));
}
$url = $url ? dr_redirect_safe_check($url) : MEMBER_URL;
if (IS_DEV) {
\Phpcmf\Service::C()->_admin_msg(1, '开发者模式:已经登录过了<br>正在自动跳转到用户中心(关闭开发者模式时即可自动跳转)', $url, 9);
} else {
dr_redirect($url);exit;
}
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$back = dr_redirect_safe_check((string)\Phpcmf\Service::L('input')->xss_clean($_POST['back'] ? \Phpcmf\Service::L('input')->post('back') : MEMBER_URL, true));
$back = str_ireplace(['<iframe', '<', '/>'], '', $back);
// 回调钩子
\Phpcmf\Hooks::trigger('member_login_before', $post);
if ($this->member_cache['login']['code']
&& !\Phpcmf\Service::L('Form')->check_captcha('code')) {
$this->_json(0, dr_lang('图片验证码不正确'));
} elseif (empty($post['password'])) {
$this->_json(0, dr_lang('密码必须填写'));
} elseif (empty($post['username'])) {
$this->_json(0, dr_lang('账号必须填写'));
} else {
$rt = \Phpcmf\Service::M('member')->login(dr_safe_username($post['username']), $post['password'], (int)$_POST['remember']);
if ($rt['code']) {
// 登录成功
$rt['data']['url'] = urldecode($back);
return $this->_json(1, dr_lang('登录成功'), $rt['data'], true);
} else {
$this->_json(0, $rt['msg']);
}
}
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(['back' => htmlspecialchars($url)]),
'is_code' => $this->member_cache['login']['code'],
'is_register' => $this->member_cache['register']['close'] ? 0 : 1,
'meta_name' => dr_lang('用户登录'),
'meta_title' => dr_lang('用户登录').SITE_SEOJOIN.SITE_NAME,
]);
return \Phpcmf\Service::V()->display('login.html');
}
// 短信验证码登录
public function sms() {
// 获取返回页面
$url = dr_safe_url($_GET['back'] ? urldecode((string)\Phpcmf\Service::L('input')->get('back')) : $_SERVER['HTTP_REFERER']);
strpos($url, 'login') !== false && $url = MEMBER_URL;
$is_img_code = $this->member_cache['login']['code'];
// 当关闭图形验证码时,启用短信图形验证时,再次开启图形验证
if (!$this->member_cache['login']['code'] && $this->member_cache['login']['sms'] && !SYS_SMS_IMG_CODE) {
$is_img_code = 1;
}
if (IS_AJAX_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$back = dr_redirect_safe_check(\Phpcmf\Service::L('input')->xss_clean($_POST['back'] ? \Phpcmf\Service::L('input')->post('back') : MEMBER_URL));
\Phpcmf\Hooks::trigger('member_login_before', $post);
if ($is_img_code && !\Phpcmf\Service::L('Form')->check_captcha('code')) {
$this->_json(0, dr_lang('图片验证码不正确'));
} elseif (empty($post['phone'])) {
$this->_json(0, dr_lang('手机号码必须填写'));
} else {
$sms = \Phpcmf\Service::L('Form')->get_mobile_code($post['phone']);
if (!$sms) {
$this->_json(0, dr_lang('未发送手机验证码'), ['field' => 'sms']);
} elseif (!$_POST['sms']) {
$this->_json(0, dr_lang('手机验证码未填写'), ['field' => 'sms']);
} elseif ($sms != trim($_POST['sms'])) {
$this->_json(0, dr_lang('手机验证码不正确'), ['field' => 'sms']);
} else {
$rt = \Phpcmf\Service::M('member')->login_sms($post['phone'], (int)$_POST['remember']);
if ($rt['code']) {
// 登录成功
$rt['data']['url'] = urldecode($back);
return $this->_json(1, 'ok', $rt['data'], true);
} else {
$this->_json(0, $rt['msg']);
}
}
}
} else {
$this->_json(0, dr_lang('提交方式不正确'));
}
}
/**
* 授权登录
*/
public function oauth() {
$id = intval(\Phpcmf\Service::L('input')->get('id'));
$name = dr_safe_replace(\Phpcmf\Service::L('input')->get('name'));
$auth_name = 'member_auth_login_'.$name.'_'.$id;
$oauth_id = \Phpcmf\Service::L('cache')->get_auth_data($auth_name, SITE_ID, 300);
if (!$oauth_id && !IS_XRDEV) {
// 需要加强判断条件
$this->_msg(0, IS_DEV ? dr_lang('授权信息(%s)获取失败', $name) : dr_lang('授权信息获取失败'));
}
$oauth = \Phpcmf\Service::M()->table('member_oauth')->get($oauth_id);
if (!$oauth && !IS_XRDEV) {
$this->_msg(0, dr_lang('授权信息(#%s)不存在', $oauth_id));
}
// 查询关联用户
$member = [];
if ($oauth['uid']) {
$member = \Phpcmf\Service::M('member')->get_member($oauth['uid']);
} elseif ($oauth['unionid']) {
$row = \Phpcmf\Service::M()->table('member_oauth')->where('unionid', $oauth['unionid'])->where('uid>0')->getRow();
if ($row) {
// 直接绑定unionid用户
\Phpcmf\Service::M()->table('member_oauth')->update($oauth['id'], [
'uid' => $row['uid']
]);
$member = \Phpcmf\Service::M('member')->get_member($row['uid']);
}
}
// 跳转地址
$back = urldecode(dr_redirect_safe_check(dr_safe_replace((string)\Phpcmf\Service::L('input')->get('back'))));
$state = \Phpcmf\Service::L('input')->get('state');
$goto_url = $back ? $back : MEMBER_URL;
if ($state && $state != 'member') {
$goto_url = strpos($state, 'http') === 0 ? $state : OAUTH_URL.'index.php?s=weixin&c='.$state.'&oid='.$oauth['oid'];
}
if ($member) {
// 已经绑定,直接登录
$sso = '';
$member['uid'] = $oauth['uid'];
$rt = \Phpcmf\Service::M('member')->login_oauth($name, $member);
foreach ($rt as $url) {
$sso.= '<script src="'.$url.'"></script>';
}
// 删除认证缓存
\Phpcmf\Service::L('cache')->del_auth_data($auth_name);
if (strpos($goto_url, 'is_admin_call')) {
// 存储后台回话
\Phpcmf\Service::M('auth')->save_login_auth($name, $member['uid']);
$goto_url.= '&name='.$name.'&uid='.$member['uid'];
return $this->_admin_msg(1, dr_lang('欢迎回来').$sso, \Phpcmf\Service::L('input')->xss_clean($goto_url), 0, true);
} else {
return $this->_msg(1, dr_lang('欢迎回来').$sso, \Phpcmf\Service::L('input')->xss_clean($goto_url), 0, true);
}
} else {
// 来自后台
if (strpos($goto_url, 'is_admin_call')) {
$this->_admin_msg(0, dr_lang('%s,没有绑定本站账号', dr_html2emoji($oauth['nickname'])));
} elseif ($this->member_cache['register']['close']) {
$this->_msg(0, dr_lang('系统关闭了注册功能'));
} elseif (!$this->member_cache['register']['group']) {
$this->_msg(0, dr_lang('系统没有可注册的用户组'));
}
// 验证用户组
$groupid = (int)\Phpcmf\Service::L('input')->get('groupid');
if (!$groupid) {
$groupid = (int)$this->member_cache['register']['groupid'];
if (!$groupid) {
$this->_msg(0, dr_lang('系统没有设置默认注册的用户组'));
}
}
if (!$groupid) {
$this->_msg(0, dr_lang('无效的用户组'));
} elseif (!$this->member_cache['group'][$groupid]['register']) {
$this->_msg(0, dr_lang('该用户组不允许注册'));
}
\Phpcmf\Service::V()->assign([
'id' => $id,
'name' => $name,
'oauth' => $oauth,
'group' => $this->member_cache['group'],
'groupid' => $groupid,
'register' => $this->member_cache['register'],
]);
// 没有绑定账号
if ($this->member_cache['oauth']['login']) {
// 直接登录 就直接创建账号
if ($this->member_cache['register']['group'] && dr_count($this->member_cache['register']['group']) > 1) {
// 多个组需要选择
if (IS_POST) {
$groupid = (int)\Phpcmf\Service::L('input')->post('groupid');
if (!$this->member_cache['group'][$groupid]['register']) {
$this->_json(0, dr_lang('该用户组不允许注册'));
}
// 注册
$rt = \Phpcmf\Service::M('member')->register_oauth($groupid, $oauth);
if ($rt['code']) {
// 登录成功
$rt['data']['url'] = \Phpcmf\Service::L('input')->xss_clean($goto_url);
// 删除认证缓存
\Phpcmf\Service::L('cache')->del_auth_data($auth_name);
if (dr_is_app('weixin') && $oauth['oauth'] == 'wechat') {
$url = SITE_URL.'index.php?s=weixin&c=go&url='.urlencode($goto_url);
$this->_json(1, dr_lang('登录成功'), ['url' => $url, 'sso' => ''], true);exit;
}
return $this->_json(1, 'ok', $rt['data'], true);
} else {
$this->_json(0, $rt['msg']);
}
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'meta_name' => dr_lang('授权登录'),
'meta_title' => dr_lang('授权登录').SITE_SEOJOIN.SITE_NAME,
]);
\Phpcmf\Service::V()->display('login_select.html');
} else {
// 单个用户组组直接注册
$rt = \Phpcmf\Service::M('member')->register_oauth(0, $oauth);
if ($rt['code']) {
// 登录成功
$rt['data']['url'] = \Phpcmf\Service::L('input')->xss_clean($goto_url);
// 删除认证缓存
\Phpcmf\Service::L('cache')->del_auth_data($auth_name);
$sso = '';
foreach ($rt['data']['sso'] as $url) {
$sso.= '<script src="'.$url.'"></script>';
}
if (dr_is_app('weixin') && $oauth['oauth'] == 'wechat') {
$url = SITE_URL.'index.php?s=weixin&c=go&url='.urlencode($goto_url);
$this->_json(1, dr_lang('登录成功'), ['url' => $url, 'sso' => ''], true);exit;
}
return $this->_msg(1, dr_lang('登录成功').$sso, $goto_url, true);
} else {
$this->_msg(0, $rt['msg']);
}
}
} else {
// 绑定账号 绑定已有的账号或者注册新账号
$type = intval(\Phpcmf\Service::L('input')->get('type'));
if ($type) {
// 获取该组可用注册字段
$field = [];
if ($this->member_cache['group'][$groupid]['register_field']) {
foreach ($this->member_cache['group'][$groupid]['register_field'] as $fname) {
$field[$fname] = $this->member_cache['field'][$fname];
$field[$fname]['ismember'] = 1;
}
}
}
if (IS_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
if (!\Phpcmf\Service::L('input')->post('is_protocol')) {
$this->_json(0, dr_lang('你没有同意注册协议'));
}
if ($type) {
// 注册绑定
if (empty($post['password'])) {
$this->_json(0, dr_lang('密码必须填写'), ['field' => 'password']);
} elseif ($post['password'] != $post['password2']) {
$this->_json(0, dr_lang('确认密码不一致'), ['field' => 'password2']);
} else {
// 注册之前的钩子
\Phpcmf\Hooks::trigger('member_register_before', $post);
// 验证操作
if ($this->member_cache['register']['sms']) {
$sms = \Phpcmf\Service::L('Form')->get_mobile_code($post['phone']);
if (!$sms) {
$this->_json(0, dr_lang('未发送手机验证码'), ['field' => 'sms']);
} elseif (!$_POST['sms']) {
$this->_json(0, dr_lang('手机验证码未填写'), ['field' => 'sms']);
} elseif ($sms != (string)$_POST['sms']) {
$this->_json(0, dr_lang('手机验证码不正确'), ['field' => 'sms']);
}
}
// 验证字段
if ($this->member_cache['oauth']['field']) {
list($data, $return, $attach) = \Phpcmf\Service::L('Form')->validation($post, null, $field);
// 输出错误
if ($return) {
$this->_json(0, $return['error'], ['field' => $return['name']]);
}
} else {
$data = [1 => []];
$attach = [];
}
// 入库记录
$rt = \Phpcmf\Service::M('member')->register_oauth_bang($oauth, $groupid, [
'username' => (string)$post['username'],
'phone' => (string)$post['phone'],
'email' => (string)$post['email'],
'password' => dr_safe_password($post['password']),
'name' => dr_safe_replace($post['name']),
], $data[1]);
if ($rt['code']) {
// 注册绑定成功
$this->member = $rt['data'];
\Phpcmf\Service::M('member')->save_cookie($this->member, 1);
// 附件归档
SYS_ATTACHMENT_DB && $attach && \Phpcmf\Service::M('Attachment')->handle(
$this->member['id'],
\Phpcmf\Service::M()->dbprefix('member').'-'.$rt['code'],
$attach
);
// 手机认证成功
if ($this->member_cache['register']['sms']) {
\Phpcmf\Service::M()->db->table('member_data')->where('id', $this->member['id'])->update(['is_mobile' => 1]);
}
$rt['data']['url'] = \Phpcmf\Service::L('input')->xss_clean($goto_url);
// 删除认证缓存
\Phpcmf\Service::L('cache')->del_auth_data($auth_name);
if (dr_is_app('weixin') && $oauth['oauth'] == 'wechat') {
$url = SITE_URL.'index.php?s=weixin&c=go&url='.urlencode($goto_url);
$this->_json(1, dr_lang('绑定成功'), ['url' => $url, 'sso' => ''], true);exit;
}
$this->_json(1, dr_lang('注册成功'), $rt['data'], true);
} else {
$this->_json(0, $rt['msg'], ['field' => $rt['data']['field']]);
}
}
} else {
// 登录绑定
if (empty($post['username']) || empty($post['password'])) {
$this->_json(0, dr_lang('账号或密码必须填写'));
} else {
\Phpcmf\Hooks::trigger('member_login_before', $post);
$rt = \Phpcmf\Service::M('member')->login($post['username'], $post['password'], (int)$_POST['remember']);
if ($rt['code']) {
// 登录成功
$rt['data']['url'] = \Phpcmf\Service::L('input')->xss_clean($goto_url);
// 删除认证缓存
\Phpcmf\Service::L('cache')->del_auth_data($auth_name);
// 删除旧账号
\Phpcmf\Service::M()->db->table('member_oauth')->where('oauth', $oauth['oauth'])->where('uid', $rt['data']['member']['id'])->delete();
// 更改状态
\Phpcmf\Service::M()->db->table('member_oauth')->where('id', $oauth['id'])->update(['uid' => $rt['data']['member']['id']]);
if (dr_is_app('weixin') && $oauth['oauth'] == 'wechat') {
\Phpcmf\Service::M()->db->table('weixin_user')->where('openid', $oauth['oid'])->update([
'uid' => $rt['data']['member']['id'],
'username' => $rt['data']['member']['username'],
]);
$url = SITE_URL.'index.php?s=weixin&c=go&url='.urlencode($goto_url);
$this->_json(1, dr_lang('绑定成功'), ['url' => $url, 'sso' => ''], true);exit;
}
$this->_json(1, dr_lang('绑定成功'), $rt['data'], true);
} else {
$this->_json(0, $rt['msg']);
}
}
}
exit;
}
$is_img_code = $this->member_cache['register']['code'];
// 当关闭图形验证码时,启用短信图形验证时,再次开启图形验证
if (!$this->member_cache['register']['code'] && $this->member_cache['register']['sms'] && !SYS_SMS_IMG_CODE) {
$is_img_code = 1;
}
\Phpcmf\Service::V()->assign([
'type' => $type,
'form' => dr_form_hidden(['type' => $type]),
'myfield' => $type && $this->member_cache['oauth']['field'] ? \Phpcmf\Service::L('field')->toform(0, $field) : '',
'register' => $this->member_cache['register'],
'meta_name' => dr_lang('绑定账号'),
'meta_title' => dr_lang('绑定账号').SITE_SEOJOIN.SITE_NAME,
'is_img_code' => $is_img_code,
]);
\Phpcmf\Service::V()->display('login_oauth.html');
}
}
exit;
}
/**
* 找回密码
*/
public function find() {
if (IS_POST) {
$post = \Phpcmf\Service::L('input')->post('data');
$value = dr_safe_replace($post['value']);
if (strpos($value, '@') !== false) {
// 邮箱模式
$data = \Phpcmf\Service::M()->db->table('member')->where('email', $value)->get()->getRowArray();
if (!$data) {
$this->_json(0, dr_lang('账号凭证不存在'), ['field' => 'value']);
}
} elseif (is_numeric($value) && strlen($value) == 11) {
// 手机
$data = \Phpcmf\Service::M()->db->table('member')->where('phone', $value)->get()->getRowArray();
if (!$data) {
$this->_json(0, dr_lang('账号凭证不存在'), ['field' => 'value']);
}
} else {
$this->_json(0, dr_lang('账号凭证格式不正确'), ['field' => 'value']);
}
// 防止验证码猜测
if (dr_is_app('xrsafe')) {
// 如果安装迅睿安全插件,进入插件验证机制
\Phpcmf\Service::M('safe', 'xrsafe')->find_check($value);
} else {
// 普通验证
$sn = 'fc_pass_find_'.date('Ymd', SYS_TIME).$value;
$count = (int)\Phpcmf\Service::L('cache')->get_data($sn);
if ($count > 20) {
$this->_json(0, dr_lang('今日找回密码次数达到上限'));
}
\Phpcmf\Service::L('cache')->set_data($sn, $count + 1, 3600 * 24);
}
if ((!$post['code'] || !$data['randcode'] || $post['code'] != $data['randcode'])) {
$this->_json(0, dr_lang('凭证验证码不正确'), ['field' => 'code']);
} elseif (!$post['password']) {
$this->_json(0, dr_lang('密码不能为空'), ['field' => 'password']);
} elseif ($post['password'] != $post['password2']) {
$this->_json(0, dr_lang('两次密码不一致'), ['field' => 'password2']);
}
// 修改密码
\Phpcmf\Service::M('member')->edit_password($data, $post['password']);
\Phpcmf\Service::M()->db->table('member')->where('id', $data['id'])->update(['randcode' => 0]);
$this->_json(-1, dr_lang('账号[%s]密码修改成功', $data['username']), $data);
}
\Phpcmf\Service::V()->assign([
'form' => dr_form_hidden(),
'api_url' => dr_member_url('api/find_code'),
'meta_name' => dr_lang('找回密码'),
'meta_title' => dr_lang('找回密码').SITE_SEOJOIN.SITE_NAME,
]);
\Phpcmf\Service::V()->display('find.html');
}
/**
* 退出
*/
public function out() {
// 注销授权登陆的会员
if ($this->session()->get('member_auth_uid')) {
\Phpcmf\Service::C()->session()->delete('member_auth_uid');
$this->_json(0, dr_lang('当前状态无法退出账号'));
}
$this->_json(1, dr_lang('您的账号已退出系统'), [
'url' => dr_safe_url(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : SITE_URL),
'sso' => \Phpcmf\Service::M('member')->logout(),
]);
}
}