当前位置: 首页 > 知识库问答 >
问题:

Spring Securityoauth 2和客户端凭据流

卫泉
2023-03-14

我试图实现一个简单的客户端凭证流spring-security-oauth2 api。我试图改编sparklr和tonr的例子,但没有成功。我也尝试按照这个线程的代码:Spring-2-leged(客户端凭证)OAuth2服务器的安全上下文设置,但它似乎不适合我。谁能给我举个例子,或者帮我做些什么来让这个工作。

spring servlet。Sparkr应用程序中的xml

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:sec="http://www.springframework.org/schema/security"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

    <!-- Just for testing... -->
    <http pattern="/oauth/cache_approvals" security="none" xmlns="http://www.springframework.org/schema/security" />
    <http pattern="/oauth/uncache_approvals" security="none" xmlns="http://www.springframework.org/schema/security" />

    <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" before="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" />
        <intercept-url pattern="/**" access="denyAll()"/>
        <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="/photos/**" 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="/photos" access="ROLE_USER,SCOPE_READ" />
        <intercept-url pattern="/photos/trusted/**" access="ROLE_CLIENT,SCOPE_TRUST" />
        <intercept-url pattern="/photos/user/**" access="ROLE_USER,SCOPE_TRUST" />
        <intercept-url pattern="/photos/**" access="ROLE_USER,SCOPE_READ" />
        <custom-filter ref="resourceServerFilter" before="PRE_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="/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>

    <http access-denied-page="/login.jsp?authorization_error=true" disable-url-rewriting="true"
            xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/oauth/**" access="ROLE_USER" />
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />

        <form-login authentication-failure-url="/login.jsp?authentication_error=true" default-target-url="/index.jsp"
                login-page="/login.jsp" login-processing-url="/login.do" />
        <logout logout-success-url="/index.jsp" logout-url="/logout.do" />
        <anonymous />
    </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.InMemoryTokenStore" />

    <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="clientDetails" />
    </bean>

    <bean id="userApprovalHandler" class="org.springframework.security.oauth.examples.sparklr.oauth.SparklrUserApprovalHandler">
        <property name="autoApproveClients">
            <set>
                <value>my-less-trusted-autoapprove-client</value>
            </set>
        </property>
        <property name="tokenServices" ref="tokenServices" />
    </bean>

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

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

    <oauth:client-details-service id="clientDetails">
        <oauth:client client-id="my-trusted-client" authorized-grant-types="password,authorization_code,refresh_token,implicit"
                authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" access-token-validity="60" />
        <oauth:client client-id="my-trusted-client-with-secret" authorized-grant-types="password,authorization_code,refresh_token,implicit"
                secret="somesecret" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" />
        <oauth:client client-id="my-client-with-secret" authorized-grant-types="client_credentials" authorities="ROLE_CLIENT"
                scope="read" secret="secret" />
        <oauth:client client-id="my-less-trusted-client" authorized-grant-types="authorization_code,implicit"
                authorities="ROLE_CLIENT" />
        <oauth:client client-id="my-less-trusted-autoapprove-client" authorized-grant-types="implicit"
                authorities="ROLE_CLIENT" />
        <oauth:client client-id="my-client-with-registered-redirect" authorized-grant-types="authorization_code,client_credentials"
                authorities="ROLE_CLIENT" redirect-uri="http://anywhere?key=value" scope="read,trust" />
        <oauth:client client-id="my-untrusted-client-with-registered-redirect" authorized-grant-types="authorization_code"
                authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read" />
        <oauth:client client-id="tonr" resource-ids="sparklr" authorized-grant-types="client_credentials"
                authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
    </oauth:client-details-service>

    <mvc:annotation-driven />

    <mvc:default-servlet-handler />

    <sec:global-method-security pre-post-annotations="enabled" proxy-target-class="true">
        <!--you could also wire in the expression handler up at the layer of the http filters. See https://jira.springsource.org/browse/SEC-1452 -->
        <sec:expression-handler ref="oauthExpressionHandler" />
    </sec:global-method-security>

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

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

    <!--Basic application beans. -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="viewResolvers">
            <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/jsp/"></property>
                <property name="suffix" value=".jsp"></property>
            </bean>
        </property>
        <property name="defaultViews">
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
                <property name="extractValueFromSingleKeyModel" value="true" />
            </bean>
        </property>
    </bean>

    <bean id="photoController" class="org.springframework.security.oauth.examples.sparklr.mvc.PhotoController">
        <property name="photoService" ref="photoServices" />
    </bean>

    <bean id="photoServiceUserController" class="org.springframework.security.oauth.examples.sparklr.mvc.PhotoServiceUserController">
        <property name="userDetailsService" ref="userDetailsService" />
    </bean>

    <bean id="adminController" class="org.springframework.security.oauth.examples.sparklr.mvc.AdminController">
        <property name="tokenServices" ref="tokenServices" />
        <property name="userApprovalHandler" ref="userApprovalHandler" />
    </bean>

    <!-- Override the default mappings for approval and error pages -->
    <bean id="accessConfirmationController" class="org.springframework.security.oauth.examples.sparklr.mvc.AccessConfirmationController">
        <property name="clientDetailsService" ref="clientDetails" />
    </bean>

    <bean id="photoServices" class="org.springframework.security.oauth.examples.sparklr.impl.PhotoServiceImpl">
        <property name="photos">
            <list>
                <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo">
                    <property name="id" value="1" />
                    <property name="name" value="photo1.jpg" />
                    <property name="userId" value="marissa" />
                    <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo1.jpg" />
                </bean>
                <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo">
                    <property name="id" value="2" />
                    <property name="name" value="photo2.jpg" />
                    <property name="userId" value="paul" />
                    <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo2.jpg" />
                </bean>
                <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo">
                    <property name="id" value="3" />
                    <property name="name" value="photo3.jpg" />
                    <property name="userId" value="marissa" />
                    <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo3.jpg" />
                </bean>
                <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo">
                    <property name="id" value="4" />
                    <property name="name" value="photo4.jpg" />
                    <property name="userId" value="paul" />
                    <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo4.jpg" />
                </bean>
                <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo">
                    <property name="id" value="5" />
                    <property name="name" value="photo5.jpg" />
                    <property name="userId" value="marissa" />
                    <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo5.jpg" />
                </bean>
                <bean class="org.springframework.security.oauth.examples.sparklr.PhotoInfo">
                    <property name="id" value="6" />
                    <property name="name" value="photo6.jpg" />
                    <property name="userId" value="paul" />
                    <property name="resourceURL" value="/org/springframework/security/oauth/examples/sparklr/impl/resources/photo6.jpg" />
                </bean>
            </list>
        </property>
    </bean>

</beans>

Spring式.xml在齿槽应用中

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:sec="http://www.springframework.org/schema/security"
        xmlns:oauth="http://www.springframework.org/schema/security/oauth2" xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
    http://www.springframework.org/schema/security/oauth2 http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <http access-denied-page="/login.jsp?authorization_error=true" xmlns="http://www.springframework.org/schema/security">
        <intercept-url pattern="/sparklr/**" access="ROLE_USER" />
        <intercept-url pattern="/facebook/**" access="ROLE_USER" />
        <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />

        <form-login authentication-failure-url="/login.jsp?authentication_error=true" default-target-url="/index.jsp"
                login-page="/login.jsp" login-processing-url="/login.do" />
        <logout logout-success-url="/index.jsp" logout-url="/logout.do" />
        <anonymous />
        <custom-filter ref="oauth2ClientFilter" after="EXCEPTION_TRANSLATION_FILTER" />
    </http>

    <authentication-manager xmlns="http://www.springframework.org/schema/security">
        <authentication-provider>
            <user-service>
                <user name="marissa" password="wombat" authorities="ROLE_USER" />
                <user name="sam" password="kangaroo" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

    <!--apply the oauth client context -->
    <oauth:client id="oauth2ClientFilter" />

    <!--  define an oauth 2 resource for sparklr --> 
    <oauth:resource id="sparklr" type="client_credentials" client-id="tonr" client-secret="secret"
            access-token-uri="${accessTokenUri}" scope="read,write" />

    <!--define an oauth 2 resource for trusted client on sparklr -->
    <oauth:resource id="trusted" type="client_credentials" client-id="my-client-with-registered-redirect"
            access-token-uri="${accessTokenUri}" scope="trust" />

    <!--define an oauth 2 resource for facebook. according to the facebook docs, the 'client-id' is the App ID, and the 'client-secret' 
        is the App Secret -->
    <oauth:resource id="facebook" type="authorization_code" client-id="233668646673605" client-secret="33b17e044ee6a4fa383f46ec6e28ea1d"
            authentication-scheme="query" access-token-uri="https://graph.facebook.com/oauth/access_token" user-authorization-uri="https://www.facebook.com/dialog/oauth"
            token-name="oauth_token" client-authentication-scheme="form" />

    <context:property-placeholder location="classpath:/sparklr.properties" />

    <bean id="conversionService" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <bean class="org.springframework.security.oauth.examples.tonr.converter.AccessTokenRequestConverter" />
            </set>
        </property>
    </bean>

    <mvc:default-servlet-handler />

    <mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
        </mvc:message-converters>
    </mvc:annotation-driven>

    <bean id="contentViewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry key="json" value="application/json" />
            </map>
        </property>
        <property name="defaultViews">
            <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView" />
        </property>
    </bean>

    <!--Basic application beans. -->
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/" />
        <property name="suffix" value=".jsp" />
    </bean>

    <bean id="sparklrController" class="org.springframework.security.oauth.examples.tonr.mvc.SparklrController">
        <property name="sparklrService" ref="sparklrService" />
    </bean>

    <bean id="facebookController" class="org.springframework.security.oauth.examples.tonr.mvc.FacebookController">
        <property name="facebookRestTemplate">
            <oauth:rest-template resource="facebook">
                <property name="messageConverters">
                    <list>
                        <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
                            <property name="supportedMediaTypes">
                                <list>
                                    <bean class="org.springframework.http.MediaType">
                                        <!--facebook sends its json as text/javascript for some reason -->
                                        <constructor-arg value="text" />
                                        <constructor-arg value="javascript" />
                                    </bean>
                                    <bean class="org.springframework.http.MediaType">
                                        <constructor-arg value="application" />
                                        <constructor-arg value="json" />
                                    </bean>
                                </list>
                            </property>
                        </bean>
                    </list>
                </property>
            </oauth:rest-template>
        </property>
    </bean>

    <bean id="sparklrService" class="org.springframework.security.oauth.examples.tonr.impl.SparklrServiceImpl">
        <property name="sparklrPhotoListURL" value="${sparklrPhotoListURL}" />
        <property name="sparklrTrustedMessageURL" value="${sparklrTrustedMessageURL}" />
        <property name="sparklrPhotoURLPattern" value="${sparklrPhotoURLPattern}" />
        <property name="sparklrRestTemplate">
            <oauth:rest-template resource="sparklr" />
        </property>
        <property name="trustedClientRestTemplate">
            <oauth:rest-template resource="trusted" />
        </property>
    </bean>

</beans>

我得到以下错误时,试图验证tonr应用程序上的火花应用程序:

HTTP状态500-请求处理失败;嵌套异常是error="access_denied",error_description="请求访问令牌的错误。

我希望有人能帮助我。谢谢

共有2个答案

江阳冰
2023-03-14

替换这条线

  <oauth:resource id="sparklr" type="client_credentials" client-id="tonr" client-secret="secret"
        access-token-uri="${accessTokenUri}" scope="read,write" />

经过

 <oauth:resource id="sparklr" type="authorization_code" client-id="tonr" client-secret="secret"
        access-token-uri="${accessTokenUri}" scope="read,write" />

错误是el类型的client_credentials,由authorization_code替换,将正常工作。

巫英纵
2023-03-14

您可以尝试允许匿名访问/oauth/tokenendpoint。这是我让client_credentials流工作的唯一方法。

改变这条线

<代码>

到这个

<代码>

并删除该行:

<代码>

希望这有帮助。

 类似资料:
  • 当授权范围限于客户端控制下的受保护资源或事先与授权服务器商定的受保护资源时客户端凭据可以被用作为一种授权许可。典型的当客户端代表自己表演(客户端也是资源所有者)或者基于与授权服务器事先商定的授权请求对受保护资源的访问权限时,客户端凭据被用作为授权许可。

  • 有人用这种方法吗?https://laravel.com/docs/5.4/passport#client-凭证授予代币 我试图使注册API只包含client_id和client_secret,我希望返回作为访问令牌、刷新令牌、过期日期,但返回www.url。com/oauth/token这是什么 有人能帮我吗?提前谢谢

  • 当客户端是资源所有者时,或者当授权范围限于受客户端控制的受保护资源时,客户端凭证可以用作授权授权。 客户端仅在客户端凭据的帮助下请求访问令牌。 客户端凭证授权流用于获取访问令牌以授权API请求。 使用客户端凭据授权,获取的访问令牌仅授予客户端应用程序搜索和获取目录文档的权限。 下图描绘了客户端凭据流。 上图所示的流程包括以下步骤 - Step 1 - 客户端使用授权服务器进行身份验证,并从令牌端点

  • 顺便说一句,这些微服务只会通过中间件层互相交谈,我的意思是不需要用户凭据来允许授权(用户登录过程如Facebook)。 我在Internet上寻找了一些示例,展示了如何创建一个授权和资源服务器来管理这种通信。然而,我只是找到了一些例子,解释了如何使用用户凭据(三条腿)来实现它。 有没有人有在Spring Boot和Oauth2中如何做的样例?如果有可能提供更多关于所用范围的详细信息,令牌交换将不胜

  • 我目前是谷歌分析API throu JavaScript的新成员。我正在实现一些图表和第一次加载,页面是重定向我到谷歌网站登录与分析帐户,然后返回到我的原始页面,刷新和图表显示。 有没有任何技巧/想法,我可以得到任何API可以解决这个问题?

  • 我已经考虑这个问题好几天了,从经验中我知道我通常会解决这些问题,但这次我遇到了砖墙。 我有一个在Azure DevOps YAML管道中实例化的python应用程序。该应用程序调用Azure DevOps REST API来创建存储库 该应用程序使用PAT(个人访问令牌)进行身份验证 我在Azure DevOps中创建了一个应用程序: 我的计划是让这一切都在Postman中工作,然后将我的发现移植