Важно
[Редактировать 27.12.2012. В приведенном ниже учебнике, на который я ссылаюсь, теперь выдается 404. На github есть немного обновленная версия этого учебника. Я пробил ссылки, которые кажутся плохими. А пока я оставляю это как есть для потомков, так как пропавший учебник - тот, на который ссылается спрашивающий. Насколько мне известно, информация, содержащаяся в этом документе, по-прежнему полезна , поэтому, возможно, когда-нибудь, когда у меня будет время, я перепишу ее с новым учебником.]
В этом ответе предполагается, что «сервер OAuth реализован на другом веб-сайте, который обрабатывает вход в систему и создание токена доступа». Вы имеете в виду, что вы пользуетесь услугой на отдельном сайте, который не принадлежит вам.
1011 *
*
Фон
Я, конечно, могу относиться к вашим проблемам с документацией. В Spring Security, пожалуй, самая крутая кривая обучения среди всех проектов Spring, и поддержка OAuth довольно новая и поддерживается отдельно от Spring Security. Документы Spring Security OAuth являются разреженными.
Если у вас нет хорошего восприятия OAuth, найдите его! Вы просите своих пользователей доверять безопасности реализации этого стандарта на вашем сайте. Таким образом, вы не можете допустить двусмысленности в понимании предмета! Очевидное место для начала - OAuth.net и Руководство для начинающих OAuth в Вселенной.
Если / как только вы почувствуете, как работает OAuth, я настоятельно рекомендую прочитать списки документации Spring Security " Getting Started " и " Articles and Tutorials " чтобы понять, как вообще реализована Spring Security.
Как только вы получите достаточные знания о Spring Security и примете OAuth, официальное руководство пользователя Spring Security OAuth начнет обретать смысл. Вы должны обратить внимание, в частности, на разделы Consumer / Client для версии OAuth, с которой вы работаете ( 1.0 или 2.0 ).
На этом же сайте также есть приличное учебное пособие для OAuth 1.0 и OAuth 2.0, основанное на втором разделе сервисов Руководство для начинающих OAuth упомянутое выше.
Доступ к защищенным ресурсам Restful
Для вашей проблемы мы сосредоточимся на реализации сервиса фотопечати Tonr из учебника , упомянутого выше. Этот сервис печатает фотографии, которые являются OAuth-защищенными ресурсами, размещенными на внешних сайтах. Tonr использует эти сайты для контроля доступа к этим ресурсам. Это будет включать в себя перенаправление пользователя для аутентификации пользователя и подтверждение аутентификации при необходимости.
Сервисы / контроллеры Spring-MVC REST, которые сами являются потребителями внешних ресурсов, защищенных OAuth, реализуют это поведение «отложенной авторизации» (мой термин) с помощью фильтров запросов. В соответствии с 1.0 руководство пользователя :
Есть два фильтра запросов, которые
применимо к потребителю OAuth
логика. Первый фильтр,
OAuthConsumerContextFilter , есть
ответственность за создание
OAuth-специфический контекст безопасности, очень
похож на Spring Security's
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, расположенных в соответствующих каталогах 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
.
Из приложения tonrContext.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
, каждый со своим внутренним компонентом OAuthRestTemplate
, каждый из которых получает ссылку через constructor-arg
на соответствующий ProtectedResourceDetails
, который был создан ранее и введен в ProtectedResourceDetailsService
боб.
Из файла 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
.Похоже, что это устанавливает соответствующие фильтры.Затем создаются бобы OAuth2ProtectedResourceDetails
для sparklr и Facebook с oauth:resource
.
Из приложения tonr 2Context.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"/>
Далее, как и в предыдущем примере, каждый контроллер или компонент службы, которому требуется доступ к защищенному ресурсу, создается с помощью внутреннего компонента OAuth2RestTemplate
.Этому внутреннему компоненту дается ссылка на правильный компонент OAuth2ProtectedResourceDetails
через constructor-arg
.
Из Spring-servlet.xml 2 тонры:
<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>