WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. – Русские Блоги

Wechat mini program авторизация пользователей и авторизация пользователей для получения информации. – русские блоги

Затем блоггеры будут делиться авторизацией пользователя при входе в систему и получать информацию о пользователях для связанных с авторизацией вещей, помогать всем избегать ям и, наконец, прикреплять исходный код!

API интерфейс получения адреса

Когда работает реальная машина, появится страница, заполненная адресом, написанным апплетом

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

В разных системах учетных записей вы можете использовать unionId, чтобы определить, является ли это один и тот же пользователь

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

Нужно авторизовать пользователей для получения информации

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

Нужно авторизовать пользователей для получения информации

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

Авторизация появится здесь
Динамические настройки включают и выключают настройки пересылки (нажмите, чтобы включить и выключить функцию пересылки

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

Ниже приведен исходный код проекта апплета WeChat. Нажмите, чтобы ввести gitee, чтобы загрузить исходный пакет напрямую.
WeChat Mini Program Демонстрационная программа

Все права защищены, перепечатка запрещена, нарушители будут расследованы.
Понравившиеся друзья могут получать комментарии, ваша поддержка – моя самая большая мотивация для обновления ~

Авторизация в приложениях

Добрый день всем. В этой статье я опишу свой практический опыт проектирования системы авторизации, в частности на C Qt 4. Для многих опытных программистов покажется все нижеизложенное банальностью, но для начинающих свой путь программистов, данный опыт думаю, будет полезен. Слов минимум, в основном вырезки кода.

Зачем же нужна авторизация? Что за вопрос, все же знают. Если коротко, то авторизация служит как для входа пользователя в систему, так и для ограничения прав на доступ к функциям системы. У меня он выделен, так сказать, в отдельный модуль, для переносимости, что позволяет использовать один и тот же код в разных проектах.

С чего же начинается авторизация? Ну, конечно же, с окна ввода пользователя и пароля! Вот как то так будет оно выглядеть:

WeChat Mini Program Авторизация пользователей и авторизация пользователей для получения информации. - Русские Блоги

Здесь все стандартно и понятно. Поле логина и пароля, и, конечно же, галочка «запомнить». Когда то в молодости я ее не использовал. Но ввод этой галочки явно облегчил жизнь моим пользователям. За кнопкой «Настройки» таится окошко настройки подключения к базе данных.

И что ж там внутри?

Функция main(), довольно все просто и понятно.

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    // Устанавливаем кодеки
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("cp1251"));
    QTextCodec::setCodecForTr(QTextCodec::codecForName("cp1251"));

    frmMain w;
    ProgSettings sett; 
    DlgAuth dlg;
    dlg.setWindowFlags(Qt::MSWindowsFixedSizeDialogHint | Qt::Dialog);
    // Устанавливаем имя последнего сохраненного пользователя в поле логин
    // и галочку "Запомнить"
    dlg.setUserName(sett.LastUser());
    dlg.setRemember(sett.IsRemember());
    // Если стоит галочка "запомнить"
    // то подключаемся к БД(при условии валидности настроек),
    // и устанавливаем последний сохраненный пароль
    if (dlg.IsRemember() && DBConnector::CanConnectToDB()) {
        DBConnector::ConnectToDB();
        dlg.setPassword(sett.SavePassword());
    }    
// Или входим сразу с сохраненным паролем, либо показываем диалог авторизации
    if ((DBConnector::CanConnectToDB() && sett.IsRemember() &&
         coreUsers::Auth(sett.LastUser(),sett.SavePassword()))
         || dlg.exec() == QDialog::Accepted)
    {
        w.show();
        // Сохраняем последние п-ры входа
        sett.setLastUser(dlg.UserName());
        sett.setSavePassword(dlg.Password());
        sett.setIsReminder(dlg.IsRemember());
    }
    else return 0;
    return a.exec();
}

Функция CanConnectToDB() проверяет корректность наших параметров для подключения к БД(если программа запущена в первые, то функция возвратит false, т.к. настроек еще нет);

Класс ProgSettings служит для работы с настройками программы, в нем нет ничего особенно, соот. и останавливаться не будем.
Отдельно стоит остановиться на функции Auth(), наверное самая главная функция.

bool coreUsers::Auth(QString login, QString pwd)
{
    QSqlQuery sql;
    bool Ok = false;
    sql.exec(QString("SELECT * FROM %1 WHERE %2 = '%3'")
             .arg(UserTable::tableName())
             .arg(UserTable::loginField())
             .arg(login));
    if (sql.lastError().isValid()) {
        QMessageBox::information(QApplication::activeWindow(),tr("Ошибка"),
            sql.lastError().text(),QMessageBox::Ok);
        return false;
    }
    if (sql.size() > 0) {
        sql.next();
        if (QString::compare(Cryptor::Decode(sql.record().field(UserTable::pwdField()).value().toString())
            ,pwd,Qt::CaseSensitive)!=0) {
            QMessageBox::information(QApplication::activeWindow(),tr("Ошибка"),tr("Неверный пароль! ")
                ,QMessageBox::Ok);
        } else {
            if (sql.record().field(UserTable::lockField()).value().toBool())
                QMessageBox::information(QApplication::activeWindow(),tr("Ошибка"),
                    tr("Пользователь '%1' заблокирован.").arg(login),QMessageBox::Ok);
            else {
                Ok = true;
                SetActiveUser(new SystemUser(sql.record().field(UserTable::idField()).value().toInt(),
                                                login,"",
                                                sql.record().field(UserTable::nameField()).value().toString()));
            }
        }
    }
    else
        QMessageBox::information(QApplication::activeWindow(),tr("Ошибка"),
            tr("Нет такого пользователя или неверный пароль!"),QMessageBox::Ok);
    return Ok;
}

Без комментариев, за исключение функции SetActiveUser(), которая создает статический экземпляр от SystemUser класса, требуемый для дальнейшей работы по ограничению доступа к функциям всей программы.
Класс UserTable предстовляет собой класс обертку таблицы пользователей.

class UserTable
{
public:
    static QString tableName()     { return "sy_user"; }
    static QString loginField()    { return "us_login"; }
    static QString pwdField()      { return "us_pwd"; }
    static QString idField()       { return "us_id"; }
    static QString nameField()     { return "us_name"; }
    static QString lockField()     { return "us_lock"; }
    static QString onlineField()   { return "us_online"; }
    static QString onlineTimeField(){ return "us_online_time"; }
    static bool IsEmpty();

    // Создать первого пользователя системы для первого входа в систему
    static void CreateFirstUser();
};

Стоит отметить о сохранении паролей, они пишутся в реестр и таблицу базы данных зашифрованными. Пароль в таблице пользователей и пароль для подключения к серверу БД шифруются одинаковым алгоритмом и ключом. Кстати, не редко вижу на практике, что многие серьезные программы, пишут в системный реестр незашифрованные пароли, это как, нормально?
Шифрация паролей происходит на уровне приложения, следовательно, первый пользователь системы (без которого мы вообще не войдем в программу) создается при первой попытке входа в систему, вот такой функцией:

void UserTable::CreateFirstUser()
{
    if (!QSqlDatabase::database().isOpen() && !UserTable::IsEmpty())
        return;
    QSqlQuery sql;
    sql.exec(QString("INSERT INTO %1 (%2, %3)  VALUES('admin', '%4');")
             .arg(tableName())
             .arg(loginField())
             .arg(pwdField())
             .arg(Cryptor::Encode("admin")));
    if (sql.lastError().isValid()) {
        qDebug() << sql.lastError().text();
    } else {
        UserLimitTable::AddLimit(sql.lastInsertId().toInt(),100);
    }
}

Тут же потребуется класс обертка для таблицы ограничений пользователей:

class UserLimitTable
{
public:
    static QString TableName()      { return "sy_user_limit"; }
    static QString limitIdField()   { return "ul_limit"; }
    static QString userIdField()    { return "ul_us_id"; }
    static void AddLimit(int userID, int limitID);
};

И на последок класс SystemUser:

class SystemUser
{
public:
    SystemUser(int id, QString login, QString pwd, QString name);
    // Возвращает список ограничений пользователя
    QList<int> Limits() {return limits;}
    int id()        {return Id;}
    QString login()     {return Login;}
    QString password()  {return Password;}
    QString userName()  {return UserName;}
    QDateTime startSessionTime() {return StartSessionTime;}
    void setId(int value) {Id = value;}
    void setLogin(QString value) { Login = value;}
    void setPassword(QString value) {Password = value;}
    void setUserName (QString value) {UserName = value;}
    void setStartSessionTime (QDateTime value) { StartSessionTime = value;}
private:
    QList<int> limits;
    int Id;
    QString Login;
    QString Password;
    QString UserName;
    QDateTime StartSessionTime;
};

Ограничения пользователя хранятся в обычном списке QList, который заполняется из таблицы лимитов пользователей в конструкторе SystemUser. Служит он для дальнейшего ограничения функций текущего пользователя.

В итоге мы получаем систему авторизации, подходящую практически для любой сложности приложений. На основе классов оберток таблиц, строятся все запросы к базе данных, что при переносе на другой проект, заменяются имена полей таблицы на свои. Что очень удобно.

Спасибо что дочитали до конца.

Всё хорошо?

Почти. Данная система по-прежнему не защищает от кражи хэша из кук при открытом канале и отсутствии SSL. Кроме того, сложно обеспечить своевременную блокировку, если доступ к аккаунту утерян (особенно если взломщик уже сменил пароль). В этом случае очень помог бы сброс пароля через смс-команду с привязанного телефона — но для этого уже нужна возможность принимать и отправлять смс.

А если она есть — то можно сразу внедрить двухфакторную авторизацию, которая снимет массу проблем. Но не проблему с необходимостью в SSL — поскольку всё равно результатом любой авторизации является получение некого токена доступа, работающего ограниченное время. И этого времени может быть достаточно, чтобы сделать от нашего имени что-то, что нам не понравится.

Делегирование полномочий

Давайте попробуем создать отдельный модуль. Назовём его совершенно бесхитростно — security.php, и оформим как отдельный скрипт. Будем подключать его ко всем закрытым страницам нашего проекта в самом начале. Внутри этого файла будем анализировать некие условия, а по итогам его работы выставлять специальный флаг в 0 или 1. Пусть этот флаг будет храниться в переменных сессии (массив $_SESSION в PHP).

Что нам это даёт? Мы можем запихать в этот скрипт сколь угодно хитрую логику, вплоть до анализа последних действий пользователя и добавления его в бан-лист по IP, либо блокировки его аккаунта на тот или иной срок. Но сперва реализуем очень базовую функциональность: будем сверять значение хэша, пришедшего из куки, с тем, что должно было бы получиться, если хэш не был искажён. Сервер знает IP, знает юзер-агент, знает пароль текущего пользователя… Кажется, всё готово!

Как быть?

Очевидно, с этим надо что-то делать. Да, можно сразу бежать покупать сертификат и подключать SSL. Но можно сделать кое-что ещё до этого, и существенно снизить тем самым необходимость в нём. В конце концов, в том же ВКонтакте SSL стал принудительным всего полгода назад, а до этого как-то ведь жили.

Первое, что приходит на ум — хранить вместо пароля хэш от него. Это не особо поможет, если кто-то перехватит трафик, и не поможет при краже кук. Но вот в ситуации «кто-то открыл настройки и прошёлся по кукам, пытаясь запомнить значения» — сильно усложнит жизнь злоумышленнику.

Можно пойти дальше, и при создании хэша использовать юзер-агент. Теперь взломщику придётся использовать браузер той же версии, что и у нас (а в случае с IE ещё и с тем же набором плагинов тех же самых версий, что выходит уж очень маловероятно, особенно если взломщик не догадался подсмотреть юзер-агент).

Предыстория


Осень 2022-ого. Примерно полтора года назад, когда мне случилось стать участником разработки проекта, где пользователей существенно больше пары десятков человек, я наконец-то впервые в своей жизни задумался о надёжности авторизации.

По сути, авторизация — это то, с чего начинается процесс взаимодействия зарегистрированного пользователя с системой (для незарегистрированного пользователя всё начинается с регистрации, и эти два процесса, как вы уже догадались, очень сильно взаимосвязаны). Я внезапно осознал, что во всех проектах, что я делал до этого, с безопасностью всё очень плохо.

Стандартная реализация

Итак, сессия в PHP по умолчанию хранится в файле. Её id сохраняется в cookie (если куки отключены — задействуется механизм передачи через адресную строку, если это не отключено в конфигурации). Время жизни такой сессионной куки по умолчанию — до момента закрытия браузера (и обычно его никто не меняет).

Поэтому более продвинутые программисты реализуют галочку «запомнить меня», либо реализуют её функционал по умолчанию, без возможности отключить. Что они делают? Просто сохраняют в собственной куке айди пользователя. Но поскольку просто айди хранить как-то уж слишком стрёмно (любой может поставить любое число и получить доступ к произвольному аккаунту), то часто вместе с айди за компанию сохраняют и пароль. В открытом виде.

Если кто-то не понимает, чем это плохо — представьте себе, что у нас пользователь пользуется очень старым, либо очень плохо реализованным браузером. Мы ведь не можем гарантировать, что браузер надёжно шифрует куки? Да и вирусы всякие могут быть у пользователя на компьютере, и в случае особо серьёзной малвари может не спасти и шифровка — зловред может попытаться считать значения прямо из памяти, когда они расшифрованы.

Человек, случайно оказавшийся у вашего компьютера в ваше отсутствие — сможет просто скопировать себе все интересующие куки, и в новых браузерах этот процесс стал ещё проще. Дыры в безопасности браузера могут потенциально привести к тому, что ваша кука станет доступна стороннему сайту (да, сейчас это крайней маловероятно, но чем чёрт не шутит).

Ну и самое главное — если у нас SSL используется только при авторизации (а на остальных страницах его решили отключить ради выигрыша в скорости, либо чтобы лучше работало промежуточное кэширование)… То наш пароль всё время передаётся открытым текстом.

Статья – аутентификация и авторизация в микросервисных приложениях [часть 1]

Доброго времени суток, codeby.

Сегодня хочу рассказать об обеспечение безопасности микросервисного приложения. Тема довольно интересная и поистине творческая: существует довольно большое множество способов, которые меняются от системы к системе. В рамках двух статей я постараюсь дать хорошие теоретические знания вопроса и практическую реализацию одного из рецептов. Я решил разделить материал, так первая статья будет про теорию а вторая будет чисто практической. Статьи сосредоточены на механизме авторизации и аутентификации, поэтому читателю предлагается самостоятельное погружение в тему микросервисов и их архитектуры. Однако небольшие отступления, дабы читатель видел картину целиком, всё таки будут присутствовать.

В качестве приложения для примера – выбраны микросервисы, из моей статьи о docker. Читателю также предлагается ознакомиться с ними самостоятельно. Стоит сказать, что приложение было модифицировано. Фронтенд вынесен в контейнер с ngnix, о чём я также расскажу во второй части, apigetway мы перепишем в рамках второй части.

Как говорилось ранее – читателю предлагается самостоятельно ознакомится в различии микросервисной и монолитной архитектур. В контексте безопасности стоит сказать, что в монолитной системе за безопасность отвечает сам монолит. В противовес, в системе состоящей из микросервисов, чтоб удовлетворить запрос пользователя приходится вовлекать несколько микросервисов, исходя из этого напрашивается вопросы:

  • какие из микросервисов должны отвечать за авторизацию, а какие за аутентификацию
  • предположим, что одни из сервисов аутентифицировал пользователя, значит ли это что этому пользователю должны доверять другие микросервисы
  • должны ли микросервисы доверять другу
  • должны ли все микросервисы иметь доступ ко всем микросервисам, т.е. имеют ли право все микросервисы обращаться друг к другу

Как раз в этом месте и начинается творчество. Проблема заключается в том, что ответы на приведённые вопросы сильно различаются. Нельзя не заметить, что различия коррелируют с особенностью рассматриваемой системы – ответы, которые правильны для системы А будут в корне не верны для системы Б и так далее.

Кейсы аутентификации и авторизации встречается во всех системах. Различие между монолитом и микросервисами (в контексте данных проблем) в том, что в микросервисной системе всегда присутствует вопрос о том, какие из микросервисов должны отвечать за авторизацию и аутентификацию.

Словарь

Рассуждая теоретически, очень важно говорить на одном языке, поэтому давайте для начала определимся с некоторыми моментами.

Задача аутентификации – убедиться, что пользователь – тот за кого себя выдаёт.

Задача авторизации – убедиться, что пользователь имеет право делать то или иное действие в системе.

Данные бывают передаваемыми и хранимыми. Передаваемые данные – это данные которые “гуляют” от микросервиса до микросервиса. Хранимые – это данные которые хранятся в базах данных микросервисов.

Область действия – идентификатор для группы ресурсов, которые необходимо защитить. Например, все конечные точки способные изменить местоположение Пети, должны входить в группу location_information_write. Этакие наименования прав.

Маркер доступа – подписанный объект, используемый для предоставления доступа к микросервисам. Микросервис может запросить маркер доступа к любой области действий, если доступ разрешен – микросервис начинает взаимодействовать с разрешенной зоной.

OAuth и OpenId Connect – мы будем использовать эти протоколы для аутентификации и авторизации, реализацию возьмём из IdentityServer.

Аутентификация

Разобравшись с понятиями давайте приступим к размышлениям. Напомни, что раньше мы использовали архитектуру frontend for backend, где в качестве бэкэнда мы использовали микросервисы. Тогда каждый фрагмент фронтенда либо прорисовывался, либо нет – в зависимости от того был ли запущен сервис. Сейчас же давайте изменим архитектуру на нечто такое:

Что произошло: я вынес фронтенд часть на волю ngnix, действительно, нет особой необходимости иметь целый .net core проект, который существует лишь для того, чтобы рендерить заглавную страницу сайта, ngnix легковесней, дешевле и быстрее, этого вполне достаточно чтобы сделать выбор в его пользу. Появилось бизнесс-требование, которое гласит: “Необходимо дать пользователю возможность предустанавливать свою страну и город, для корректного вывода погоды и курса валют”. Вот у нас и появился функционал, который должен быть разграничен пользовательским контекстом. Так для Пети из Москвы погода и курс рубля к доллару будет отличаться от Тараса из Харькова (курс валюты для Тараса будет представлен как гривна к доллару).

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

Взглянем ещё раз на новую архитектуру. Микросервис Login отвечает за вход Тараса и Пети в систему, однако за запросы Пети и Тараса всё ещё отвечает API Gateway (вернее он вообще отвечает за то что запросы могут выполнять только вошедшие в систему пользователи). Следовательно микросервис API Gateway должен знать аутентифицирован ли пользователь отправивший запрос или нет.

Тут нам на помощь придёт промежуточное ПО, которое перенаправляет пользователей, которые не вошли в систему, в микросервис Login. Сам же микросервис Login решает как именно пользователь будет входить в систему и проводит его через процесс входа. В рамках статьи, Петя и Тарас смогут попасть в систему двумя способами:

Вне зависимости от способа входа, микросервис Login должен предоставлять подтверждение API Gateway того, что пользователь аутентифицирован, в таком виде в котором API Gateway предоставляет возможность проверить подлинность. Для этого существуют различные протоколы, в данном случае мы будем использовать OpenId Connect.

Хочу обратить ваше внимание, что аутентификация пользователя происходит на периферии системы, т.е. она проводится микросервисом, получившем запрос непосредственно от пользователя (через промежуточное ПО перенаправления). Это хорошо зарекомендовавший себя принцип разработки систем безопасности для микросервисов: аутентификация пользователя происходит на периферии системы.

Авторизация пользователей

После аутентификации пользователя – мы знаем кто он такой, однако в нормальных системах присутствует система прав, а значит знания, что пользователь является тем за кого себя выдаёт не гарантирует того что у пользователя есть разрешение на совершение того или иного действия. Ну банальный пример: уборщице Таси не нужно давать разрешения на визирование документов отправленных Тарасом для Петра. Также понятно, что система должна отклонять запрос на изменение местоположения Тараса направленного от имени Петра.

Так как мы имеем дело с микросервисной архитектурой, нам нужно понять какой сервис должен отвечать за авторизацию запросов. И вот ответ: поскольку один микросервис это всегда одна бизнес-возможность, мы вполне можем оставить авторизацию в конкретном сервисе. То есть, если Тарас имеет право на визирования документов для Петра, проверку этого визирования можно и нужно оставить в микросервисе документов. Так мы приходим к тому, что авторизация – это тоже часть бизнес возможности, если конкретней то это бизнес-правило.

Теперь поразмышляем о том как это реализовать. Несомненно проясняется факт, что мы должны передавать идентифицированную информацию пользоватяля от микросервиса к микросервису. Так сказать прокидывать её. Эту ответственность мы делегируем нашему Api Gateway так как именно он первым принимает запросы от пользователя, он должен каким то образом модифицировать пользовательский запрос.

Доверие микросервисов друг к другу

Поговорим о моменте, который нередко (разумеется во вред) упускается из вида. Смоделируем ситуацию атаки, допустим злоумышленник смог завладеть микросервисом валют и собирается отправить от его имени запрос на изменение логина и пароля Тараса на микросервис Login. В сценарии, где микросервисы доверяют друг другу и ничем не ограничены – мы, как blue team, потерпели сокрушительное фиаско. Однако, если голова нам дана “не чтоб шапку носить” и мы ограничили доступ к микросервису Login (разумно, чтоб его мог вызывать только Api Gateway, так как он находится на периферии) то всё будет хорошо.

Так насколько же микросервис должен доверять другому микросервису? Ответ на это вопрос, к сожалению, когда как. Это очень сильно зависит от проектируемых систем, от орг. структур, от требований соблюдений нормативных стандартов и т.д.

Чтобы обеспечить ограничение по взаимодействию – мы создадим в микросервисе Login области действий (см словарь). При необходимости вызова другого микросервиса, вызывающий микросервис должен будет запросить доступ у микросервиса Login в виде маркера доступа к конкретной области действия. К тому же мы должны передавать эти данные в зашифрованном виде, а не обычным текстом.

Google OAuth

Напоследок хочу сказать пару слов о том, как работает гугл аутентификация.

Давайте взглянем на картинку:

Процесс описан сверху вниз. В данном случае Client – это фронтенд часть приложения которое мы обсуждаем. Server – это его серверная часть, которая представлена у нас микросервисом Login. Google API Server – апи гугла, с которым мы будем взаимодействовать, а OAuth Dialog – это тот самый диалог, которые предоставляет гугл для аутентификации юзеров. Для использование google oauth нам нужен api-ключ: не имеет смысла расписывать пошагово как его получить, поэтому вот:

Implement social authentication with React RESTful API

Ну а в следующей части я расскажу и покажу как всё это реализовать.

Похожее:  Как зайти в настройки роутера Asus и где их найти

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *