2015-01-29 2 views
4

Я очень новичок в веб-сервисах. Я выставил некоторые услуги REST с использованием Jersey 2 в интеграции с Spring. Теперь мне нужно защитить эти службы отдыха, используя аутентификацию с именем пользователя/паролем. Мне сказали не использовать весеннюю безопасность.услуги по обеспечению безопасности в Джерси

Я понятия не имею, как это сделать. Я выполнял поиск в сети, но различные ссылки показывают различную реализацию, и я не могу решить, как это сделать.

Я знаю, что это что-то неопределенное, но, пожалуйста, помогите в этом контексте.

+0

Взгляните на http://stackoverflow.com/questions/10826293/restful-authentication-via-spring – Hannes

ответ

11

Общим способом аутентификации с использованием имени пользователя и пароля является использование Basic Authentication. В основном клиенту необходимо отправить заголовок запроса Authorization, а значение заголовка - Basic Base64Encoded(username:password). Так мое имя пользователя является peeskillet и мой пароль pass, я, как клиент, должны установить заголовок, как

Authorization: Basic cGVlc2tpbGxldDpwYXNz 

В среде сервлетов, контейнер должен иметь поддержку для обычной проверки подлинности. Вы настроили эту поддержку на web.xml. Вы можете увидеть пример в 48.2 Securing Web Applications учебника Java EE. Вы также заметите в примере

<transport-guarantee>CONFIDENTIAL</transport-guarantee> 

Это для поддержки SSL. Это рекомендуется для базовой проверки подлинности.

Если вы не хотите иметь дело с проблемами, связанными с доменами безопасности и модулями входа, модулем и т. Д., Которые потребуются для настройки поддержки сервлетов или если вы просто не находитесь в среде сервлетов , реализация Basic Auth в ContainerRequestFilter действительно не слишком сложна.

Вы можете увидеть полный пример того, как это можно сделать при jersey/examples/https-clientserver-grizzly. Вы должны сосредоточиться на SecurityFilter

Основной поток в фильтре идет что-то вроде этого

  1. Получить заголовок Authorization. Если этого не существует, введите AuthenticationException. В этом случае AuthenticationExceptionMapper будет посылать заголовок "WWW-Authenticate", "Basic realm=\"" + e.getRealm() + "\", который является частью протокола Basic Auth

  2. После того, как у нас есть заголовок, разбираемого это просто, чтобы получить кодировкой Base64 логин: пароль. Затем мы расшифруем его, затем разделим, а затем разделим имя пользователя и пароль. Если какой-либо из этих процессов выходит из строя, снова введите WebApplicationException, который отображает 400 Bad Request.

  3. Проверьте имя пользователя и пароль. Исходный код примера просто проверяет, является ли имя пользователя user, а пароль password, но вы хотите использовать некоторую услугу в фильтре для проверки этой информации. Если какой-либо из них терпят неудачу, бросают AuthenticationException

  4. Если все идет хорошо, А User создается из метода authenticate, и вводится в Authorizer (который является SecurityContext). В JAX-RS обычно используется для авторизации SecurityContext.

Для авторизации, если вы хотите, чтобы обеспечить определенную области для определенных ресурсов, вы можете использовать @RolesAllowed аннотации для классов или методов. Джерси поддерживает эту аннотацию, registering the RolesAllowedDynamicFeature.

Что происходит под капотом, так это то, что SecurityContext будет получен из запроса. С примером, с которым я связан, вы можете видеть Authorizer, он имеет переопределенный метод isUserInRole. Этот метод будет вызываться для проверки на значение (ы) в @RolesAllowed({"ADMIN"}). Поэтому, когда вы создаете SecurityContext, вы должны обязательно включить в переопределенный метод, роли пользователя.

Для тестирования вы можете просто использовать браузер. Если все настроено правильно, при попытке доступа к ресурсу вы должны увидеть (в Firefox) диалоговое окно, как показано в this post. Если вы используете cURL, вы могли бы сделать

C:/>curl -v -u username:password http://localhost:8080/blah/resource 

Это будет посылать запрос Basic Authenticated. Из-за переключателя -v вы должны увидеть все задействованные заголовки. Если вы просто хотите протестировать клиентский API, вы можете увидеть here, как его настроить. В любом из трех упомянутых случаев кодировка Base64 будет выполнена для вас, поэтому вам не придется беспокоиться об этом.

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

1

Security поставляется в двух основных вариантах:

  • Контейнер На основе
  • приложений на основе

стандартный способ обеспечения пружинные приложений заключается в использовании Spring Security (ранее Acegi). Было бы интересно узнать, почему вам не разрешают использовать это.

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

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

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

  • BASIC
  • Digest
  • Форма
  • Сертификата

Приложения REST обычно должны быть «без гражданства», что, по сути, исключает проверку подлинности на основе форм (потому что вам потребуется использование сеанса) , оставляя вас с BASIC, дайджестом и сертификатом.

Ваш следующий вопрос: кто я аутентифицируюсь. Если вы можете ожидать узнать имя пользователя и пароль пользователя в зависимости от того, какой URL-адрес они запросили (скажем, если это один набор учетных данных для всех пользователей), то Digest - лучший выбор, поскольку пароль никогда не отправляется, а только хэш. Если вы не можете узнать пароль (потому что вы просите стороннюю систему проверить его и т. Д.), То вы застряли с BASIC. Но вы можете повысить безопасность BASIC с помощью SSL или, еще лучше, объединения BASIC с аутентификацией сертификата клиента. Фактически аутентификация BASIC через HTTPS является стандартной методикой обеспечения безопасности большинства приложений REST.

Вы можете легко реализовать сервлет-фильтр, который ищет заголовок аутентификации и самостоятельно проверяет учетные данные. Есть много примеров таких фильтров, это один автономный файл класса. Если учетные данные не найдены, фильтр возвращает 401, передавая приглашение для базового auth в заголовках ответов. Если учетные данные недействительны, вы возвращаетесь 403. Безопасность приложений - это почти целая карьера сама по себе, но я надеюсь, что это поможет.

+0

Спасибо, Ричард .. упомянул в последнем абзаце вам..это означает, что вы проверяете учетные данные в фильтре сам по отношению к некоторым таблицам базы данных, где можно сохранить имя пользователя и пароль? – Anand

+0

Да .. Но если вы создадите фильтр внутри Spring, вы можете ввести в этот фильтр все, что вам нужно, чтобы действительно выполнить аутентификацию (соединение с базой данных и т. Д.). Поэтому я, вероятно, рекомендую создать фильтр весеннего сервлета. – Richard

1

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

Если вы используете tomcat, вы можете установить realm, что относительно просто реализовать. Вы можете использовать JDBCRealm, который вводит пользователя и пароль из указанных столбцов в вашей базе данных и настраивает его через server.xml и web.xml. Это будет автоматически запрашивать учетные данные, каждый раз, когда вы пытаетесь получить доступ к вашему приложению. Для этого вам не нужна реализация на стороне приложения.

1

Теперь я могу сказать вам, что вы уже сделали большую часть «грязной» работы, интегрирующей Джерси с весной. Я рекомендую вам обратиться к решению на основе приложений, не привязывает ли вы к определенному контейнеру. Spring Security может быть пугающей сначала, но тогда, когда вы приручите зверя, вы видите, что это был действительно дружелюбный щенок.

Дело в том, что Spring Security чрезвычайно настраивается, просто реализуя свои интерфейсы. И есть много документации и поддержки. Кроме того, у вас уже есть приложение на основе Spring.

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

http://www.baeldung.com/rest-with-spring-series/ http://www.baeldung.com/2011/10/31/securing-a-restful-web-service-with-spring-security-3-1-part-3/

1

На самом деле это сделал, вчера.

Так что это действительно то, что вы хотели бы достичь. Мое дело состояло в том, чтобы заставить эту работу работать с мобильным телефоном и JavaScript с одной страницей.

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

Так вы конечной точки в ведьма вы ждете пост с пользователя/пароль:

@Path("/login") 
public class AuthenticationResource { 

@POST 
@Consumes("application/json") 
public Response authenticate(Credentials credential) { 
    boolean canBeLoggedIn = (...check in your DB or anywher you need to) 

    if (canBeLoggedIn) { 
     UUID uuid = UUID.randomUUID(); 
     Token token = new Token(); 
     token.setToken(uuid.toString()); 
     //save your token with associated with user 
     (...) 

     return Response.ok(token).type(MediaType.APPLICATION_JSON_TYPE).build(); 
    } else { 
     return Response.status(Response.Status.UNAUTHORIZED).build(); 
    } 
} 

}

Теперь вы должны обеспечить ресурс с необходимостью для этой лексемы:

@Path("/payment") 
    @AuthorizedWithToken 
    public class Payments { 

    @GET 
    @Produces("application/json") 
    public Response sync() { 
    (...) 
    } 

} 

Обратите внимание на аннотацию @AuthorizedWithToken. Это annotaation вы можете создать на своей собственной, используя специальной мету аннотации @NameBinding

@NameBinding 
@Target({ElementType.METHOD, ElementType.TYPE}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface AuthorizedWithToken {} 

И теперь для фильтра, который реализует проверки заголовка:

@AuthorizedWithToken 
@Provider 
public class XAuthTokenFilter implements ContainerRequestFilter { 

    private static String X_Auth_Token = "X-Auth-Token"; 

    @Override 
    public void filter(ContainerRequestContext crc) throws IOException { 
     String headerValue = crc.getHeaderString(X_Auth_Token); 
     if (headerValue == null) { 
      crc.abortWith(Response.status(Response.Status.FORBIDDEN).entity("Missing " + X_Auth_Token + " value").build()); 
      return; 
     } 

     if(! TOKEN_FOUND_IN_DB) { 
      crc.abortWith(Response.status(Response.Status.UNAUTHORIZED).entity("Wrong " + X_Auth_Token + " value").build()); 
      return; 
     } 
    } 
} 

Вы можете создать любое количество собственных аннотаций проверки для различные вещи в запросе http и смешивать их. Однако вам нужно обратить внимание на Приоритеты, но это на самом деле легко найти. Этот метод требует использования https, но это очевидно.

Смежные вопросы