ChkMobilePwdController.class.php
8.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
<?php
/**
* 检查手机和密码, 并返回匹配记录列表
* Created by IntelliJ IDEA.
* User: zhuxun37
* Date: 2016/7/29
* Time: 15:35
*/
namespace Apicp\Controller\Admin;
use Com\Validator;
use Common\Service\CommonHidemenuService;
use VcySDK\Service;
use VcySDK\Adminer;
class ChkMobilePwdController extends AbstractAnonymousController
{
// 登录最大错误次数
const LOGIN_MAX_ERROR_NUM = 5;
// 不提示错误信息
const NOT_ERROR_MSG = 0;
// 提示错误信息
const SHOW_ERROR_MSG = 1;
// 不能登录
const NOT_LOGIN = 0;
// 可以登录
const LOGIN_ADMIN = 1;
/**
* SDK的Adminer对象
*
* @var Adminer
*/
protected $_adminer;
/**
* 初始化Redis
*
* @var Redis
*/
protected $_redis;
public function before_action($action = '')
{
if (!parent::before_action($action)) {
return false;
}
// 调用UC,登陆接口
$serv_sdk = &Service::instance();
// 实例化
$this->_adminer = new Adminer($serv_sdk);
// 初始化redis
$this->_redis = new \Redis();
$this->_redis->connect(cfg('REDIS_HOST'), cfg('REDIS_PORT'));
$this->_redis->auth(cfg('REDIS_PWD'));
return true;
}
public function Index()
{
// 接收数据
$mobile = I('post.mobile'); // 用户手机
$passwd = I('post.passwd'); // 密码
// 是否报错
$msg_error = $this->get_login_error($mobile);
// 如果显示错误信息
if (self::SHOW_ERROR_MSG == $msg_error['show_msg']) {
E('_ERR_ADMIN_LOGIN_TIME');
}
// 如果是手机号密码登录
$listAdminer = $this->_listAdminer($mobile, $passwd);
// 登录失败
if (empty($listAdminer)) {
// 写入错误数据
$this->set_login_error($mobile);
return false;
}
$this->_redis->set('longin_' . $mobile, serialize(array()));
// 获取菜单列表反序列化输出
$this->_result = $listAdminer;
return true;
}
/**
* 手机号密码登录
*
* @param string $username 手机号码
* @param string $passwd MD5密文密码
*
* @return string|array 登录成功返回ID,否则返回false
*/
protected function _listAdminer($username, $passwd)
{
// 判断是否为手机号码
if (!Validator::is_mobile($username)) {
$this->_set_error("_ERR_PHONE_FORMAT");
return false;
}
// 判断是否为 md5 之后的密码
if (!Validator::is_password($passwd)) {
$this->_set_error("_ERR_PWD_INVALID");
return false;
}
$adminers = array();
try {
// 登录验证
$adminers = $this->_adminer->checkPwd(array(
'eaMobile' => $username,
'eaPassword' => $passwd
));
} catch (\Exception $e) {
}
// 重新检查数据格式, 保证数据格式的正确性
if (!is_array($adminers) || empty($adminers)) {
$this->_set_error("_ERR_ADMINER_NOT_EXIST");
return false;
}
$servHideMenu = new CommonHidemenuService();
// 遍历管理员列表, 反序列化权限字串
foreach ($adminers as $key => &$_adminer) {
// 如果用户信息不存在
if (!isset($_adminer['adminerInfo']) || !is_array($_adminer['adminerInfo'])) {
continue;
}
// 被禁用(过滤企业)
if (isset($_adminer['adminerInfo']['eaUserstatus']) && $_adminer['adminerInfo']['eaUserstatus'] == Adminer::MANAGER_DISABLE_LOGIN) {
unset($adminers[$key]);
}
// 生成登录用token, 用于之后的用户选择指定企业进行登陆的操作
$_adminer['adminerInfo']['loginToken'] = $this->_login->generateLoginToken($_adminer['enterpriseInfo']['epEnumber'], $_adminer['adminerInfo']['eaId'], $passwd);
// 定制企业用户需要隐藏的菜单
$hideMenu = $servHideMenu->getMenus($_adminer['enterpriseInfo']['epEnumber']);
$_adminer['enterpriseInfo']['hideMenu'] = empty($hideMenu['menus']) ? [] : unserialize($hideMenu['menus']);
// 禁用的菜单Key
//$disabled_keys = [];
// FIXME zhonglei 2017年09月27日15:38:08 开哥要求圆圈套件上线时需要隐藏管理后台的一些菜单
$disabled_keys = ['ability-setting', 'clear-cache'];
// 禁用任务中心
if (cfg('TASKCENTER_DISABLED') === true) {
$disabled_keys[] = 'task-center';
}
// 禁用线下培训
if (cfg('TRAIN_DISABLED') === true) {
$disabled_keys[] = 'train';
}
if (!empty($disabled_keys)) {
$hidemenu_keys = array_column($_adminer['enterpriseInfo']['hideMenu'], 'key');
foreach ($disabled_keys as $k) {
if (!in_array($k, $hidemenu_keys)) {
$_adminer['enterpriseInfo']['hideMenu'][] = ['key' => $k];
}
}
}
}
return $adminers;
}
/**
* 获取是否显示错误信息
* @param string $loginToken 手机号
* @return array
*/
protected function get_login_error($loginToken = '')
{
// 初始化
$show_msg = self::NOT_ERROR_MSG;
// 获取错误数据详情
$login_error_info = $this->_redis->get('login_' . $loginToken);
$login_error_info=unserialize($login_error_info);
// 如果首次错误时间不为空
if (!empty($login_error_info['start_time'])) {
// 开始时间+15分钟统计错误次数
$check_time = $login_error_info['start_time'] + 15 * 60 * 1000;
// 最后一次错误时间+1个小时
$max_error_time = $login_error_info['last_time'] + 60 * 60 * 1000;
// 如果当前时间小于首次错误+15分钟且错误次数到达5次或者最后错误时间+1个小时大于当前时间错误次数大于5次
if (($check_time > MILLI_TIME
||
$max_error_time > MILLI_TIME
) &&
$login_error_info['is_login'] == self::NOT_LOGIN
) {
// 显示错误信息
$show_msg = self::SHOW_ERROR_MSG;
}
}
return array('show_msg' => $show_msg, 'data' => $login_error_info);
}
/**
* 记录用户错误信息且保存在redis中
* @param string $loginToken 用户手机号
* @return bool
*/
protected function set_login_error($loginToken = '')
{
// 获取错误数据
$list = $this->get_login_error($loginToken);
// 获取错误数据赋值
$data = $list['data'];
// 首次错误时间+15分钟
$check_time = $data['start_time'] + 15 * 60 * 1000;
// 如果首次登录错误时间+15分钟小于当前时间
if ($check_time <= MILLI_TIME) {
$data['start_time'] = MILLI_TIME;
$data['error_list'] = array();
$data['is_login'] = self::LOGIN_ADMIN;
}
// 最后登录错误时间
$data['last_time'] = MILLI_TIME;
// 初始化错误列表
if (empty($data['error_list'])) {
$data['error_list'] = array();
}
// 赋值错误列表
$error_list= $data['error_list'];
// 记录每次的错误时间
array_push($error_list,MILLI_TIME);
$data['error_list']=$error_list;
// 如果是登录错误次数等于最大错误次数
if (self::LOGIN_MAX_ERROR_NUM == count($data['error_list'])) {
$data['is_login'] = self::NOT_LOGIN;
}
// 写入信息
$this->_redis->set('longin_' . $loginToken, serialize($data));
// 如果是登录错误次数等于最大错误次数
if (self::LOGIN_MAX_ERROR_NUM == count($data['error_list'])) {
E('_ERR_ADMIN_LOGIN_TIME');
}
return true;
}
}