Использование базового TOTP через мобильное приложение вместо существующей реализации второго пароля на javascript.
This commit is contained in:
parent
85b74015b7
commit
244e081014
69
_incl_data/class/Core/TOTP.php
Normal file
69
_incl_data/class/Core/TOTP.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Core;
|
||||
|
||||
readonly class TOTP
|
||||
{
|
||||
private const BASE32CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'; // RFC 4648 Base32
|
||||
|
||||
public function __construct(private string $secret)
|
||||
{
|
||||
}
|
||||
|
||||
public static function otpSecret($uniqueString, $length = 20): string
|
||||
{
|
||||
// Уникальная строка + текущее время в микросекундах
|
||||
$seed = $uniqueString . microtime(true);
|
||||
|
||||
// Хэшируем сид для более случайного распределения
|
||||
$seed = hash('sha256', $seed);
|
||||
|
||||
$secret = '';
|
||||
$max = strlen(self::BASE32CHARS) - 1;
|
||||
|
||||
// Генерируем случайную строку нужной длины
|
||||
for ($i = 0; $i < $length; $i++) {
|
||||
$index = hexdec(substr($seed, $i, 2)) % $max; // Получаем индекс символа из хэшированного сида
|
||||
$secret .= self::BASE32CHARS[$index];
|
||||
}
|
||||
|
||||
return $secret;
|
||||
}
|
||||
|
||||
public function generate(int $digits = 6, int $timeStep = 30): string
|
||||
{
|
||||
$time = floor(time() / $timeStep);
|
||||
$secretKey = $this->base32_decode($this->secret);
|
||||
$binaryTime = pack('N*', 0) . pack('N*', $time);
|
||||
$hash = hash_hmac('sha1', $binaryTime, $secretKey, true);
|
||||
$offset = ord($hash[strlen($hash) - 1]) & 0x0F;
|
||||
$otp = (
|
||||
((ord($hash[$offset]) & 0x7F) << 24) |
|
||||
((ord($hash[$offset + 1]) & 0xFF) << 16) |
|
||||
((ord($hash[$offset + 2]) & 0xFF) << 8) |
|
||||
(ord($hash[$offset + 3]) & 0xFF)
|
||||
) % 10 ** $digits;
|
||||
return str_pad((string)$otp, $digits, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
private function base32_decode(string $input): string
|
||||
{
|
||||
$base32charsFlipped = array_flip(str_split(self::BASE32CHARS));
|
||||
$output = '';
|
||||
$v = 0;
|
||||
$vbits = 0;
|
||||
|
||||
for ($i = 0, $j = strlen($input); $i < $j; $i++) {
|
||||
$v <<= 5;
|
||||
if ($input[$i] == '=') continue;
|
||||
$v += $base32charsFlipped[$input[$i]];
|
||||
$vbits += 5;
|
||||
|
||||
if ($vbits >= 8) {
|
||||
$vbits -= 8;
|
||||
$output .= chr(($v & (0xFF << $vbits)) >> $vbits);
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
}
|
@ -6,30 +6,24 @@ use Core\Config;
|
||||
use Core\Db;
|
||||
use Helper\Mail;
|
||||
use PassGen;
|
||||
use UserIp;
|
||||
|
||||
class Confirmation
|
||||
{
|
||||
/**
|
||||
* Для однотипных писем с подтверждением.
|
||||
* @param array $userinfo Данные из (User)->info.
|
||||
* @param mixed $value Новое значение
|
||||
* @param string $value Новое значение
|
||||
* @param ?int $code Проверочный код
|
||||
* @param string $type Тип меняемого значения. С маленькой буквы, именительный падеж.
|
||||
* @return void
|
||||
*/
|
||||
public static function byEmail(array $userinfo, string $type, $value, ?int $code = null)
|
||||
public static function byEmail(array $userinfo, string $type, string $value, ?int $code = null): void
|
||||
{
|
||||
if ($type === 'pass2' && is_null($code)) {
|
||||
self::pass2ByEmailCustom($userinfo, $value);
|
||||
return;
|
||||
}
|
||||
$ip = UserIp::get();
|
||||
$date = date('d.m.y H:i');
|
||||
$https = Config::get('https');
|
||||
$support = Config::get('support');
|
||||
$activationLink = 'https://' . $userinfo['city'] . Config::get('host') .
|
||||
"/confirm.php?id={$userinfo['id']}&code=$code";
|
||||
$activationLink = Config::get('https') . "/confirm.php?id={$userinfo['id']}&code=$code";
|
||||
$fulllogin = $userinfo['login'] . "[{$userinfo['level']}]";
|
||||
Mail::send(
|
||||
$userinfo['mail'],
|
||||
@ -55,31 +49,7 @@ class Confirmation
|
||||
);
|
||||
}
|
||||
|
||||
private static function pass2ByEmailCustom(array $userinfo, string $pass2)
|
||||
{
|
||||
|
||||
$ip = UserIp::get();
|
||||
$fulllogin = $userinfo['login'] . "[{$userinfo['level']}]";
|
||||
Mail::send(
|
||||
$userinfo['mail'],
|
||||
<<<HTML
|
||||
<html lang="ru">
|
||||
<head><title>Второй пароль от персонажа $fulllogin.</title></head>
|
||||
<body>
|
||||
Вами, с IP адреса - $ip, был установлен второй пароль в игре Бойцовский Клуб.<br>
|
||||
Если это были не Вы, свяжитесь с администрацией сайта.<br><br>
|
||||
------------------------------------------------------------------<br>
|
||||
Ваш логин | {$userinfo['login']}<br>
|
||||
Второй пароль | ' . $pass2 . '<br>
|
||||
------------------------------------------------------------------<br>
|
||||
<br><br>Желаем Вам приятной игры.<br><br><i>Администрация</i>
|
||||
</body>
|
||||
HTML,
|
||||
"Второй пароль от персонажа $fulllogin"
|
||||
);
|
||||
}
|
||||
|
||||
public static function userRegistrationCodeByEmail(string $email, string $login)
|
||||
public static function userRegistrationCodeByEmail(string $email, string $login): void
|
||||
{
|
||||
$code = PassGen::intCode(4);
|
||||
Db::sql('insert into secure_code (email, code, time) values (?,?,unix_timestamp())', [$email, $code]);
|
||||
|
@ -57,28 +57,5 @@ class Password
|
||||
}
|
||||
return $this->info['pass'];
|
||||
}
|
||||
|
||||
public function changeSecond(?int $passLength): array
|
||||
{
|
||||
if (in_array($passLength, [4, 6, 8])) {
|
||||
$query = 'update users set pass2 = ? where id = ?';
|
||||
$pass2 = PassGen::intCode($passLength);
|
||||
$args = [
|
||||
password_hash($pass2, PASSWORD_DEFAULT),
|
||||
$this->info['id'],
|
||||
];
|
||||
Confirmation::byEmail($this->info, 'pass2', $pass2);
|
||||
$hash = $args[0];
|
||||
} else {
|
||||
$query = 'update users set pass2 = default where id = ?';
|
||||
$args = [$this->info['id']];
|
||||
}
|
||||
|
||||
Db::sql($query, $args);
|
||||
return [
|
||||
'pass2' => $pass2 ?? '',
|
||||
'hash' => $hash ?? null,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
|
302
enter.php
302
enter.php
@ -3,6 +3,8 @@
|
||||
use Core\Config;
|
||||
use Core\Database;
|
||||
use Core\Db;
|
||||
use Core\TOTP;
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
use User\Password;
|
||||
use User\UserIp;
|
||||
|
||||
@ -15,43 +17,36 @@ require_once __DIR__ . DIRECTORY_SEPARATOR . '_incl_data/autoload.php';
|
||||
Database::init();
|
||||
|
||||
define('IP', UserIp::get());
|
||||
|
||||
$chat = new Chat();
|
||||
$login = $_SESSION['login'] ?? '';
|
||||
$password = '';
|
||||
$otp = '';
|
||||
|
||||
if (isset($_GET['login'])) {
|
||||
$_POST['login'] = $_GET['login'];
|
||||
$_POST['pass'] = $_GET['pass'];
|
||||
$_POST['code'] = $_GET['code'];
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['login'])) {
|
||||
$login = $_POST['login'];
|
||||
}
|
||||
if (isset($_POST['password'])) {
|
||||
$password = $_POST['password'];
|
||||
}
|
||||
if (isset($_POST['otp'])) {
|
||||
$otp = $_POST['otp'];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['psw'])) {
|
||||
$_POST['pass'] = $_POST['psw'];
|
||||
}
|
||||
|
||||
if (isset($_SESSION['login'])) {
|
||||
$_POST['login'] = $_SESSION['login'];
|
||||
$_POST['pass'] = $_SESSION['pass'];
|
||||
}
|
||||
|
||||
function error($e)
|
||||
#[NoReturn] function error($e): void
|
||||
{
|
||||
die(
|
||||
'
|
||||
<link rel="stylesheet" href="error.css">
|
||||
<div class="text-wrapper">
|
||||
<div class="title" data-content="Ошибка">
|
||||
Ошибка!!
|
||||
$returnLink = Config::get('https');
|
||||
$html = <<<HTML
|
||||
<link rel="stylesheet" href="error.css">
|
||||
<div class="text-wrapper">
|
||||
<div class="title" data-content="Ошибка">Ошибка!!</div>
|
||||
<div class="subtitle">$e</div>
|
||||
<div class="buttons"><a class="button" href="$returnLink">Вернуться назад</a></div>
|
||||
</div>
|
||||
|
||||
<div class="subtitle">
|
||||
' . $e . '
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<a class="button" href="' . Config::get('https') . '">Вернуться назад</a>
|
||||
</div>
|
||||
</div>
|
||||
'
|
||||
);
|
||||
HTML;
|
||||
exit($html);
|
||||
}
|
||||
|
||||
$u = Db::getRow(
|
||||
@ -60,185 +55,79 @@ $u = Db::getRow(
|
||||
users.login,
|
||||
auth,
|
||||
pass,
|
||||
pass2,
|
||||
users.city,
|
||||
totp,
|
||||
users.ip,
|
||||
ipreg,
|
||||
admin,
|
||||
online,
|
||||
banned,
|
||||
host_reg,
|
||||
timereg,
|
||||
securetime,
|
||||
users_delo.text as block_reason
|
||||
from users
|
||||
left join users_delo on users.id = users_delo.uid
|
||||
where users.login = ?',
|
||||
[$_POST['login']]
|
||||
[$login]
|
||||
);
|
||||
$auth = Db::getValue('select id from logs_auth where uid = ? and ip = ?', [$u['id'], IP]);
|
||||
|
||||
if (!isset($u['id'])) {
|
||||
error('Логин "' . $_POST['login'] . '" не найден в базе.');
|
||||
} elseif ($u['banned'] > 0) {
|
||||
if (empty($_SESSION['login'])) {
|
||||
if (!isset($u['id'])) {
|
||||
error('Логин "' . $login . '" не найден в базе.');
|
||||
} elseif ($u['banned'] > 0) {
|
||||
$blockstr = "Персонаж <b>{$u['login']}</b> заблокирован.";
|
||||
$blockstr .= $u['block_reason'] ? "Причина блокировки: {$u['block_reason']}<br><br>" : '<br><br>';
|
||||
error($blockstr);
|
||||
} elseif (!Password::isGood($_POST['pass'], $u['pass'], $u['login'])) {
|
||||
error("Неверный пароль к персонажу {$u['login']}.");
|
||||
} elseif (!Password::isGood($password, $u['pass'], $u['login'])) {
|
||||
Db::sql(
|
||||
'insert into logs_auth (uid, ip, browser, type, time) values (?,?,?,3,unix_timestamp())',
|
||||
[$u['id'], IP, $_SERVER['HTTP_USER_AGENT']]
|
||||
);
|
||||
} else {
|
||||
|
||||
//Второй пароль
|
||||
if (!empty($u['pass2'])) {
|
||||
$_SESSION['login'] = $_POST['login'];
|
||||
$_SESSION['pass'] = $_POST['pass'];
|
||||
$good2 = false;
|
||||
$koko = '';
|
||||
if (password_verify($_POST['code'], $u['pass2'])) {
|
||||
$good2 = true;
|
||||
unset($_SESSION['login'], $_SESSION['pass']);
|
||||
} else {
|
||||
if (isset($_POST['code'])) {
|
||||
$koko = 'Неверный второй пароль<br>';
|
||||
}
|
||||
setcookie('login', '', time() - 60 * 60 * 24, '', Config::get('host'));
|
||||
error("Неверный пароль к персонажу {$u['login']}.");
|
||||
}
|
||||
|
||||
if ($koko) {
|
||||
$koko = '<b style="color: red">' . $koko . '</b>';
|
||||
$_SESSION['login'] = $u['login'];
|
||||
if (!empty($u['totp'])) {
|
||||
$_SESSION['totp'] = new TOTP($u['totp']);
|
||||
}
|
||||
if (!$good2) {
|
||||
}
|
||||
|
||||
if (!empty($_SESSION['totp']) && !empty($_SESSION['login'])) {
|
||||
if (empty($otp)) {
|
||||
?>
|
||||
<!Doctype html>
|
||||
<HTML lang="ru">
|
||||
<HEAD>
|
||||
<link rel=stylesheet type="text/css">
|
||||
|
||||
<meta name="msapplication-config" content="browserconfig.xml"/>
|
||||
<TITLE>Второй пароль</TITLE>
|
||||
</HEAD>
|
||||
<body style="background-color: #dfdfde;">
|
||||
<H3>Запрос второго пароля к персонажу.</H3>
|
||||
<?= $koko ?>
|
||||
<div style="text-align: center">
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<img id="pass" onClick="" width="295" src="i/pin/e0.png" alt="pass">
|
||||
<br>
|
||||
<br>
|
||||
<img id="p1" onClick="" src="" alt="p1">
|
||||
<img id="p2" onClick="" src="" alt="p2">
|
||||
<img id="p3" onClick="" src="" alt="p3">
|
||||
<br>
|
||||
<img id="p4" onClick="" src="" alt="p4">
|
||||
<img id="p5" onClick="" src="" alt="p5">
|
||||
<img id="p6" onClick="" src="" alt="p6">
|
||||
<br>
|
||||
<img id="p7" onClick="" src="" alt="p7">
|
||||
<img id="p8" onClick="" src="" alt="p8">
|
||||
<img id="p9" onClick="" src="" alt="p9">
|
||||
<br>
|
||||
<img onClick="keypush(12);" src="i/pin/12.png" alt="back">
|
||||
<img id="p0" name="image" onClick="" src="" alt="nan">
|
||||
<img onClick="keypush(11);" src="i/pin/11.png" alt="ok">
|
||||
<br>
|
||||
</div>
|
||||
</BODY>
|
||||
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
|
||||
<script>
|
||||
|
||||
var dopass = '';
|
||||
var tdopass = '';
|
||||
var lenth = 0;
|
||||
randomp();
|
||||
|
||||
function randomp() {
|
||||
var ss = [];
|
||||
var n = 0;
|
||||
while (n < 10) {
|
||||
ss[n] = n;
|
||||
n++;
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var k = 0;
|
||||
var m = 0;
|
||||
var tmpp = 0;
|
||||
while (i < 10) {
|
||||
k = getRandomInt(10);
|
||||
m = getRandomInt(10);
|
||||
if (k != m) {
|
||||
tmpp = ss[k];
|
||||
ss[k] = ss[m];
|
||||
ss[m] = tmpp;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
n = 10;
|
||||
while (n > -1) {
|
||||
n = n - 1;
|
||||
document.getElementById('p' + n).setAttribute("src", "i/pin/" + ss[n] + ".png");
|
||||
document.getElementById('p' + n).setAttribute("onClick", "keypush(" + ss[n] + ");");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function getRandomInt(max) {
|
||||
return Math.floor(Math.random() * Math.floor(max));
|
||||
}
|
||||
|
||||
function keypush(n) {
|
||||
if (n == 12) {
|
||||
|
||||
if (lenth > 0) {
|
||||
|
||||
dopass = '';
|
||||
|
||||
lenth = 0;
|
||||
document.getElementById('pass').setAttribute("src", "i/pin/e" + lenth + ".png");
|
||||
}
|
||||
} else if (n == 11) {
|
||||
|
||||
var $_POST = <?= json_encode($_POST); ?>;
|
||||
window.location.replace("/enter.php?code=" + dopass + "&login=" + $_POST['login'] + "&pass=" + $_POST['pass']);
|
||||
|
||||
} else {
|
||||
|
||||
if (lenth < 8) {
|
||||
dopass = dopass + '' + n;
|
||||
lenth++;
|
||||
document.getElementById('pass').setAttribute("src", "i/pin/e" + lenth + ".png");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
</HTML>
|
||||
<!doctype html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<title>Второй пароль</title>
|
||||
</head>
|
||||
<body>
|
||||
<form method="post">
|
||||
<label for="otp">Одноразовый код:</label><br>
|
||||
<input name="otp" id="otp" minlength="6" maxlength="6" size="6" placeholder="000000" required><br>
|
||||
<input type="submit">
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
die();
|
||||
}
|
||||
exit();
|
||||
}
|
||||
|
||||
if (!Db::getValue('select count(*) from stats where id = ?', [$u['id']])) {
|
||||
if ($_SESSION['totp']->generate() !== $otp) {
|
||||
unset($_SESSION['login'], $_SESSION['totp']);
|
||||
error('Неверный одноразовый код!');
|
||||
}
|
||||
}
|
||||
|
||||
if (!Db::getValue('select count(*) from stats where id = ?', [$u['id']])) {
|
||||
Db::sql('insert into stats (id, stats) values (?,?)', [$u['id'], 's1=3|s2=3|s3=3|s4=3|rinv=40|m9=5|m6=10']);
|
||||
}
|
||||
if (!Db::getValue('select count(*) from online where uid = ?', [$u['id']])) {
|
||||
}
|
||||
if (!Db::getValue('select count(*) from online where uid = ?', [$u['id']])) {
|
||||
Db::sql('insert into online (uid, timeStart) values (?,unix_timestamp())', [$u['id']]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_COOKIE['login'])) {
|
||||
if (isset($_COOKIE['login'])) {
|
||||
setcookie('login', '', time() - 60 * 60 * 24, '', Config::get('host'));
|
||||
}
|
||||
}
|
||||
|
||||
//мульты
|
||||
if ($u['admin'] === 0) {
|
||||
//мульты
|
||||
if ($u['admin'] === 0) {
|
||||
$ipm1 = Db::getValue(
|
||||
'select ip from logs_auth where uid = ? and ip != ? order by id limit 1',
|
||||
[$u['id'], $u['ip']]
|
||||
@ -256,39 +145,38 @@ if (!isset($u['id'])) {
|
||||
Db::sql('insert into mults (uid, uid2, ip) VALUES (?,?,?)', [$u['id'], $item['uid'], $item['ip']]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_COOKIE['ip']) && $_COOKIE['ip'] != IP) {
|
||||
if (isset($_COOKIE['ip']) && $_COOKIE['ip'] != IP) {
|
||||
Db::sql(
|
||||
'insert into logs_auth (uid, ip, browser, type, time) VALUES (?,?,?,1,unix_timestamp())',
|
||||
[$u['id'], $_COOKIE['ip'], $_SERVER['HTTP_USER_AGENT']]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
setcookie('login', $_POST['login'] ?? '', time() + 60 * 60 * 24 * 7, '', Config::get('host'));
|
||||
setcookie('ip', IP, time() + 60 * 60 * 24 * 150, '');
|
||||
setcookie('login', $_POST['login'] ?? '', time() + 60 * 60 * 24 * 7, '', Config::get('host'));
|
||||
setcookie('ip', IP, time() + 60 * 60 * 24 * 150, '');
|
||||
|
||||
if ($u['online'] < time() - 520) {
|
||||
$sp = Db::getRows('select room, city, login from users where online > unix_timestamp() - 600 and id in (select user from friends where friend = ?)', [$u['id']]);
|
||||
if ($u['online'] < time() - 520) {
|
||||
$sp = Db::getRows('select room, login from users where online > unix_timestamp() - 600 and id in (select user from friends where friend = ?)', [$u['id']]);
|
||||
foreach ($sp as $usr) {
|
||||
$chatDto = new ChatMessage();
|
||||
$chatDto->setRoom($usr['room']);
|
||||
$chatDto->setCity($usr['city']);
|
||||
$chatDto->setTo($usr['login']);
|
||||
$chatDto->setText('Вас приветствует: <b>' . $u['login'] . '</b>.');
|
||||
$chatDto->setType(6);
|
||||
$chat->sendMsg($chatDto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$apu = '';
|
||||
Db::sql('update dump set ver = 1, upd = 2 where uid = ?', [$u['id']]);
|
||||
$apu = '';
|
||||
Db::sql('update dump set ver = 1, upd = 2 where uid = ?', [$u['id']]);
|
||||
|
||||
if (
|
||||
if (
|
||||
$u['auth'] != md5($u['login'] . 'AUTH' . IP) ||
|
||||
$_COOKIE['auth'] != md5($u['login'] . 'AUTH' . IP) ||
|
||||
$u['auth'] == '' || $u['auth'] == '0'
|
||||
) {
|
||||
) {
|
||||
if (
|
||||
$u['auth'] != '' &&
|
||||
$u['auth'] != '0' &&
|
||||
@ -302,17 +190,19 @@ if (!isset($u['id'])) {
|
||||
}
|
||||
$apu = "auth = '" . md5($u['login'] . 'AUTH' . IP) . "',";
|
||||
setcookie('auth', md5($u['login'] . 'AUTH' . IP), time() + 60 * 60 * 24 * 365, '', Config::get('host'));
|
||||
}
|
||||
|
||||
$ipnew = IP;
|
||||
|
||||
Db::sql('insert into logs_auth (uid, ip, browser, time) values (?,?,?,unix_timestamp())', [
|
||||
$u['id'], IP, $_SERVER['HTTP_USER_AGENT'],
|
||||
]);
|
||||
|
||||
Db::sql("update users set $apu ip = ?, dateEnter = ?, online = unix_timestamp() where id = ?", [$ipnew, $_SERVER['HTTP_USER_AGENT'], $u['id']]);
|
||||
|
||||
$_SESSION['uid'] = $u['id'];
|
||||
header('location: /bk');
|
||||
exit();
|
||||
}
|
||||
|
||||
$ipnew = IP;
|
||||
|
||||
Db::sql('insert into logs_auth (uid, ip, browser, time) values (?,?,?,unix_timestamp())', [
|
||||
$u['id'], IP, $_SERVER['HTTP_USER_AGENT'],
|
||||
]);
|
||||
|
||||
Db::sql("update users set $apu ip = ?, dateEnter = ?, online = unix_timestamp() where id = ?", [$ipnew, $_SERVER['HTTP_USER_AGENT'], $u['id']]);
|
||||
|
||||
$_SESSION['uid'] = $u['id'];
|
||||
|
||||
unset($_SESSION['login'], $_SESSION['totp']);
|
||||
|
||||
header('location: /bk');
|
||||
exit();
|
||||
|
110
gate.php
110
gate.php
@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
define('GAME',true);
|
||||
include_once('_incl_data/__config.php');
|
||||
include_once('_incl_data/class/__db_connect.php');
|
||||
|
||||
if( isset($_GET['md5']) ) {
|
||||
$_GET['in'] = 1;
|
||||
}
|
||||
|
||||
if( isset($_GET['in']) ) {
|
||||
|
||||
$_GET['ref'] = 7;
|
||||
|
||||
$login = $_GET['login'];
|
||||
$pass = $_GET['pass'];
|
||||
|
||||
$md5 = md5( 'GATE_IN_DATA::'.$_GET['login'].$_GET['pass'].$_GET['exp'].$_GET['align'].$_GET['clan_prava'].$_GET['bithday'].$_GET['clan'].$_GET['sex'].$_GET['win'].$_GET['lose'].$_GET['nich'] );
|
||||
|
||||
if( $md5 != $_GET['md5'] ) {
|
||||
unset($_GET['in']);
|
||||
}else{
|
||||
echo 'Нельзя создать т.к. не верный ключ и данные!';
|
||||
}
|
||||
|
||||
if( $_GET['exp'] > 300000 ) {
|
||||
$_GET['exp'] = 300000;
|
||||
}
|
||||
|
||||
if( $_GET['clan'] == 1 ) {
|
||||
$_GET['clan'] = 0;
|
||||
$_GET['align'] = 0;
|
||||
$_GET['clan_prava'] = 0;
|
||||
}
|
||||
if( $_GET['clan'] > 1 ) {
|
||||
$_GET['clan'] += 2;
|
||||
}
|
||||
|
||||
$usr = mysql_fetch_array(mysql_query('SELECT * FROM `users` WHERE `login` = "'.mysql_real_escape_string($_GET['login']).'" LIMIT 1'));
|
||||
if(isset($usr['id']) && isset($_GET['in'])) {
|
||||
unset($_GET['in']);
|
||||
setcookie('login',$_GET['login'], (time()+60*60*24*7) , '' , '.new-combats.com' );
|
||||
setcookie('pass',$_GET['pass'], (time()+60*60*24*7) , '' , '.new-combats.com' );
|
||||
setcookie('login',$_GET['login'], (time()+60*60*24*7) );
|
||||
setcookie('pass',$_GET['pass'], (time()+60*60*24*7) );
|
||||
header('location: /enter.php?login='.$_GET['login'].'&pass='.$_GET['pass'].'');
|
||||
die();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( isset($_GET['in']) ) {
|
||||
|
||||
//Создаем персонажа
|
||||
if( (int)$_GET['ref'] > 0 ) {
|
||||
mysql_query("UPDATE `users` SET `referals` = `referals` + 1 WHERE `id` = '".mysql_real_escape_string((int)$_GET['ref'])."' LIMIT 1");
|
||||
}
|
||||
$pass = md5($pass);
|
||||
mysql_query('INSERT INTO `users` (`real`,`online`,`align`,`clan`,`clan_prava`,`win`,`lose`,`nich`,`sex`,`bithday`,`host_reg`,`pass`,`ip`,`ipreg`,`city`,`cityreg`,`room`,`timereg`) VALUES (
|
||||
"1",
|
||||
"'.time().'",
|
||||
"'.mysql_real_escape_string($_GET['align']).'",
|
||||
"'.mysql_real_escape_string($_GET['clan']).'",
|
||||
"'.mysql_real_escape_string($_GET['clan_prava']).'",
|
||||
"'.mysql_real_escape_string($_GET['win']).'",
|
||||
"'.mysql_real_escape_string($_GET['lose']).'",
|
||||
"'.mysql_real_escape_string($_GET['nich']).'",
|
||||
"'.mysql_real_escape_string($_GET['sex']).'",
|
||||
"'.mysql_real_escape_string($_GET['bithday']).'",
|
||||
|
||||
"'.mysql_real_escape_string(0+$_GET['ref']).'",
|
||||
"'.mysql_real_escape_string($pass).'",
|
||||
"'.mysql_real_escape_string(GetRealIpTest()).'",
|
||||
"'.mysql_real_escape_string(GetRealIpTest()).'",
|
||||
"capitalcity",
|
||||
"capitalcity",
|
||||
"0",
|
||||
"'.time().'"
|
||||
)');
|
||||
$uid = mysql_insert_id();
|
||||
if( $uid > 0 ) {
|
||||
|
||||
mysql_query('UPDATE `users` SET `login` = "'.mysql_real_escape_string($login).'" WHERE `id` = "'.$uid.'" LIMIT 1');
|
||||
//Создаем статы персонажа
|
||||
mysql_query("INSERT INTO `online` (`uid`,`timeStart`) VALUES ('".$uid."','".time()."')");
|
||||
mysql_query("INSERT INTO `stats` (`id`,`stats`,`exp`) VALUES ('".$uid."','s1=3|s2=3|s3=3|s4=3|rinv=40|m9=5|m6=10','".mysql_real_escape_string($_GET['exp'])."')");
|
||||
|
||||
//мульты
|
||||
$ipm1 = mysql_fetch_array(mysql_query('SELECT * FROM `logs_auth` WHERE `uid` = "'.mysql_real_escape_string($uid).'" AND `ip`!="'.mysql_real_escape_string(GetRealIpTest()).'" ORDER BY `id` ASC LIMIT 1'));
|
||||
$ppl = mysql_query('SELECT * FROM `logs_auth` WHERE `ip`!="" AND (`ip` = "'.mysql_real_escape_string(GetRealIpTest()).'" OR `ip`="'.mysql_real_escape_string($ipm1['ip']).'" OR `ip`="'.mysql_real_escape_string($_COOKIE['ip']).'")');
|
||||
while($spl = mysql_fetch_array($ppl))
|
||||
{
|
||||
$ml = mysql_fetch_array(mysql_query('SELECT `id` FROM `mults` WHERE (`uid` = "'.$spl['uid'].'" AND `uid2` = "'.$uid.'") OR (`uid2` = "'.$spl['uid'].'" AND `uid` = "'.$uid.'") LIMIT 1'));
|
||||
if(!isset($ml['id']) && $spl['ip']!='' && $spl['ip']!='127.0.0.1')
|
||||
{
|
||||
mysql_query('INSERT INTO `mults` (`uid`,`uid2`,`ip`) VALUES ("'.$uid.'","'.$spl['uid'].'","'.$spl['ip'].'")');
|
||||
}
|
||||
}
|
||||
mysql_query("INSERT INTO `logs_auth` (`uid`,`ip`,`browser`,`type`,`time`,`depass`) VALUES ('".$uid."','".mysql_real_escape_string(GetRealIpTest())."','".mysql_real_escape_string($_SERVER['HTTP_USER_AGENT'])."','1','".time()."','')");
|
||||
|
||||
//Обновяем таблицы
|
||||
mysql_query("UPDATE `users` SET `online`='".time()."',`ip` = '".mysql_real_escape_string(GetRealIpTest())."' WHERE `uid` = '".$uid."' LIMIT 1");
|
||||
|
||||
if(!setcookie('login',$login, (time()+60*60*24*7) , '' , '.new-combats.com' ) || !setcookie('pass',$pass, (time()+60*60*24*7) , '' , '.new-combats.com' )) {
|
||||
die('Ошибка сохранения cookie.');
|
||||
}
|
||||
header('location: /enter.php?login='.$_GET['login'].'&pass='.$_GET['pass'].'');
|
||||
}
|
||||
}
|
||||
?>
|
@ -6,11 +6,6 @@ if (!defined('GAME_VERSION')) {
|
||||
require_once '_incl_data/autoload.php';
|
||||
}
|
||||
|
||||
if (isset($_GET['time'])) {
|
||||
echo time() . '<br>' . date('d.m.Y H:i:s', (int)$_GET['time']);
|
||||
die();
|
||||
}
|
||||
|
||||
header("Cache-Control: max-age=3600");
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
@ -30,6 +25,7 @@ header("Cache-Control: max-age=3600");
|
||||
flex-direction: column;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
hr.incontent {
|
||||
width: 32%;
|
||||
border: 1px #1c1c1c solid;
|
||||
@ -43,7 +39,7 @@ header("Cache-Control: max-age=3600");
|
||||
<label for="first-name">Ваш Никнейм</label><br>
|
||||
<input type="text" id="first-name" name="login" autocomplete="username"><br>
|
||||
<label for="last-name">Ваш Пароль</label><br>
|
||||
<input type="password" id="last-name" name="psw" autocomplete="current-password">
|
||||
<input type="password" id="last-name" name="password" autocomplete="current-password">
|
||||
<p>
|
||||
<input type="submit" value="Войти в игру" class="btn btn-default">
|
||||
</form>
|
||||
|
@ -3,6 +3,8 @@
|
||||
/* @var $u User */
|
||||
|
||||
use Core\Config;
|
||||
use Core\Db;
|
||||
use Core\TOTP;
|
||||
use User\Email;
|
||||
use User\Password;
|
||||
|
||||
@ -14,23 +16,18 @@ $password = new Password($u->info);
|
||||
$email = new Email($u->info);
|
||||
$status = null;
|
||||
|
||||
if ($_POST['oldpsw2']) { // remove psw2
|
||||
if (password_verify((int)$_POST['oldpsw2'], $u->info['pass2'])) {
|
||||
$u->info['pass2'] = $password->changeSecond(null)['pass2'];
|
||||
$status = "<b style='color: darkolivegreen'>Второй пароль выключен.</b><br>";
|
||||
} else {
|
||||
$status = "<b style='color: red'>Введен не верный второй пароль!</b><br>";
|
||||
}
|
||||
if ($_POST['removetotp']) {
|
||||
// Удаление ключа ТОТР
|
||||
$u->info['totp'] = '';
|
||||
Db::sql('update users set totp = ? where id = ?', [$u->info['totp'], $u->info['id']]);
|
||||
$status = "<b style='color: darkolivegreen'>Секретный ключ удалён.</b><br>";
|
||||
}
|
||||
|
||||
if ($_POST['num_count']) { //add psw2
|
||||
$arr = $password->changeSecond((int)$_POST['num_count']);
|
||||
$status = "<b style='color: red'>Второй пароль: {$arr['pass2']}.<br>
|
||||
Запомните или запишите, т.к. он не высылается на email и его нельзя как-либо узнать.
|
||||
Потеряв второй пароль, вы потеряете персонажа!<br>
|
||||
Этот пароль выслан на ваш email.<br>
|
||||
</b><br>";
|
||||
$u->info['pass2'] = $arr['hash'];
|
||||
if ($_POST['newtotp']) {
|
||||
// Создание ключа ТОТР
|
||||
$u->info['totp'] = TOTP::otpSecret($u->info['id']);
|
||||
Db::sql('update users set totp = ? where id = ?', [$u->info['totp'], $u->info['id']]);
|
||||
$status = "<b style='color: darkolivegreen'>Секретный ключ создан.</b><br>";
|
||||
}
|
||||
|
||||
if (
|
||||
@ -66,7 +63,7 @@ if (
|
||||
}
|
||||
?>
|
||||
|
||||
<form action="main.php?security" method="post" id="security"></form>
|
||||
<form action="/main.php?security" method="post" id="security"></form>
|
||||
|
||||
<div>
|
||||
<h3>Настройки безопасности</h3>
|
||||
@ -180,41 +177,18 @@ if (
|
||||
</TABLE>
|
||||
</FIELDSET>
|
||||
<FIELDSET>
|
||||
<LEGEND><B> Второй уровень защиты </B></LEGEND>
|
||||
Настоятельно рекомендуем включить второй уровень защиты.<BR>
|
||||
На компьютере может быть установлен клавиатурный шпион, который записывает все нажатия клавиш, таким
|
||||
образом,
|
||||
могут узнать ваш пароль.<BR>
|
||||
Возможно, в сети компьютеров установлен "сетевой снифер", перехватывающий все интернет пакеты, который легко
|
||||
покажет все пароли. Чтобы обезопасить себя, вы можете установить своему персонажу второй пароль, который
|
||||
можно
|
||||
вводить при помощи мышки (клавиатурным шпионом не перехватить) и который передается на игровой сервер в
|
||||
зашифрованном виде, не поддающимся расшифровке ("сетевой снифер" не сможет перехватить его).<BR>
|
||||
<U>Будьте внимательны!</U> Второй пароль отправляется на email один раз,при установке второго уровня защиты!<BR>
|
||||
|
||||
<?php
|
||||
if (!empty($u->info['pass2'])) {
|
||||
echo "<BR><B>Второй пароль установлен.</B><BR><BR>
|
||||
Введите второй пароль <INPUT TYPE=password NAME=oldpsw2 size=10 maxlength=8>
|
||||
<INPUT form='security' TYPE=submit name=changepsw value=\"Выключить второй пароль\" onclick=\"return confirm('Выключить запрос второго пароля при входе в Бойцовский Клуб?')\">";
|
||||
} else {
|
||||
?>
|
||||
Длина пароля:<BR>
|
||||
<label>
|
||||
<INPUT form="security" TYPE=radio NAME="num_count" value=4> 4 знака<BR>
|
||||
</label>
|
||||
<label>
|
||||
<INPUT form="security" TYPE=radio NAME="num_count" checked value=6> 6 знаков<BR>
|
||||
</label>
|
||||
<label>
|
||||
<INPUT form="security" TYPE=radio NAME="num_count" value=8> 8 знаков<BR>
|
||||
</label>
|
||||
<INPUT form="security" TYPE=submit name=changepsw value="Установить второй пароль"
|
||||
onclick="return confirm('Система сама придумает вам второй пароль, он будет показан на этой странице, после того, как вы нажмете OK и продублирован на email, указанный при регистрации. Будьте внимательны.\nУстановить второй пароль?')">
|
||||
<BR>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<LEGEND><B> TOTP </B></LEGEND>
|
||||
TOTP (Time-based One-Time Password) - это метод двухфакторной аутентификации, который генерирует одноразовый пароль на основе текущего времени.
|
||||
Устанавливается для повышения безопасности вашего аккаунта, так как помогает защитить его от несанкционированного доступа.<br>
|
||||
Вы можете использовать TOTP приложения, такие как Google Authenticator или Authy, чтобы генерировать и отображать временные одноразовые пароли на вашем мобильном устройстве.
|
||||
<br><br>
|
||||
<U>Будьте внимательны!</U> Секретный ключ генерируется только один раз и не подлежит восстановлению. Его можно только удалить или заменить новым.<br>
|
||||
<?php if (!empty($u->info['totp'])): ?>
|
||||
<br><b>Секретный ключ:</b>
|
||||
<pre>{$u->info['totp']}</pre><br><br>
|
||||
<input form='security' type='submit' name='removetotp' value='Удалить секретный ключ' disabled><br>
|
||||
<?php endif; ?>
|
||||
<input form='security' type='submit' name='newtotp' value='Создать новый секретный ключ' disabled><br>
|
||||
</FIELDSET>
|
||||
</div>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user