Подразумевает ли аутентифицированный запрос REST ВСЕГДА запрос к базе данных? - PullRequest
2 голосов
/ 19 января 2012

Я использую RESTeasy Framework для разработки своего веб-сервиса.Мне удалось настроить BASIC-аутентификацию, и теперь она работает правильно.Конечно, я планирую использовать SSL поверх этого.

Процесс прост (и, пожалуйста, прочитайте что-нибудь об основной аутентификации HTTP, если вы не знаете, о чем идет речь):

  1. Каждый запрос перехватывается методом, который анализирует заголовок запроса.
  2. Этот заголовок декодируется и извлекаются имя пользователя и пароль.
  3. Затем метод запрашивает базу данных , чтобы проверить, совпадают ли имя пользователя и пароль.
  4. Если они совпадают, запрос продолжается, если нет, возвращается код 401.

При таком подходе каждый запрос подразумевает запрос к базе данных из-за природы REST (и самого HTTP) без сохранения состояния.

Мой вопрос: возможно ли не запрашивать базу данных на каждомзапрос с проверкой подлинности?

Возможные подсказки: какой-то механизм, использующий куки-файлы?

Этот вопрос технологически не связан.Я действительно чувствую, что есть очень малоИнформация об этой аутентификации REST имеет значение.Это просто OAuth, OAuth, OAuth ... Если мы не хотим аутентифицировать сторонние приложения, информация разбросана повсюду, и нет конкретных примеров, как, например, использование OAuth.Если у вас есть какие-либо полезные советы, касающиеся аутентификации в REST WebServices, я бы хотел их услышать.

Спасибо.

Ответы [ 5 ]

1 голос
/ 21 января 2012

Если вы интегрируетесь с UserService AppEninge (и, следовательно, с учетными записями Google), то вы можете предотвратить любые запросы. RESTlet имеет супер элегантный аутентификатор, который поставляется с каркасом:

public class GaeAuthenticator extends Authenticator {
    /**
     * The GAE UserService that provides facilities to check whether a user has
     * authenticated using their Google Account
     */
    private UserService userService = UserServiceFactory.getUserService();

    /**
     * Constructor setting the mode to "required".
     * 
     * @param context
     *            The context.
     * @see #Authenticator(Context)
     */
    public GaeAuthenticator(Context context) {
        super(context);
    }

    /**
     * Constructor using the context's default enroler.
     * 
     * @param context
     *            The context.
     * @param optional
     *            The authentication mode.
     * @see #Authenticator(Context, boolean, Enroler)
     */
    public GaeAuthenticator(Context context, boolean optional) {
        super(context, optional);
    }

    /**
     * Constructor.
     * 
     * @param context
     *            The context.
     * @param optional
     *            The authentication mode.
     * @param enroler
     *            The enroler to invoke upon successful authentication.
     */
    public GaeAuthenticator(Context context, boolean optional, Enroler enroler) {
        super(context, optional, enroler);
    }

    /**
     * Integrates with Google App Engine UserService to redirect
     * non-authenticated users to the GAE login URL. Upon successful login,
     * creates a Restlet User object based values in GAE user object. The GAE
     * "nickname" property gets mapped to the Restlet "firstName" property.
     * 
     * @param request
     *            The request sent.
     * @param response
     *            The response to update.
     * @return True if the authentication succeeded.
     */
    @Override
    protected boolean authenticate(Request request, Response response) {
        ClientInfo info = request.getClientInfo();
        if (info.isAuthenticated()) {
            // The request is already authenticated.
            return true;
        } else if (userService.isUserLoggedIn()) {
            // The user is logged in, create restlet user.
            com.google.appengine.api.users.User gaeUser = userService
                    .getCurrentUser();
            User restletUser = new User(gaeUser.getUserId());
            restletUser.setEmail(gaeUser.getEmail());
            restletUser.setFirstName(gaeUser.getNickname());
            info.setUser(restletUser);
            info.setAuthenticated(true);
            return true;
        } else {
            // The GAE user service says user not logged in, let's redirect him
            // to the login page.
            String loginUrl = userService.createLoginURL(request
                    .getOriginalRef().toString());
            response.redirectTemporary(loginUrl);
            return false;
        }
    }
}
1 голос
/ 19 января 2012

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

Имейте в виду, что доступ к memchaced должен быть таким же безопасным, как и доступ к вашей базе данных, поскольку в ней хранятся пароли. Это одна из причин, по которой многие сайты используют OAuth, особенно OAuth 2, где вы раздаете токен краткосрочного доступа и токен долгосрочного обновления, который при необходимости получит новый токен доступа.

1 голос
/ 19 января 2012

Добро пожаловать в мир представительского государственного Tranfer Security! Знаете, я отправил сообщение Рою Филдингу, в котором спрашивал, как вы можете создать действительно RESTful-сервис, который также был бы безопасным. Он еще не вернулся ко мне.

На самом деле вашими двумя вариантами являются Basic Auth (будем надеяться использовать SSL или какой-то смысл) или OAuth. Для всех решений, с которыми я сейчас работаю, мы используем OAuth. Хотя это усложняет тестирование, оно очень безопасно и позволяет нам создавать внешние интерфейсы API из наших сервисов.

Я не советую использовать куки для хранения информации о сеансе. Это не только нарушает дух REST, но также открывает ваше приложение для перехвата сессии. Одна вещь, которую вы можете сделать, чтобы ускорить процесс, - это поддерживать хороший кэш второго уровня с пользовательской информацией, чтобы ваши запросы фактически не попадали в БД для каждого входящего запроса. Это может дать значительное увеличение скорости. Эта тактика одинаково хорошо работает как для основного автора, так и для Oauth.

1 голос
/ 19 января 2012

Существуют различные способы реализовать «билет авторизации» (Google, и вы, вероятно, найдете некоторые ссылки, отличные от OAuth) с файлами cookie, чтобы не для каждого запроса требовался запрос к базе данных.Тем не менее, они обычно включают в себя ключ шифрования.

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

Как заявляет Восприятие, добавление файлов cookie (состояния) в проект системы без сохранения состояния является своего рода обманом.

0 голосов
/ 20 января 2012

Ответ оказался кеш .

В моем конкретном случае я использовал RESTeasy в качестве среды REST и Google App Engine в качестве сервера приложений.Было несложно узнать, что GAE поддерживает memcache .

Если вы используете Objectify (вам действительно следует; это потрясающе), это дажеПолегче.Просто аннотируйте свои классы сущностей с помощью @ Cached .Эта процедура иллюстрируется здесь .

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

В качестве заключительного замечания я рассмотрю возможность использования Дайджест-аутентификация вместо Basic .Кажется, намного безопаснее.Тот факт, что пароль никогда не передается по сети, действительно меня радует.

Я надеюсь, что этот ТАК вопрос был полезен кому-то и тем, кто мне помог: спасибо.:)

...