Spring security oauth 2 简单示例

Posted

技术标签:

【中文标题】Spring security oauth 2 简单示例【英文标题】:Spring security oauth 2 simple example 【发布时间】:2013-01-09 11:10:41 【问题描述】:

我尝试根据官方教程Sparklr2/Tonr2 实现我自己的示例。一切看起来都不错,但是当我在 Tonr2 实现中从 web.xml 中删除时,弹簧安全过滤器出现异常:

没有为当前请求建立重定向 URI

我不明白应该使用哪个 URL。这是我的代码,用于客户端实现:

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

<!--define an oauth 2 resource for sparklr -->
<oauth:resource id="provider" type="authorization_code" client-id="client" client-secret="secret" 
    access-token-uri="http://localhost:8080/provider/oauth/token" user-authorization-uri="http://localhost:8080/provider/oauth/authorize" scope="read,write" />

<beans:bean id="clientController" class="com.aouth.client.ClientController">
    <beans:property name="trustedClientRestTemplate">
        <oauth:rest-template resource="provider" />
    </beans:property>
</beans:bean>

对于提供者:

<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 />
</http>

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

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

<!-- 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="/secured" create-session="never" access-decision-manager-ref="accessDecisionManager" xmlns="http://www.springframework.org/schema/security">
    <anonymous enabled="false" />
    <intercept-url pattern="/secured" access="ROLE_USER,SCOPE_READ" />
    <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
    <http-basic />
</http>

<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>

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

<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="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />

<http auto-config="true" xmlns="http://www.springframework.org/schema/security">
    <intercept-url pattern="/test" access="ROLE_USER" />
    <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</http>

<authentication-manager alias="authenticationManager" xmlns="http://www.springframework.org/schema/security">
    <authentication-provider>
        <user-service>
            <user name="pr" password="pr" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
</authentication-manager>

<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:client-details-service id="clientDetails">
    <oauth:client client-id="client" resource-ids="resource" authorized-grant-types="authorization_code, implicit"
        authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
</oauth:client-details-service>

我只想让我的客户在没有弹簧安全的情况下工作。当我需要受保护的资源时,我只想在提供者端登录。

【问题讨论】:

你完成了吗?你有代码来证明你做了什么吗?我正在努力学习同样的东西 【参考方案1】:

您在此处粘贴的第二个 XML 是 oauth-providerprotected-resource 的 Spring XML,在您的情况下,它们在同一个 web 应用程序中运行。 (当然,如果您愿意,可以将它们分开)。

客户端(第一个粘贴的 XML)是另一回事。如果我理解正确,您希望您的客户端在没有 Spring 帮助的情况下运行(成为常规 webapp,而不是 spring-security-oauth-client webapp)。

您必须了解 oAuth 的工作原理:客户端尝试访问受保护的资源;如果它没有访问令牌,它将被重定向到 oAuth-provider(显示登录页面并提供令牌)。 By the standard,访问令牌的请求必须包含“redirect-uri”参数,因此在成功登录后,oAuth 提供者知道将客户端重定向到哪里。 oAuth 客户端会为您完成,如果您从 web.xml 中删除“oauth 客户端”,您现在必须自己实现。

感谢您的回答。但我还是不明白春天是怎么来的 安全性会影响我的 oAuth 客户端。我可以用于客户端吗 没有 spring-security 的 spring-oauth (spring-mvc)?

当你在你的 XML 中写下这一行时:

< oauth:client id="oauth2ClientFilter" />

这意味着你使用了spring-security-oauth,这是一个专门用于oauth的包,建立在spring-security之上。如果您深入研究,它会在处理与客户端相关的 oAuth 内容的链中放置一个特殊过滤器 (OAuth2ClientContextFilter)。其中之一是发送带有所有参数的请求(“redirect-uri”就是其中之一)。

如果你决定不使用 spring-security-oauth,那么 - 你必须自己实现这个逻辑......

希望有帮助!

【讨论】:

感谢您的回答。但我仍然不明白 spring 安全性如何影响我的 oAuth 客户端。我可以在没有 spring-security 的情况下用于客户端 spring-oauth (spring-mvc) 吗? 感谢 OhadR,您的回答确实帮助我理解了。 @chaldaean 能否请您在更正后演示完整的 security.xml 文件 感谢@OhadR。所以如果我理解正确,如果我只想用它来检索令牌以便将来调用应用程序,这是不可能的吗?我不需要重定向 uri 我看到许多使用 spring 安全性来检索令牌的示例。我的客户端是 angular.js,我的服务器端是 REST api。 Twitter API 也可以使用令牌

以上是关于Spring security oauth 2 简单示例的主要内容,如果未能解决你的问题,请参考以下文章

使用 spring-session 和 spring-cloud-security 时,OAuth2ClientContext (spring-security-oauth2) 不会保留在 Redis

spring-security-oauth2中的HttpSecurity配置问题

spring-security-oauth2 - 从资源服务器检查ClientDetails

社交登录,spring-security-oauth2 和 spring-security-jwt?

如何处理 spring-security-oauth2 的版本升级?

为啥spring-security-oauth oauth 2.0实现中需要scope参数