30

我们有基于 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"
}

我错过了什么吗?请建议。

4

4 回答 4

44

使用 spring-security-oauth2 2.0.5.RELEASE 或以上版本

在基于 java 的配置中,经过测试并且工作正常,它以某种方式覆盖了 TokenEndpoint 类的 RequestMapping 值。

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {      

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                .pathMapping("/oauth/token", "<your custom endpoint>")
        }
}
于 2015-01-09T11:58:29.263 回答
6

刚为此苦苦挣扎了几天,但现在可以在最新的 Spring Oauth2 1.0.5.RELEASE 上运行。我不是 100% 确定我的解决方案是最经典的(尤其是第 4 步),但它有效并且我能够继续前进。

就我而言,我想/oauth从 url 中删除前缀,以仅以/tokenand结尾/authorize。我的解决方案主要是 xml 配置,有两个技巧可以覆盖端点请求映射。

1 - 在应用程序上下文 xml 中,向您的元素添加authorization-endpoint-url和属性。token-endpoint-url<oauth:authorization-server>

矿:

<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 中,相应地调整安全端点。应该有两个,分别管理令牌和身份验证 URL 的安全性。需要更新模式道具<http><intercept-url>标签。

矿:

<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 中,您应该已经将clientCredentialsTokenEndpointFilterbean 作为<custom-filter> within yourelement. So, within the filter's bean, add afilterProcessesUrl` 属性连接。

矿:

<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 库带有两个类:AuthorizationEndpointTokenEndpoint. 每个都使用@RequestMapping类型注释来绑定 url(就像我们对项目的应用程序控制器所做的那样)。对我来说,除了(可悲地)在我的 src 文件夹中重新创建 spring 类包,将 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's 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>
于 2014-05-25T11:07:31.560 回答
5

要自定义令牌端点 URL,请执行以下步骤。

1) 编写您自己的类来扩展 ClientCredentialsTokenEndpointFilter 类并使用“/external/oauth/token”值调用 ClientCredentialsTokenEndpointFilter 类构造函数。

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”

于 2014-04-02T08:56:37.813 回答
4

你让这比它应该做的更难,它实际上非常简单!(注意我使用“oauth2:”而不是“oauth:”作为 XML 标签)

  1. 转到您的 security-context.xml

  2. 在上述文件中找到“oauth2:authorization-server”。

    <oauth2:authorization-server
                    client-details-service-ref="someService"
                    request-validator-ref="someScopeRequestValidator"
                    token-services-ref="someTokenServices" >
    
  3. 只需添加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"** >
    
于 2014-12-17T18:41:50.150 回答