Ответ 1
Я бы порекомендовал вам проверить OAuth. он определенно поможет вам разобраться в проблемах безопасности с авторизацией инструментов для доступа к вашему API.
Мне предлагается написать веб-API для приложения (pc executable, не веб-приложение), которое позволит отправлять электронные письма.
Пользователь нажимает что-то, приложение связывается с API, который генерирует электронное письмо и отправляет его.
Я должен убедиться, что никто из несанкционированных пользователей не получит доступ к API, поэтому мне нужно сделать некоторую аутентификацию, и у меня нет идеи, как это сделать правильно.
Будет больше приложений, обращающихся к API.
Первая мысль - отправить имя пользователя и пароль, но это не решит проблему. Потому что, если кто-то декомпилирует приложение, они будут иметь URL-адрес запроса и переменные, включая пользователя/пароль, или просто его можно просто понюхать.
Итак... какие у меня варианты?
Я уверен, что безопасное соединение (SSL) недоступно мне в данный момент, но все же это не поможет мне в решении проблемы декомпиляции, не так ли?
ИЗМЕНИТЬ
Я не сказал, что изначально, но пользователь не будет запрашивать имя пользователя/пароль. Это приложение (приложения), которое должно быть аутентифицировано, а не пользователи приложения (ов).
Я бы порекомендовал вам проверить OAuth. он определенно поможет вам разобраться в проблемах безопасности с авторизацией инструментов для доступа к вашему API.
Распределение вашего программного обеспечения на самом деле является основной проблемой. Хеширование имен пользователей и паролей и их сохранение в программном обеспечении не более полезно, чем хранение не хэшированных значений, так как любой из них будет работать для доступа к серверу API. Если вы собираетесь внедрять имена пользователей и пароли для своих пользователей, я думаю, вы можете использовать это как предварительный указатель на управление API, не сохраняя значения в самом программном обеспечении. Позвольте мне описать это в двух частях.
Запросить подписи
Наиболее распространенным методом, используемым для проверки запроса API, является сигнатура запроса. В принципе, перед отправкой запроса на сервер API параметры в запросе сортируются, и в микс добавляется уникальный ключ. Затем вся партия используется для создания хэша, который добавляется к запросу. Например:
public static function generateRequestString(array $params, $secretKey)
{
$params['signature'] = self::generateSignature($params, $secretKey);
return http_build_query($params,'','&');
}
public static function generateSignature($secretKey, array $params)
{
$reqString = $secretKey;
ksort($params);
foreach($params as $k => $v)
{
$reqString .= $k . $v;
}
return md5($reqString);
}
Вы можете создать строку запроса запроса API, используя вышеуказанный код, просто вызвав метод generateRequestString()
с массивом всех параметров, которые вы хотите отправить. Секретный ключ - это то, что предоставляется уникально каждому пользователю API. Как правило, вы передаете свой идентификатор пользователя на сервер API вместе с подписью, а сервер API использует ваш идентификатор для извлечения секретного ключа из локальной базы данных и проверки запроса так же, как вы его создали. Предполагая, что ключ и идентификатор пользователя верны, этот пользователь должен быть единственным, кто может создать правильную подпись. Обратите внимание, что ключ никогда не передается в запросе API.
К сожалению, для каждого пользователя требуется уникальный ключ, который является проблемой для вашего настольного приложения. Это приводит меня к шагу два.
Временные ключи
Таким образом, вы не можете распространять ключи с приложением, потому что их можно декомпилировать, и ключи будут уходить. Чтобы противодействовать этому, вы могли бы сделать очень короткоживущие ключи.
Предполагая, что вы внедрили часть настольного приложения, которое запрашивает у пользователей свое имя пользователя и пароль, вы можете заставить приложение выполнить запрос аутентификации на ваш сервер. При успешной аутентификации вы можете вернуть временный ключ с ответом, который настольное приложение может хранить на протяжении всего срока действия авторизованного сеанса и использовать для запросов API. Поскольку вы упомянули, что вы не можете использовать SSL, эта начальная проверка подлинности является наиболее уязвимой частью, и вам придется жить с некоторыми ограничениями.
Статья, предложенная Энди Э, - хороший подход (я проголосовал за это). Это в основном рукопожатие, чтобы установить недолговечный ключ, который можно использовать для аутентификации. Один и тот же ключ можно использовать для хэширования подписи. Вы также можете воспользоваться своими шансами и просто отправить имя пользователя/пароль незашифрованным и получить временный ключ (это произойдет только один раз), но вы должны знать, что его можно обнюхивать.
Резюме
Если вы можете установить временный ключ сеанса, вам не нужно хранить что-либо в клиентской программе, которую можно декомпилировать. Имя пользователя/пароль, отправленные один раз на ваш сервер, должно быть достаточно, чтобы установить это. После того, как у вас есть этот ключ, вы можете использовать его для создания запросов в настольных приложениях и проверки запросов на сервере API.
Кто-то всегда сможет декомпилировать и искать переменные. Обфускатор может скрыть их немного лучше. Sniffing также легко без SSL, если вы не используете частный и открытый набор ключей для шифрования клиентской части данных запроса и расшифровки серверной части (но, очевидно, этот ключ будет храниться в клиентском приложении).
Лучшее, что вам нужно сделать, это предоставить как можно больше уровней защиты, создающих безопасное соединение и обфускацию вашего кода. Вы можете посмотреть следующую статью, которая демонстрирует безопасное соединение без использования SSL:
http://www.codeproject.com/KB/security/SecureStream.aspx
Как упоминалось mattjames, вы никогда не должны хранить пароли в текстовом формате. Когда пользователь вводит свой пароль в приложение, храните хеш пароля. Тот же хеш должен храниться на сервере. Таким образом, если хеш рассматривается перехватчиком, они, по крайней мере, не будут видеть исходный пароль пользователя.
Вам нужно будет использовать SSL, если вам нужно, чтобы люди не видели простой текстовый пароль, который отправляется из приложения по сети в API.
Для проблемы декомпиляции вам нужно сохранить хэш пароля в API, а не исходный пароль. См. Объяснение здесь: http://phpsec.org/articles/2005/password-hashing.html.