PTS GF Регистрация аккаунтов Web(Python)

ZombieXLX

Путник
Участник
Сообщения
19
Розыгрыши
0
Репутация
0
Реакции
6
Баллы
78
После долгих блужданий по просторам интернета, так и не найдя никакой ВЕБ регистрации, для PTS сервера GF, какие-то древние технологии мамонтов на просторах интернета. Выкатываю свой каркас для регистрации обычных не админских аккаунтов.
Нам понадобится:
1. Создать процедуру на MSSQL сервере
SQL:
USE [lin2db]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

CREATE PROCEDURE [dbo].[user_reg]
    @account VARCHAR(14),
    @password BINARY(16),
    @quiz1 VARCHAR(255),
    @quiz2 VARCHAR(255),
    @answer1 BINARY(32),
    @answer2 BINARY(32),
    @pay_stat SMALLINT,
    @login_flag INT,
    @warn_flag INT,
    @block_flag INT,
    @block_flag2 INT,
    @subscription_flag INT
AS
BEGIN
    SET NOCOUNT ON;

    INSERT INTO dbo.user_auth (account, password, quiz1, quiz2, answer1, answer2)
    VALUES (@account, @password, @quiz1, @quiz2, @answer1, @answer2);

    DECLARE @UserID INT;
    SET @UserID = (SELECT MAX(uid) AS LastID FROM dbo.user_account)+1;

    SET IDENTITY_INSERT user_account ON;
    INSERT INTO dbo.user_account (uid, account, pay_stat, login_flag, warn_flag, block_flag, block_flag2, subscription_flag)
    VALUES (@UserID, @account, @pay_stat, @login_flag, @warn_flag, @block_flag, @block_flag2, @subscription_flag);
    SET IDENTITY_INSERT user_account OFF;
END;
GO
2. Рега хостится на убунту 22.0+ с использование Python + Microsoft ODBC Driver 17 следовательно нужно всё установить
Bash:
sudo -i
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list > /etc/apt/sources.list.d/mssql-release.list
exit

sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17 mssql-tools
sudo apt-get install -y unixodbc-dev python3 python-pip
pip install pyodbc flask
3. Отредактировать конфиги для подключения к MSSQL
Bash:
/etc/odbcinst.ini
[ODBC Driver 17 for SQL Server]
Description = Microsoft ODBC Driver 17 for SQL Server
Driver      = /opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.10.so.5.1

/etc/ssl/openssl.cnf
[system_default_sect]
#CipherString = DEFAULT:@SECLEVEL=2
CipherString = DEFAULT:@SECLEVEL=0
[/soiler]

4. Хостим сайт веб на фласк.
Структура веба
 
  • Мне нравится
Реакции: òbi

3. Отредактировать конфиги для подключения к MSSQL
Bash:
/etc/odbcinst.ini
[ODBC Driver 17 for SQL Server]
Description = Microsoft ODBC Driver 17 for SQL Server
Driver      = /opt/microsoft/msodbcsql17/lib64/libmsodbcsql-17.10.so.5.1

/etc/ssl/openssl.cnf
[system_default_sect]
#CipherString = DEFAULT:@SECLEVEL=2
CipherString = DEFAULT:@SECLEVEL=0

4. Хостим сайт веб на фласк.
Структура каталога с вебом
app.py dec.py
Python:
from flask import Flask, render_template, request, redirect, url_for
import pyodbc
import dec

app = Flask(__name__)

# Замените параметры подключения на свои
server = '10.6.0.11'
database = 'lin2db'
username = 'l2'
password = 'test'
driver = 'ODBC Driver 17 for SQL Server'

# Строка подключения
connection_string = f'DRIVER={driver};SERVER={server};DATABASE={database};UID={username};PWD={password}'

@app.route('/')
def index():
    return render_template('index.html')

@app.route('/register', methods=['POST'])
def register():
    if request.method == 'POST':

        # Параметры для передачи в процедуру
        account_value = request.form['username']
        password_value = bytes.fromhex(dec.encrypt(request.form['password'])[2:])
        quiz1_value = ''
        quiz2_value = ''
        answer1_value = bytes.fromhex("0x1100000000000000000000000000000000000000000000000000000000000000"[2:])
        answer2_value = bytes.fromhex("0x1100000000000000000000000000000000000000000000000000000000000000"[2:])
        pay_stat_value = 1
        login_flag_value = 0
        warn_flag_value = 0
        block_flag_value = 0
        block_flag2_value = 0
        subscription_flag_value = 0

    try:
        # Подключение к базе данных
        connection = pyodbc.connect(connection_string)
        cursor = connection.cursor()

        # Вызов хранимой процедуры с передачей параметров
        cursor.execute("EXEC user_reg ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?",
                       account_value, password_value, quiz1_value, quiz2_value, answer1_value, answer2_value,
                       pay_stat_value, login_flag_value, warn_flag_value, block_flag_value, block_flag2_value, subscription_flag_value)

        # Подтверждение транзакции
        connection.commit()

        print("Процедура успешно вызвана!")

    except pyodbc.Error as ex:
        # В случае ошибки выводим сообщение об ошибке
        print("Ошибка:", ex)

    finally:
        # Закрываем подключение
        if connection:
           connection.close()
           return redirect(url_for('index'))

if __name__ == '__main__':
    app.run(debug=True, port=8080, host='0.0.0.0')
Python:
def encrypt(text):
    key = [0] * 17
    dst = [0] * 17
    i = 0

    for char in text:
        i += 1
        key[i] = ord(char)
        dst[i] = key[i]

    rslt = key[1] + key[2] * 256 + key[3] * 65536 + key[4] * 16777216
    one = (rslt * 213119 + 2529077) - int((rslt * 213119 + 2529077) / 4294967296) * 4294967296

    rslt = key[5] + key[6] * 256 + key[7] * 65536 + key[8] * 16777216
    two = (rslt * 213247 + 2529089) - int((rslt * 213247 + 2529089) / 4294967296) * 4294967296

    rslt = key[9] + key[10] * 256 + key[11] * 65536 + key[12] * 16777216
    three = (rslt * 213203 + 2529589) - int((rslt * 213203 + 2529589) / 4294967296) * 4294967296

    rslt = key[13] + key[14] * 256 + key[15] * 65536 + key[16] * 16777216
    four = (rslt * 213821 + 2529997) - int((rslt * 213821 + 2529997) / 4294967296) * 4294967296

    key[4] = int(one / 16777216)
    key[3] = int((one - key[4] * 16777216) / 65535)
    key[2] = int((one - key[4] * 16777216 - key[3] * 65536) / 256)
    key[1] = int((one - key[4] * 16777216 - key[3] * 65536 - key[2] * 256))

    key[8] = int(two / 16777216)
    key[7] = int((two - key[8] * 16777216) / 65535)
    key[6] = int((two - key[8] * 16777216 - key[7] * 65536) / 256)
    key[5] = int((two - key[8] * 16777216 - key[7] * 65536 - key[6] * 256))

    key[12] = int(three / 16777216)
    key[11] = int((three - key[12] * 16777216) / 65535)
    key[10] = int((three - key[12] * 16777216 - key[11] * 65536) / 256)
    key[9] = int((three - key[12] * 16777216 - key[11] * 65536 - key[10] * 256))

    key[16] = int(four / 16777216)
    key[15] = int((four - key[16] * 16777216) / 65535)
    key[14] = int((four - key[16] * 16777216 - key[15] * 65536) / 256)
    key[13] = int((four - key[16] * 16777216 - key[15] * 65536 - key[14] * 256))

    dst[1] = dst[1] ^ key[1]

    i = 1
    while i < 16:
        i += 1
        dst[i] = dst[i] ^ dst[i - 1] ^ key[i]

    i = 0
    while i < 16:
        i += 1
        if dst[i] == 0:
            dst[i] = 102

    encrypt_result = "0x"
    i = 0
    while i < 16:
        i += 1
        if dst[i] < 16:
            encrypt_result += "0" + format(dst[i], 'x')
        else:
            encrypt_result += format(dst[i], 'x')

    return encrypt_result
каталог templates
в каталоге templates содержится файл index.html
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Registration</title>
</head>
<body>
    <h1>Registration Form</h1>
    <form action="{{ url_for('register') }}" method="post">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required><br>

        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required><br>

        <button type="submit">Register</button>
    </form>
</body>
</html>

какие хроники, такие и технологии :Wahaha:
Можно же одностраничную регу выкатить то
 
  • Мне нравится
Реакции: òbi
Простой чекер для проверки подключения к БД
Python:
import pyodbc

# Замените параметры подключения на свои
server = '10.6.0.11'
database = 'lin2db'
username = 'l2'
password = 'test'
driver = 'ODBC Driver 17 for SQL Server'

# Строка подключения
connection_string = f'DRIVER={driver};SERVER={server};DATABASE={database};UID={username};PWD={password}'

try:
    # Подключение к базе данных
    connection = pyodbc.connect(connection_string)
    print("Подключение успешно!")

    # Закрываем подключение
    connection.close()

except pyodbc.Error as ex:
    # В случае ошибки выводим сообщение об ошибке
    print("Ошибка подключения:", ex)
 
  • Мне нравится
Реакции: òbi
PTS разработчики сами себе проблемы придумывают, понимаю сидят в С++ и куче гомна копают
но веб простую регу на питоне делать это уже слишком
Садомазохисты видимо :Hahaha:
 
PTS разработчики сами себе проблемы придумывают, понимаю сидят в С++ и куче гомна копают
но веб простую регу на питоне делать это уже слишком
Садомазохисты видимо :Hahaha:
Так, а на яве реги другие? Вместо MSSQL MySQL? Или XOR'а нет? Python проще чем php так, что вот так. :]
 
в php PDO уже есть готовый драйвер PDO_SQLSRV который работает с MSSQL, MySQL и кучей других ODBC

сидеть на хостинге питон пакет ставить )) который есть не на всех хостингах ))

я же говорю проблему на пустом месте придумываете )
 
в php PDO уже есть готовый драйвер PDO_SQLSRV который работает с MSSQL, MySQL и кучей других ODBC

сидеть на хостинге питон пакет ставить )) который есть не на всех хостингах ))

я же говорю проблему на пустом месте придумываете )
Админу доставляет сложность поставить пакет? Не улавливаю суть проблемы... Да и то что php установлен всё ещё не делает его проще :D
 
Админу доставляет сложность поставить пакет? Не улавливаю суть проблемы... Да и то что php установлен всё ещё не делает его проще :D
зачем ставить пакет и тучу гомна из терминала? когда можно реализовать на php веб часть где будет работать рега статистика и туча всего

расширять функционал будешь тоже весь на питоне?
и будет в корневой папке сайта гибрид смесь питона, пхп, и верстки статичной ))
 
зачем ставить пакет и тучу гомна из терминала? когда можно реализовать на php веб часть где будет работать рега статистика и туча всего

расширять функционал будешь тоже весь на питоне?
и будет в корневой папке сайта гибрид смесь питона, пхп, и верстки статичной ))
Конечное! Питон отлично подходит, как для бэка так и для фронта, не вижу причин его не использовать.
Рега прикручена, осталось дело за малым.
всё равно дальше локалки это не выйдет.
 
Приложение регистрации обновилось:

Ключи RECAPTCHA можно
Python:
from flask import Flask
from register import register


app = Flask(__name__)
app.config['RECAPTCHA_PUBLIC_KEY'] = '' 
app.config['RECAPTCHA_PRIVATE_KEY'] = ''
app.config['SECRET_KEY'] = 'Придумать свой'


app.add_url_rule('/register', 'register', register, methods=['GET', 'POST'])


if __name__ == '__main__':
    app.run(debug=True, port=8080, host='0.0.0.0')
Python:
def encrypt(text):
    key = [0] * 17
    dst = [0] * 17
    i = 0

    for char in text:
        i += 1
        key[i] = ord(char)
        dst[i] = key[i]

    rslt = key[1] + key[2] * 256 + key[3] * 65536 + key[4] * 16777216
    one = (rslt * 213119 + 2529077) - int((rslt * 213119 + 2529077) / 4294967296) * 4294967296

    rslt = key[5] + key[6] * 256 + key[7] * 65536 + key[8] * 16777216
    two = (rslt * 213247 + 2529089) - int((rslt * 213247 + 2529089) / 4294967296) * 4294967296

    rslt = key[9] + key[10] * 256 + key[11] * 65536 + key[12] * 16777216
    three = (rslt * 213203 + 2529589) - int((rslt * 213203 + 2529589) / 4294967296) * 4294967296

    rslt = key[13] + key[14] * 256 + key[15] * 65536 + key[16] * 16777216
    four = (rslt * 213821 + 2529997) - int((rslt * 213821 + 2529997) / 4294967296) * 4294967296

    key[4] = int(one / 16777216)
    key[3] = int((one - key[4] * 16777216) / 65535)
    key[2] = int((one - key[4] * 16777216 - key[3] * 65536) / 256)
    key[1] = int((one - key[4] * 16777216 - key[3] * 65536 - key[2] * 256))

    key[8] = int(two / 16777216)
    key[7] = int((two - key[8] * 16777216) / 65535)
    key[6] = int((two - key[8] * 16777216 - key[7] * 65536) / 256)
    key[5] = int((two - key[8] * 16777216 - key[7] * 65536 - key[6] * 256))

    key[12] = int(three / 16777216)
    key[11] = int((three - key[12] * 16777216) / 65535)
    key[10] = int((three - key[12] * 16777216 - key[11] * 65536) / 256)
    key[9] = int((three - key[12] * 16777216 - key[11] * 65536 - key[10] * 256))

    key[16] = int(four / 16777216)
    key[15] = int((four - key[16] * 16777216) / 65535)
    key[14] = int((four - key[16] * 16777216 - key[15] * 65536) / 256)
    key[13] = int((four - key[16] * 16777216 - key[15] * 65536 - key[14] * 256))

    dst[1] = dst[1] ^ key[1]

    i = 1
    while i < 16:
        i += 1
        dst[i] = dst[i] ^ dst[i - 1] ^ key[i]

    i = 0
    while i < 16:
        i += 1
        if dst[i] == 0:
            dst[i] = 102

    encrypt_result = "0x"
    i = 0
    while i < 16:
        i += 1
        if dst[i] < 16:
            encrypt_result += "0" + format(dst[i], 'x')
        else:
            encrypt_result += format(dst[i], 'x')

    return encrypt_result
Python:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired, ValidationError, Length
from flask_wtf.recaptcha import RecaptchaField

class RegistrationForm(FlaskForm):
    username = StringField('Username', validators=[DataRequired()])
    password = PasswordField('Password', validators=[DataRequired(), Length(min=8)])
    password2 = PasswordField('Confirm Password', validators=[DataRequired()])
    recaptcha = RecaptchaField()
    submit = SubmitField('Register')
Python:
def is_valid_login(login):
    if len(login) < 6:
        return False, "Логин должен содержать не менее 6 символов."

    if any(char in '!@#$%^&*()-_=+[]{};:,.<>?/~`"\\|' for char in login):
        return False, "Логин содержит недопустимые символы."

    return True, "Логин прошел валидацию."


pass
Python:
def is_valid_password(password):
    if len(password) < 8:
        return False, "Пароль должен содержать не менее 8 символов."

    if not any(char.isupper() for char in password):
        return False, "Пароль должен содержать хотя бы одну заглавную букву."

    if not any(char.islower() for char in password):
        return False, "Пароль должен содержать хотя бы одну строчную букву."

    if not any(char.isdigit() for char in password):
        return False, "Пароль должен содержать хотя бы одну цифру."

    if not any(char in '!@#$%^&*()-_=+[]{};:,.<>?/~`"\\|' for char in password):
        return False, "Пароль должен содержать хотя бы один специальный символ."

    return True, "Пароль прошел валидацию."


pass
Python:
from flask import Flask, render_template, request, redirect, url_for
from forms import RegistrationForm
from pass_valid import is_valid_password
from login_valid import is_valid_login
import pyodbc
import dec

server = '127.0.0.1'
database = 'lin2db'
username = 'l2'
password = 'l2'
driver = 'ODBC Driver 17 for SQL Server'

connection_string = f'DRIVER={driver};SERVER={server};DATABASE={database};UID={username};PWD={password}'

def register():
    form = RegistrationForm()
    if form.password.data == form.password2.data:
        if request.method == 'POST':
            if form.validate_on_submit():
                is_valid, message = is_valid_login(form.username.data)
                if is_valid:
                    is_valid, message = is_valid_password(form.password.data)
                    if is_valid:
                        account_value = form.username.data
                        pwd_value = bytes.fromhex(dec.encrypt(form.password.data)[2:])
                        quiz1_value = ''
                        quiz2_value = ''
                        answer1_value = ''
                        answer2_value = ''
                        real_name_value = ''
                        address_value = ''
                        phone_value = ''
                        email_value = ''

                        try:
                            connection = pyodbc.connect(connection_string)
                            cursor = connection.cursor()

                            cursor.execute("EXEC UserCheck ?", account_value)
                            result = cursor.fetchone()

                            if result and result[0] == account_value:
                                print("Ошибка: Аккаунт уже существует")
                                message = "Аккаунт уже существует. Пожалуйста, выберите другое имя пользователя."
                                return redirect(url_for('index'))
                            else:
                                cursor.execute(
                                    "EXEC lin_CreateAccount ?, ?, ?, ?, ?, ?, ?, ?, ?, ?",
                                    account_value, pwd_value, quiz1_value, quiz2_value,
                                    answer1_value, answer2_value, real_name_value,
                                    address_value, phone_value, email_value)
                                connection.commit()
                                print("Процедура успешно вызвана!")
                                message = "Аккаунт создан"

                        except pyodbc.Error as ex:
                            print("Ошибка:", ex)

                        finally:
                            if connection:
                                connection.close()
                                return render_template('registration.html',
                                                    form=form,
                                                    message=message)
                    else:
                        return render_template('registration.html',
                                            form=form,
                                            message=message)
                else:
                    return render_template('registration.html',
                                        form=form,
                                        message=message)
            else:
                return render_template('registration.html', form=form, message="Каптча не пройдена")
    else:
        return render_template('registration.html', form=form, message="Пароли не совпадают")
    return render_template('registration.html', form=form)

pass
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Registration</title>
</head>
<body>
    <h1>Registration Form</h1>
    <form method="post">
        {{ form.hidden_tag() }}
        {{ form.username.label }} {{ form.username }}
        {{ form.password.label }} {{ form.password }}
        {{ form.password2.label }} {{ form.password2 }}
        {{ form.recaptcha }}
        <button type="submit">Register</button>
    </form>
        {% if message %}
        <p>{{ message }}</p>
        {% endif %}
</body>
</html>

Bash:
sudo -i
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list > /etc/apt/sources.list.d/mssql-release.list
exit

sudo apt-get update
sudo apt-get install -y unixodbc-dev mssql-tools python3 python-pip
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17 
pip install pyodbc flask Flask-WTF

Функция на MSSQL сервере для проверки на существующий логин
SQL:
USE [lin2db]
GO

/****** Object:  StoredProcedure [dbo].[UserCheck]    Script Date: 04/22/2024 17:13:31 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[UserCheck]
(
@account VARCHAR(14)
)
AS

SET NOCOUNT ON

    SELECT account FROM user_auth WHERE account = @account

    IF @@ROWCOUNT <> 0 
        BEGIN
            print 'alredy exist'
        END
GO

Функция создания аккаунта на MSSQL сервере, модифицировал ту, что шла с PTS GF final от Vanganth
SQL:
USE [lin2db]
GO

/****** Object:  StoredProcedure [dbo].[lin_CreateAccount]    Script Date: 04/22/2024 20:15:23 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO


CREATE PROCEDURE [dbo].[lin_CreateAccount]
(
@account    NVARCHAR(14),
@pwd        NVARCHAR(50),
@quiz1     NVARCHAR(255),
@quiz2     NVARCHAR(255),
@answer1     NVARCHAR(255),
@answer2     NVARCHAR(255),
@real_name     NVARCHAR(20),
@address     NVARCHAR(50),
@phone     NVARCHAR(50),
@email     NVARCHAR(50)
)
AS

SET NOCOUNT ON

DECLARE @account_id    INT
DECLARE @pay_stat   SMALLINT = 1

    INSERT INTO user_account (account, pay_stat)
    VALUES (@account, @pay_stat)

    SELECT @account_id = @@IDENTITY

    INSERT INTO user_auth (account, password, answer1, answer2, quiz1, quiz2)
    VALUES (@account, CONVERT(BINARY(50), @pwd),CONVERT(BINARY(50), @answer1), CONVERT(BINARY(50), @answer2), @quiz1, @quiz2)
    
    SELECT @account_id as Account_id

GO

Бесплатный SSL сертификат для хоста можно попросить у
Пример конфига nginx
NGINX:
server {
    listen [::]:443 ssl ipv6only=on;
    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/test.ru/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.ru/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    
    root /var/www/html;
    index index.html
    
    server_name test.ru;
        location /register {
        proxy_pass http://10.10.10.10:8080/register;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        }
}
server {
    if ($host = test.ru) {
    return 301 https://$host$request_uri;
    }
        listen 80 ;
        listen [::]:80 ;
    server_name test.ru;
    return 404;
}
 
Может быть будет удобнее залить на гит и сделать репу публичной?
Могу помочь еще образ докера собрать под это дело, а то как-то по одному файлу копировать в 24 году выглядит не очень
 
Может быть будет удобнее залить на гит и сделать репу публичной?
Могу помочь еще образ докера собрать под это дело, а то как-то по одному файлу копировать в 24 году выглядит не очень
Может ты и прав, НО раз в пол года сажусь за это дело, мб как в след раз петух клюнет сделаю гит.
 
Назад
Сверху Снизу