jax-rs rest аутентификация и авторизация веб-сервиса - PullRequest
7 голосов
/ 15 января 2012

У меня есть веб-приложение, которое должно позволить пользователям, использующим различные веб-клиенты (браузер, собственное мобильное приложение и т. Д.), Регистрироваться. После входа они могут получить доступ к ограниченному контенту или своему собственному контенту (например, к создаваемым им записям и т. Д.).

То, что я сделал до сих пор: я создал веб-сервис jax-rs rest (я размещаю свое приложение на glassfish), который предоставляет следующие методы:

  • регистрация - пользователь POST выбирает желаемое имя пользователя, пароль, адрес электронной почты и т. Д .; если имя пользователя / адрес электронной почты уникальны, запись для этого пользователя создается в базе данных (я использую Hibernate для персистентности)
  • логин - имя пользователя и пароль пользователя POST. Если они в порядке, UUID создается и возвращается пользователю (это будет использоваться в качестве токена для будущих запросов). У меня есть таблица с именем logedusers, с userID, токеном, validSince в качестве столбцов.

Здесь меня это сбивает с толку.

Допустим, у меня есть другой метод, getUserEntries, который должен возвращать все записи, сделанные пользователем. Чтобы сделать это более понятным, будет таблица Entry со следующими полями: entryId, userId, text.

Какой здесь лучший подход?

Что я делаю сейчас, я делаю запрос на получение и передаю токен следующим образом:

localhost:8080/myApp/getUserEntries?token=erf34c34

После этого, если токен действителен, я получаю userID из таблицы logedusers и, основываясь на этом userId, получаю все записи и возвращаю их как json.

Примерно так:

@GET
@Path("getUserEntries")
@Produces(MediaType.APPLICATION_JSON)
public Response getUserEntries(@QueryParam("token") String token) {      
    String userId=getUserIdFromToken(token);
    if (userId == null){
        return Response.status(Response.Status.UNAUTHORIZED).build();
    } else {
        //get some data associated with that userId, put it in the response object and send it back
        return Response.ok().entity(response).build();
    }
}

Однако что произойдет, если у меня будет больше методов, предоставляющих данные, если они вызываются действительным пользователем?

Я должен был бы сделать эту проверку в начале каждого метода.

Я хочу сделать этот процесс авторизации прозрачным

Итак, два основных вопроса здесь:

  1. Этот дизайн в порядке? Все аутентифицируется с помощью user / pass, сервер создает и сохраняет и отправляет токен пользователю, пользователь отправляет токен на будущие запросы.
  2. Что мне делать, если у меня много конечных точек, которые должны определить личность вызывающего пользователя? Могу ли я пометить их некоторыми аннотациями, использовать своего рода провайдера / аутентификатора безопасности (где я могу добавить свою собственную логику для проверки - например, проверить, не является ли токен старше 5 дней и т. Д.).

Спасибо

1 Ответ

2 голосов
/ 16 января 2012

Этот дизайн в порядке?Все аутентифицируется с помощью user / pass, сервер создает и сохраняет и отправляет токен пользователю, пользователь отправляет токен на будущие запросы.

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

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

Что мне делать, если у меня много конечных точек, которым необходимо определить личностьвызывающий пользователь?Могу ли я пометить их некоторыми аннотациями, использовать своего рода провайдера / аутентификатора безопасности (где я могу добавить свою собственную логику для проверки - например, проверить, не является ли токен старше 5 дней и т. Д.).

Им нужна личность?Или им просто нужно знать, что пользователю разрешен доступ к ним?Если последнее, самый простой способ - это поместить подходящую аннотацию @RolesAllowed в метод, в какой момент (с подходящей конфигурацией; см. документы по безопасности JEE5 ).Если первое, вам нужно получить объект HttpServletRequest для текущего действия и вызвать его метод getUserPrincipal() для получения идентификатора пользователя (или ноль, если они еще не вошли в систему). Этот вопрос SO описывает, как получить объект запроса;Есть несколько возможных способов сделать это, но я рекомендую инъекцию с помощью аннотации @Resource.

Чего я не хотел бы делать, так это разрешить пользователям обычно предоставлять свою собственную идентификацию через @QueryParam;это просто дико открыто для злоупотреблений.Вы можете разрешить им задавать вопросы о других пользователях таким образом, но затем вам нужно решить, собираетесь ли вы им что-то сказать или нет, основываясь на том, разрешено ли текущему пользователю что-либо знать о другом пользователе.Это такая сложная проблема безопасности, которая возникает в реальном приложении и является хорошей отправной точкой для того, чтобы нуждаться в текущей проверенной личности пользователя.

...