Как изменить spring оконечную точку маркера oauth2 по умолчанию?
У нас есть приложение spring security oauth2. Все прекрасно работает. Но мне не удалось изменить конечную точку маркера по умолчанию от "/oauth/token" до "/external/oauth/token".
Мой spring -servlet.xml
<http pattern="/external/oauth/token" create-session="stateless"
authentication-manager-ref="clientAuthenticationManager"
use-expressions="true" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/external/oauth/token" access="isFullyAuthenticated()" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<!-- include this only if you need to authenticate clients via request parameters -->
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler"/>
</http>
<oauth:authorization-server client-details-service-ref="clientDetails"
token-services-ref="tokenServices"
user-approval-handler-ref="userApprovalHandler" token-endpoint-url="/external/oauth/token">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<oauth:password />
</oauth:authorization-server>
Но результат при доступе к этой конечной точке
{
error: "unauthorized"
error_description: "An Authentication object was not found in the SecurityContext"
}
Мне что-то не хватает? Пожалуйста, предложите.
Ответы
Ответ 1
С версией 2.0.5.RELEASE или выше spring -security-oauth2
В одной строке в конфигурации на основе Java, проверена и работает нормально, каким-то образом она переопределяет значение RequestMapping класса TokenEndpoint.
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.pathMapping("/oauth/token", "<your custom endpoint>")
}
}
Ответ 2
Просто боролся с этим в течение нескольких дней, но теперь он работает на последнем Spring Oauth2 1.0.5.RELEASE. Я не уверен на 100%, что мое решение является самым классным (шаг 4 в частности), но он работает, и я могу двигаться вперед.
В моем случае я хотел удалить префикс /oauth
из URL-адресов, чтобы в итоге получить только /token
и /authorize
. Решение для меня было главным образом xml config, с двумя хаками, чтобы переопределить сопоставления запросов конечных точек.
1 - В контексте приложения xml добавьте authorization-endpoint-url
и token-endpoint-url
к вашему элементу <oauth:authorization-server>
.
Mine:
<oauth:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler" authorization-endpoint-url="/authorize" token-endpoint-url="/token">
2 - В контекстном приложении xml соответствующим образом настройте конечные точки безопасности. Должно быть два, которые соответственно управляют безопасностью на токенах и auth-адресах. Необходимо обновить шаблонную привязку в тегах <http>
и <intercept-url>
.
Mine:
<http pattern="/token/**" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/token/**" access="IS_AUTHENTICATED_FULLY" />
...
<http pattern="/authorize/**" access-denied-page="/login.jsp?authorization_error=true" disable-url-rewriting="true" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/authorize/**" access="IS_AUTHENTICATED_FULLY" />
3 - (Если вы решили использовать дополнительный фильтр clientCreds.) В контексте приложения xml вы должны уже подключить clientCredentialsTokenEndpointFilter
bean как свойство <custom-filter> within your
element. So, within the filter bean, add a
filterProcessesUrl`.
Mine:
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
<property name="filterProcessesUrl" value="/token" />
</bean>
4 - Последний шаг - переопределить URL-адреса, относящиеся к запросу, для внутренних контроллеров конечных точек. Spring oauth2 lib поставляется с двумя классами: AuthorizationEndpoint
и TokenEndpoint
. Каждый из них использует аннотации типа @RequestMapping
для привязки URL-адреса (как мы все делаем для контроллеров приложений наших проектов). Для меня это было стремление к вытягиванию волос, чтобы попытаться переопределить значение сопоставлений запросов любым способом, кроме как (к сожалению) воссоздать пакет класса Spring в моей папке src, скопировать классы AuthorizationEndpoint и TokenEndpoint дословно папку и отредактировать значения встроенных @RequestMapping
аннотаций.
Во всяком случае, это делает трюк. Хотелось бы услышать более грациозный способ переопределить значения отображения запроса контроллера конечной точки.
Спасибо.
Конечный, рабочий контекст приложения:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:sec="http://www.springframework.org/schema/security" xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
xsi:schemaLocation="
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2.xsd
"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<!-- Declare OAuth2 services white-list. (This is the top of the config.) -->
<oauth:authorization-server client-details-service-ref="clientDetailsService" token-services-ref="tokenServices" user-approval-handler-ref="userApprovalHandler" authorization-endpoint-url="/authorize" token-endpoint-url="/token">
<oauth:authorization-code />
<oauth:implicit />
<oauth:refresh-token />
<oauth:client-credentials />
<!-- <oauth:password /> -->
</oauth:authorization-server>
<bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
<!-- This bean bridges client auth service and user tokens... kind of an out of place requirement. -->
<property name="tokenServices" ref="tokenServices" />
</bean>
<!-- This starts the far back-end config for client token management. -->
<sec:authentication-manager id="clientAuthenticationManager">
<sec:authentication-provider user-service-ref="clientDetailsUserService" />
</sec:authentication-manager>
<bean id="clientDetailsUserService" class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
<constructor-arg ref="clientDetailsService" />
</bean>
<bean id="clientDetailsService" class="com.mycompany.oauth.spring.security.oauth2.IntegratedOauth2ClientDetailsService">
<!-- This bean is what wires OAuth2 into the persistence stack for client details stored in the oauth_client table. -->
</bean>
<!-- OAuth is layered on to spring security which is centered around users which requires a user auth manager. -->
<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
<authentication-provider ref="daoAuthenticationProvider" />
</authentication-manager>
<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userDetailsService" />
</bean>
<bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
<property name="tokenStore" ref="tokenStore" />
<property name="supportRefreshToken" value="true" />
<property name="clientDetailsService" ref="clientDetailsService" />
</bean>
<bean id="tokenStore" class="com.mycompany.oauth.spring.security.oauth2.IntegratedOAuth2TokenStore">
<!-- This bean is what wires OAuth2 tokens into my company application stack. -->
<constructor-arg ref="dataSource" />
</bean>
<!-- **************************************************************************************** -->
<!-- Finally, sew OAuth into spring security with some http tags... -->
<!-- **************************************************************************************** -->
<!-- The OAuth2 endpoint for direct token requests (i.e. for client_credentials flow). -->
<http pattern="/token/**" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/token/**" access="IS_AUTHENTICATED_FULLY" />
<anonymous enabled="false" />
<http-basic entry-point-ref="clientAuthenticationEntryPoint" />
<custom-filter ref="clientCredentialsTokenEndpointFilter" before="BASIC_AUTH_FILTER" />
<access-denied-handler ref="oauthAccessDeniedHandler" />
</http>
<bean id="clientCredentialsTokenEndpointFilter" class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
<property name="authenticationManager" ref="clientAuthenticationManager" />
<property name="filterProcessesUrl" value="/token" />
</bean>
<bean id="clientAuthenticationEntryPoint" class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
<property name="realmName" value="myrealm" />
</bean>
<bean id="oauthAccessDeniedHandler" class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
<!-- The OAuth2 endpoint for user-approved authorization (i.e. for "authorization" flow involving user login/approve). -->
<http pattern="/authorize/**" access-denied-page="/login.jsp?authorization_error=true" disable-url-rewriting="true" xmlns="http://www.springframework.org/schema/security">
<intercept-url pattern="/authorize/**" access="IS_AUTHENTICATED_FULLY" />
<form-login authentication-failure-url="/login.jsp?authentication_error=true" default-target-url="http://www.mycompany.com/" login-page="/login.jsp" login-processing-url="/login.do" />
<http-basic />
<anonymous />
</http>
</beans>
Ответ 3
Вы делаете это сложнее, чем должно быть, это на самом деле очень просто!
(Обратите внимание, что я использую "oauth2:" вместо "oauth:" в качестве XML-тега)
-
Перейдите в свой security-context.xml
-
Найдите в файле выше "oauth2: authorization-server".
<oauth2:authorization-server
client-details-service-ref="someService"
request-validator-ref="someScopeRequestValidator"
token-services-ref="someTokenServices" >
-
Просто добавьте token-endpoint-url="/oauth/whatever_you_like"
<oauth2:authorization-server
client-details-service-ref="someService"
request-validator-ref="someScopeRequestValidator"
token-services-ref="someTokenServices"
**token-endpoint-url="/oauth/whatever_you_like"** >
Ответ 4
Для настройки URL конечной точки маркера выполните следующие шаги.
1) Напишите свой собственный класс, который расширяет класс ClientCredentialsTokenEndpointFilter и вызывает конструктор класса ClientCredentialsTokenEndpointFilter со значением "/external/oauth/token".
super("/external/oauth/token");
2) Подключите новый фильтр настройки в конфигурации безопасности.
Заменить
<custom-filter ref="clientCredentialsTokenEndpointFilter" after="BASIC_AUTH_FILTER" />
с
<custom-filter ref="your customize filter" after="BASIC_AUTH_FILTER" />
3) Создайте свой собственный класс для нового сопоставления (/external/oauth/token) и продолжите токененд-точку.
4) Измените значение атрибута шаблона элемента http и intercept-url на "/external/oauth/token"