/**
  * Handle an incoming request.
  *
  * @param  \Illuminate\Http\Request  $request
  * @param  \Closure  $next
  * @param  int  $maxAttempts
  * @param  int  $decayMinutes
  * @return mixed
  */
 public function handle($request, Closure $next, $maxAttempts = 60, $decayMinutes = 1)
 {
     $key = $this->resolveRequestSignature($request);
     if ($this->limiter->tooManyAttempts($key, $maxAttempts, $decayMinutes)) {
         return new Response('Too Many Attempts.', 429, ['Retry-After' => $this->limiter->availableIn($key), 'X-RateLimit-Limit' => $maxAttempts, 'X-RateLimit-Remaining' => 0]);
     }
     $this->limiter->hit($key, $decayMinutes);
     return $next($request)->withHeaders(['X-RateLimit-Limit' => $maxAttempts, 'X-RateLimit-Remaining' => $maxAttempts - $this->limiter->attempts($key) + 1]);
 }
 /**
  * Calculate the number of remaining attempts.
  *
  * @param  string  $key
  * @param  int  $maxAttempts
  * @param  int|null  $retryAfter
  * @return int
  */
 protected function calculateRemainingAttempts($key, $maxAttempts, $retryAfter = null)
 {
     if (!is_null($retryAfter)) {
         return 0;
     }
     return $this->limiter->retriesLeft($key, $maxAttempts);
 }
Beispiel #3
0
 public function postSendVerify($type = null, RateLimiter $rateLimiter)
 {
     $user = auth()->user();
     $request = request();
     $response = response();
     if (!$type) {
         $type = $request->input('type');
     }
     if ($type != 'phone' && $type != 'email') {
         $response->json(['status' => false, 'message' => '发送失败,Type参数错误!']);
     }
     $typeValue = $request->input('input_value');
     if ($type == 'email') {
         if ($typeValue == $user->email || !is_email($typeValue) || strlen($typeValue) > 64) {
             return $response->json(['status' => false, 'message' => '请输入正确的新邮箱']);
         }
     } elseif ($type == 'phone') {
         if ($typeValue == $user->phone || !is_phone($typeValue)) {
             return $response->json(['status' => false, 'message' => '请输入正确的新手机号']);
         }
     }
     // 60秒发送一次
     $sessionKey = 'send_verify_last_time';
     $sessionKey .= ".change.{$type}";
     $sessionValue = session($sessionKey);
     $currentTime = time();
     if ($sessionValue && $sessionValue + 60 > $currentTime) {
         return $response->json(['status' => false, 'message' => '发送失败,请不要频繁获取验证码']);
     }
     // 一个IP一个小时可以发送10次
     $rateLimiterKey = 'send_verify_rate_limiter';
     $rateLimiterKey .= ":change:{$type}_" . $user->id;
     if ($rateLimiter->tooManyAttempts($rateLimiterKey, 60, 10)) {
         return $response->json(['status' => false, 'message' => '当前网络环境获取已达上限,请一小时后再试']);
     }
     if (User::hasBeenUsed($type, $typeValue, true)->exists()) {
         $typeName = $type == 'phone' ? '手机号' : '邮箱';
         return $response->json(['status' => false, 'message' => '此' . $typeName . '已被其他用户使用']);
     }
     $code = rand(100000, 999999);
     $value = ['type' => $type, 'code' => $code, 'value' => $typeValue, 'attempt' => 0, 'user_id' => $user->id];
     $cacheKey = md5("send_verify_detail.change.{$typeValue}" . config('key'));
     if ($type == 'phone') {
         require app_path('Services/Taobao/TopSdk.php');
         $status = sendSms('phone_change', $typeValue, ['code' => $code, 'product' => '积木']);
     } elseif ($type == 'email') {
         $vars = ['email' => $typeValue, 'code' => $code, 'link' => url('account/set/change-confirm') . '?key=' . urlencode($cacheKey)];
         $view = 'user.set.change_verify_mail';
         $status = \Mail::send($view, $vars, function ($message) use($typeValue) {
             $message->to($typeValue);
             $message->subject('[积木] 邮箱绑定验证码');
         });
     }
     if (empty($status)) {
         $status = false;
     } else {
         Cache::put($cacheKey, $value, 60);
         session([$sessionKey => $currentTime]);
         $rateLimiter->hit($rateLimiterKey);
     }
     $typeName = $type == 'phone' ? '短信' : '邮件';
     return $response->json(['status' => (bool) $status, 'message' => $status ? '' : 'Oh. 验证' . $typeName . '发送失败,请稍后重试']);
 }
Beispiel #4
0
 /**
  * Calculate the number of remaining attempts.
  *
  * @param  string  $key
  * @param  int  $maxAttempts
  * @return int
  */
 protected function calculateRemainingAttempts($key, $maxAttempts)
 {
     return $maxAttempts - $this->limiter->attempts($key) + 1;
 }
Beispiel #5
0
 /**
  * Clear the login locks for the given user credentials.
  *
  * @return void
  */
 public function clearLoginAttempts()
 {
     $this->cacheLimiter->clear($this->getUniqueLoginKey());
 }
 public function postSendVerify($type = null, RateLimiter $rateLimiter)
 {
     $request = request();
     $response = response();
     if (!$type) {
         $type = $request->input('type');
     }
     if ($type != 'register' && $type != 'forgot_password') {
         $response->json(['status' => false, 'message' => '发送失败,Type参数错误!']);
     }
     $identifier = $request->input('identifier');
     if (!is_email($identifier) || strlen($identifier) > 64) {
         if (!is_phone($identifier)) {
             return $response->json(['status' => false, 'message' => '请输入正确的手机号或邮箱']);
         }
         $verifyType = 'phone';
     } else {
         $verifyType = 'email';
     }
     // 60秒发送一次
     $sessionKey = 'send_verify_last_time';
     $sessionKey .= ".{$type}.{$verifyType}";
     $sessionValue = session($sessionKey);
     $currentTime = time();
     if ($sessionValue && $sessionValue + 60 > $currentTime) {
         return $response->json(['status' => false, 'message' => '发送失败,请不要频繁获取验证码']);
     }
     // 一个IP一个小时可以发送20次
     $rateLimiterKey = 'send_verify_rate_limiter';
     $rateLimiterKey .= ":{$type}:{$verifyType}_" . request()->ip();
     if ($rateLimiter->tooManyAttempts($rateLimiterKey, 60, 20)) {
         return $response->json(['status' => false, 'message' => '当前网络环境获取已达上限,请一小时后再试']);
     }
     if ($type == 'register') {
         if (User::hasBeenUsed($verifyType, $identifier, true)->exists()) {
             $verifyTypeName = $verifyType == 'phone' ? '手机号' : '邮箱';
             $loginUrl = url('account/login', [$identifier]);
             $forgotPasswordUrl = url('account/forgot-password', [$identifier]);
             return $response->json(['status' => false, 'message' => '此' . $verifyTypeName . '已被注册,你可以 <a href="' . $loginUrl . '">尝试登陆</a> 或 <a href="' . $forgotPasswordUrl . '">找回密码</a>']);
         }
     } elseif ($type == 'forgot_password') {
         if (!User::hasBeenUsed($verifyType, $identifier, false)->exists()) {
             $verifyTypeName = $verifyType == 'phone' ? '手机号' : '邮箱';
             $createUrl = url('account/create', [$identifier]);
             return $response->json(['status' => false, 'message' => '此' . $verifyTypeName . '还没注册,<a href="' . $createUrl . '">现在去注册</a>']);
         }
     }
     $code = rand(100000, 999999);
     $value = ['type' => $type, 'code' => $code, 'identifier' => $identifier, 'verify_type' => $verifyType, 'attempt' => 0];
     $cacheKey = md5("send_verify_detail.{$type}.{$identifier}" . config('key'));
     if ($verifyType == 'phone') {
         require app_path('Services/Taobao/TopSdk.php');
         $status = sendSms($type . '_verify', $identifier, ['code' => $code, 'product' => '积木']);
     } elseif ($verifyType == 'email') {
         $action = $type == 'register' ? 'create' : 'forgot-password';
         $vars = ['email' => $identifier, 'code' => $code, 'link' => url('account/' . $action) . '?key=' . urlencode($cacheKey)];
         $view = 'user.account.' . $type . '_verify_mail';
         $subject = $type == 'register' ? '[积木] 账户注册验证码' : '[积木] 账户密码找回验证码';
         $status = \Mail::send($view, $vars, function ($message) use($identifier, $subject) {
             $message->to($identifier);
             $message->subject($subject);
         });
     }
     if (empty($status)) {
         $status = false;
     } else {
         Cache::put($cacheKey, $value, 60);
         session([$sessionKey => $currentTime]);
         $rateLimiter->hit($rateLimiterKey);
     }
     $typeName = $verifyType == 'phone' ? '短信' : '邮件';
     return $response->json(['status' => (bool) $status, 'message' => $status ? '' : 'Oh. 验证' . $typeName . '发送失败,请稍后重试']);
 }