Подтвердить что ты не робот

Попытка защитить ресурсы с помощью OAuth в Spring MVC

У нас уже есть веб-службы REST, написанные на Java на Spring MVC, и я пытался их защитить.

Сервер OAuth реализован на другом веб-узле, который обрабатывает вход в систему и создает токен доступа. Поэтому мне нужно проверить правильность доступа к токену доступа, прежде чем предоставить пользователям доступ к веб-службам.

Однако документация для Spring Безопасность с OAuth кажется очень бедной, а примерный код на самом деле не объясняет, что он делает! Я даже не уверен, что я должен реализовать его для этого, так как это должна быть такая простая проверка.

Каков наилучший способ защиты этих веб-сервисов? И какой лучший способ начать работу?

Спасибо за помощь.

4b9b3361

Ответ 1

Внимание!

[Редактировать 12/27/2012: учебник, приведенный ниже, теперь бросает 404. Существует немного обновленная версия этого руководства по github. Я ударил по ссылкам, которые выглядят плохо. На данный момент я оставляю это как есть для потомков, так как теперь отсутствующий учебник - это тот, на который ссылается ассер. Насколько мне известно, информация, содержащаяся здесь, по-прежнему полезна, поэтому, возможно, когда-нибудь, когда у меня будет время, я переписал ее против нового учебника.]

Этот ответ предполагает, что "сервер OAuth реализован на другом веб-сайте, который обрабатывает вход в систему и создание токена доступа". Вы имеете в виду, что вы потребляете услугу на отдельном сайте, который не является вашим собственным.


Фон

Я, безусловно, могу сказать о ваших проблемах с документацией. Spring Безопасность, возможно, самая крутая кривая обучения любого проекта Spring, а поддержка OAuth довольно новая и поддерживается отдельно от Spring Security. Документы безопасности OAuth Spring разрежены.

Если у вас нет хорошего отношения к OAuth, идите один!. Вы просите своих пользователей доверять безопасности вашего сайта в соответствии с этим стандартом. Таким образом, вы не можете позволить себе какую-либо двусмысленность в своем понимании предмета! Очевидным местом для начала является OAuth.net и Руководство для начинающих OAuth at huniverse.

Если/Если у вас есть хорошее представление о том, как работает OAuth, я бы настоятельно рекомендовал прочитать Spring Security "Getting Started "и " Статьи и учебные пособия", чтобы получить хорошее представление о том, как Spring Безопасность реализована в целом.

Как только у вас есть достойное знание Spring Безопасность и приличное знание OAuth, официальное руководство пользователя Spring Security OAuth начнет иметь смысл. Вы хотите обратить особое внимание на разделы "Потребитель/Клиент" для версии OAuth, с которой вы работаете (1.0 или 2.0).

Этот же сайт также имеет приличный tutorial для OAuth 1.0 и OAuth 2.0, который основан на второй раздел служб Руководство для начинающих OAuth, упомянутое выше.

Доступ к защищенным ресурсам с сохранением

Для вашей проблемы мы сосредоточимся на реализации службы печати фотографий Tonr с tutorial, упомянутых выше. Эта служба печатает фотографии, которые являются защищенными OAuth ресурсами, размещенными на внешних сайтах. Tonr отправляется на эти сайты для контроля доступа этих ресурсов. Это будет включать перенаправление пользователя для аутентификации пользователя и подтверждения аутентификации, если это необходимо.

Spring -MVC REST сервисы/контроллеры, которые сами являются потребителями внешних OAuth-защищенных ресурсов, реализуют это поведение "отложенного авторизации" (мой термин) с помощью фильтров запросов. В 1.0 руководство пользователя

Есть два фильтра запросов, которые применимо к потребителю OAuth логика. Первый фильтр, OAuthConsumerContextFilter, является ответственный за создание OAuth-специфический контекст безопасности, очень аналогично Spring Security SecurityContext. Контекст безопасности просто содержит набор токенов доступа которые были получены для текущий пользователь. Этот контекст безопасности при подаче заявок на защищенных ресурсов.

Существует еще один фильтр запросов, OAuthConsumerProcessingFilter, что могут применяться к определенным URL-адресам или URL-адресу шаблоны, требующие доступа к удаленный защищенный ресурс. Ввод этот фильтр в Spring Security цепь фильтра гарантирует, что токены доступа, необходимые для указанного URL-адреса будут получены до разрешая доступ к ресурсам.

Итак, как вы можете видеть, для OAuth 1.0 фильтрация запросов с допустимым OAuthConsumerProcessingFilter будет обрабатывать все, что связано с приобретением действительных токенов доступа, а также уведомлять пользователя о том, что доступ запрещен. Также существуют соответствующие OAuth2ClientContextFilter и OAuth2ClientProcessingFilter классы.

Наконец, как только все будет настроено, вы можете получить доступ к ресурсам, защищенным OAuth, в ваших контроллерах с помощью OAuthRestTemplate или OAuth2RestTemplate, как если бы вы получили доступ к незащищенным ресурсам с помощью обычного RestTemplate (info здесь). Однако они должны быть введены в ваш сервис или контроллер экземпляром ProtectedResourceDetails или OAuth2ProtectedResourceDetails.

У меня есть хорошие новости, если это звучит сложно. Вся эта глупость обычно абстрагируется и обрабатывается вами с помощью пространств имен OAuth и OAuth2 XML

Пространство имен oauth показано в файлах конфигурации XML Tonr tutorials, расположенных в соответствующих каталогах src/webapp/WEB-INF. Нижеприведенные примеры сокращены непосредственно оттуда.

Если вы хотите увидеть, как работает сторона поставщика без использования пространств имен OAuth, я бы посоветовал вам проверить этот пост форума SpringSource, и выполните обновление SECOAUTH-53 для обновлений.

OAuth 1.0 Пример

Tonr потребляет OAuth-защищенные сервисы от Sparklr и Google здесь, поэтому он устанавливает ProtectedResourceDetailsService, называемый resourceDetails, с помощью тега oauth:resource-details-service. Затем он устанавливает OAuthConsumerContextFilter и OAuthConsumerProcessingFilter со ссылкой на resourceDetails с помощью тега oauth:consumer. Эти фильтры создаются с экземплярами ProtectedResourceDetails для каждого из защищенных поставщиков ресурсов с помощью тега oauth:resource.


Из tonr applicationContext.xml:

<oauth:consumer resource-details-service-ref="resourceDetails" oauth-failure-page="/oauth_error.jsp">
  <oauth:url pattern="/sparklr/**" resources="sparklrPhotos"/>
  <oauth:url pattern="/google/**" resources="google"/>
</oauth:consumer>

<oauth:resource-details-service id="resourceDetails">
  <oauth:resource id="sparklrPhotos"
                  key="tonr-consumer-key"
                  secret="SHHHHH!!!!!!!!!!"
                  request-token-url="http://localhost:8080/sparklr/oauth/request_token"
                  user-authorization-url="http://localhost:8080/sparklr/oauth/confirm_access"
                  access-token-url="http://localhost:8080/sparklr/oauth/access_token"/>
  <!--see http://code.google.com/apis/accounts/docs/OAuth_ref.html-->
  <oauth:resource id="google" key="anonymous" secret="anonymous"
                  request-token-url="https://www.google.com/accounts/OAuthGetRequestToken"
                  user-authorization-url="https://www.google.com/accounts/OAuthAuthorizeToken"
                  access-token-url="https://www.google.com/accounts/OAuthGetAccessToken"
                  request-token-method="GET"
                  access-token-method="GET">
    <oauth:addtionalParameter name="scope" value="https://picasaweb.google.com/data/"/>
    <oauth:addtionalParameter name="xoauth_displayname" value="Tonr Example Application"/>
  </oauth:resource>
</oauth:resource-details-service>


Затем создаются sparklrService и googleService beans, каждый со своим собственным внутренним OAuthRestTemplate bean, каждый из которых снабжен ссылкой через constructor-arg в соответствующий ProtectedResourceDetails, которые были созданы ранее и введены в ProtectedResourceDetailsService bean.


Из tonr spring -servlet.xml:

<bean id="sparklrService" class="org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl">
  <property name="sparklrPhotoListURL" value="${sparklrPhotoListURL}"/>
  <property name="sparklrPhotoURLPattern" value="${sparklrPhotoURLPattern}"/>
  <property name="sparklrRestTemplate">
    <bean class="org.springframework.security.oauth.consumer.OAuthRestTemplate">
      <constructor-arg ref="sparklrPhotos"/>
    </bean>
  </property>

</bean>
<bean id="googleService" class="org.springframework.security.oauth.examples.tonr.impl.GoogleServiceImpl">
  <property name="googleRestTemplate">
    <bean class="org.springframework.security.oauth.consumer.OAuthRestTemplate">
      <constructor-arg ref="google"/>
    </bean>
  </property>

</bean>


Пример OAuth 2.0

Мое понимание здесь немного слабее.. Часть причин для этого состоит в том, что пространство имен OAuth2, похоже, абстрагируется гораздо больше. Кроме того, похоже, что пример Tonr 2 не был выделен, а также оригинальный пример Tonr. Я сделаю все возможное и при необходимости отредактирую.

Сначала создается тег oauth:client и дается ссылка на InMemoryOAuth2ClientTokenServices bean. Похоже, что это устанавливает соответствующие фильтры. Затем OAuth2ProtectedResourceDetails beans создаются как для sparklr, так и для Facebook с помощью oauth:resource.


Из tonr 2 applicationContext.xml:

<!--apply the oauth client context-->
<oauth:client token-services-ref="oauth2TokenServices"/>

<beans:bean id="oauth2TokenServices" class="org.springframework.security.oauth2.consumer.token.InMemoryOAuth2ClientTokenServices"/>

<!--define an oauth 2 resource for sparklr-->
<oauth:resource id="sparklr" type="authorization_code" clientId="tonr"
                  accessTokenUri="http://localhost:8080/sparklr/oauth/authorize"
                  userAuthorizationUri="http://localhost:8080/sparklr/oauth/user/authorize"/>

<!--define an oauth 2 resource for facebook. according to the facebook docs, the 'clientId' is the App ID, and the 'clientSecret' is the App Secret -->
<oauth:resource id="facebook" type="authorization_code" clientId="162646850439461" clientSecret="560ad91d992d60298ae6c7f717c8fc93"
                  bearerTokenMethod="query" accessTokenUri="https://graph.facebook.com/oauth/access_token"
                  userAuthorizationUri="https://www.facebook.com/dialog/oauth"/>


Далее, как и в предыдущем примере, каждый контроллер или служба bean, которая нуждается в доступе к защищенному ресурсу, создается с помощью внутреннего OAuth2RestTemplate bean. Этот внутренний bean получает ссылку на правильный OAuth2ProtectedResourceDetails bean через constructor-arg.


От tonr 2 spring -servlet.xml:

<bean id="facebookController" class="org.springframework.security.oauth.examples.tonr.mvc.FacebookController">
  <!-- snipped irrelevant properties -->
  <property name="facebookRestTemplate">
    <bean class="org.springframework.security.oauth2.consumer.OAuth2RestTemplate">
      <constructor-arg ref="facebook"/>
    </bean>
  </property>
  <property name="tokenServices" ref="oauth2TokenServices"/>
</bean>

<bean id="sparklrService" class="org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl">
  <!-- snipped irrelevant properties -->
  <property name="sparklrRestTemplate">
    <bean class="org.springframework.security.oauth2.consumer.OAuth2RestTemplate">
      <constructor-arg ref="sparklr"/>
    </bean>
  </property>
  <property name="tokenServices" ref="oauth2TokenServices"/>
</bean>