【问题标题】:In Spring OAuth2, why is my resource still unprotected even though I have marked it in my resource server?在 Spring OAuth2 中,即使我在资源服务器中标记了资源,为什么我的资源仍然不受保护?
【发布时间】:2016-09-02 00:51:22
【问题描述】:

我,

我正在使用 Spring 3.2.11.RELEASE 和 spring-security-oauth2 v 2.0.7.RELEASE。我想设置一个资源服务器,这样如果客户端正确提交了他们的 id 和 secret 并使用了 client_credentials 的授权类型,他们可以使用生成的令牌将数据 POST 到 URL。但是,我不知道如何保护该 URL(即使令牌不正确,我也可以 POST 到该 URL)。以下是我尝试配置资源服务器的方式

<oauth:resource-server id="resourceServerFilter" entry-point-ref="entry"
    resource-id="writeUrl" token-services-ref="tokenServices" />

<bean id="entry" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <constructor-arg value="/writeUrl" />
</bean>

<oauth:client-details-service id="clientDetails">
    <oauth:client client-id="my-client-with-secret"
        authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
        scope="read,write" secret="secret" />
</oauth:client-details-service>

但是,正如我所说,将数据发布到“/writeUrl”无论我是否拥有有效的令牌都是成功的,并且我希望锁定该 URL。我怎么做?我完整的 OAuth2 应用程序上下文配置如下……

<http pattern="/oauth/token" create-session="stateless" authentication-manager-ref="clientAuthenticationManager" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/oauth/token" access="IS_AUTHENTICATED_FULLY" />
    <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>

<!-- The OAuth2 protected resources are separated out into their own block 
    so we can deal with authorization and error handling separately. This isn't 
    mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/oauth/(users|clients)/.*" request-matcher="regex"
    create-session="stateless" entry-point-ref="oauthAuthenticationEntryPoint"
    use-expressions="true" xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/oauth/users/([^/].*?)/tokens/.*"
        access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')"
        method="DELETE" />
    <intercept-url pattern="/oauth/users/.*"
        access="#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')"
        method="GET" />
    <intercept-url pattern="/oauth/clients/.*"
        access="#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')"
        method="GET" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
    <expression-handler ref="oauthWebExpressionHandler" />
</http>

<!-- The OAuth2 protected resources are separated out into their own block 
    so we can deal with authorization and error handling separately. This isn't 
    mandatory, but it makes it easier to control the behaviour. -->
<http pattern="/me/**" create-session="never"
    entry-point-ref="oauthAuthenticationEntryPoint"
    access-decision-manager-ref="accessDecisionManager"
    xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/me" access="ROLE_USER,SCOPE_READ" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <access-denied-handler ref="oauthAccessDeniedHandler" />
</http>

<bean id="oauthAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="sparklr2" />
</bean>

<bean id="clientAuthenticationEntryPoint"
    class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    <property name="realmName" value="sparklr2/client" />
    <property name="typeName" value="Basic" />
</bean>

<bean id="oauthAccessDeniedHandler"
    class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />

<bean id="clientCredentialsTokenEndpointFilter"
    class="org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter">
    <property name="authenticationManager" ref="clientAuthenticationManager" />
</bean>

<bean id="accessDecisionManager" class="org.springframework.security.access.vote.UnanimousBased"
    xmlns="http://www.springframework.org/schema/beans">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.oauth2.provider.vote.ScopeVoter" />
            <bean class="org.springframework.security.access.vote.RoleVoter" />
            <bean class="org.springframework.security.access.vote.AuthenticatedVoter" />
        </list>
    </constructor-arg>
</bean>

<authentication-manager id="clientAuthenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <authentication-provider user-service-ref="clientDetailsUserService" />
</authentication-manager>

<authentication-manager alias="authenticationManager"
    xmlns="http://www.springframework.org/schema/security">
    <authentication-provider>
        <user-service id="userDetailsService">
            <user name="marissa" password="koala" authorities="ROLE_USER" />
            <user name="paul" password="emu" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

<bean id="clientDetailsUserService"
    class="org.springframework.security.oauth2.provider.client.ClientDetailsUserDetailsService">
    <constructor-arg ref="clientDetails" />
</bean>

<bean id="tokenStore"
    class="org.springframework.security.oauth2.provider.token.store.JdbcTokenStore">
    <constructor-arg ref="dataSource" />
</bean>

<bean id="tokenServices"
    class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
    <property name="tokenStore" ref="tokenStore" />
    <property name="tokenEnhancer" ref="tokenEnhancer" />
    <property name="supportRefreshToken" value="true" />
    <property name="clientDetailsService" ref="clientDetails" />
</bean>

<bean id="tokenEnhancer"
    class="org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter" />

<bean id="requestFactory"
    class="org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory">
    <constructor-arg name="clientDetailsService" ref="clientDetails" />
</bean>

<bean id="approvalStore"
    class="org.springframework.security.oauth2.provider.approval.TokenApprovalStore">
    <property name="tokenStore" ref="tokenStore" />
</bean>

<oauth:authorization-server
    client-details-service-ref="clientDetails" token-services-ref="tokenServices">
    <oauth:authorization-code />
    <oauth:implicit />
    <oauth:refresh-token />
    <oauth:client-credentials />
    <oauth:password />
</oauth:authorization-server>

<oauth:resource-server id="resourceServerFilter" entry-point-ref="entry"
    resource-id="writeUrl" token-services-ref="tokenServices" />

<bean id="entry" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
    <constructor-arg value="/writeUrl" />
</bean>

<oauth:client-details-service id="clientDetails">
    <oauth:client client-id="my-client-with-secret"
        authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
        scope="read,write" secret="secret" />
</oauth:client-details-service>

<mvc:default-servlet-handler />

<oauth:expression-handler id="oauthExpressionHandler" />

<oauth:web-expression-handler id="oauthWebExpressionHandler" />

【问题讨论】:

  • 你能把完整的源代码上传到github或者其他地方吗?
  • 不幸的是,没有。然而,整个 OAuth 配置都在上面的 XML 中——我的项目中没有其他部分与 OAuth 相关。我的问题基本上是如何使用 XML 配置将 URL 和安全 taht 作为资源服务器的一部分。

标签: spring spring-security resources oauth2


【解决方案1】:

资源端点配置中应该有一个intercept-url,并且仅限授权用户访问(我猜您的网址可能与以下模式匹配)

   <security:http pattern="/writeUrl/**" 
                  create-session="never" 
                  entry-point-ref="oauthAuthenticationEntryPoint"
                  access-decision-manager-ref="accessDecisionManager">
     <security:anonymous enabled="false" />
     <security:intercept-url pattern="/**"
                             access="IS_AUTHENTICATED_FULLY"/>

     <security:custom-filter ref="resourceServerFilter"
                             before="PRE_AUTH_FILTER" />
     <security:access-denied-handler ref="oauthAccessDeniedHandler" />
   </security:http>

【讨论】:

  • 当你有“IS_AUTHENTICATED_FULLY”时,在 Spring 安全或 Spring OAuth2 的上下文中是 taht(也许它们是同一件事)?我正在使用“client_credentials”授权类型,但是当我的客户提交他们的 id 和秘密时,我不确定这是否会使他们成为“IS_AUTHENTICATED_FULLY”。
  • 好吧,在这种情况下,我的意思是在 OAuth2 的上下文中。 Also isAuthenticated() 应该没问题,让他们通过身份验证。
猜你喜欢
  • 2017-08-18
  • 1970-01-01
  • 2015-03-19
  • 1970-01-01
  • 2020-11-30
  • 2013-12-21
  • 2018-04-14
  • 2016-05-21
  • 2019-11-27
相关资源
最近更新 更多