关于RESTEasy API的oauth2 spring安全性

时间:2014-02-12 12:01:59

标签: spring jboss spring-security oauth-2.0 resteasy

我正在尝试通过Oauth 2.0 spring security来保护我的休息服务。我谷歌也一样,并得到了一些例子。我在谷歌的帮助下尝试了一个例子,并且能够生成access_token。但是当我要访问我的受保护资源时,它可以在不传递任何access_token的情况下访问,而应该显示一些授权错误消息。 我在这里缺少什么???

接收授权码的网址:

http://localhost:8080/springsecurity-oauth2-POC/oauth/token?grant_type=password&client_id=my-trusted-client-with-secret&client_secret=somesecret&username=marissa&password=koala 

得到令牌,如 { “的access_token”: “64ee1cf7-2445-40d8-86a5-c4900b47db9e”, “token_type”: “承载”, “refresh_token”: “e7c7bce1-35db-4879-a2de-e6690f8d482d”, “expires_in”:299969}

资源网址

http://localhost:8080/springsecurity-oauth2-POC/resources/MyResource/getMyInfo

因为它不包含任何令牌,但我仍然可以访问它。

我的 spring-servlet.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 ">


    <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="/resources/*" 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="/resources/*" access="ROLE_USER" />
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler" />
    </http>

    <http pattern="/logout" create-session="never" 
        entry-point-ref="oauthAuthenticationEntryPoint"
        xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false" />
        <intercept-url pattern="/logout" method="GET" />
        <sec:logout invalidate-session="true" logout-url="/logout" success-handler-ref="logoutSuccessHandler"   />
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler" />
    </http>


    <bean id="logoutSuccessHandler" class="demo.oauth2.authentication.security.LogoutImpl" >
        <property name="tokenstore" ref="tokenStore"></property>
    </bean>

    <bean id="oauthAuthenticationEntryPoint"
        class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
    </bean>

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

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

    <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-ref="clientDetailsUserService" /> -->
        <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>

    <!-- Used for the persistenceof tokens (currently an in memory implementation) -->
    <bean id="tokenStore" class="org.springframework.security.oauth2.provider.token.InMemoryTokenStore" />

    <!-- Used to create token and and every thing about them except for their persistence that is reposibility of TokenStore (Given here is a default implementation) -->
    <bean id="tokenServices" class="org.springframework.security.oauth2.provider.token.DefaultTokenServices">
        <property name="tokenStore" ref="tokenStore" />
        <property name="supportRefreshToken" value="true" />
        <property name="accessTokenValiditySeconds" value="300000"></property>
        <property name="clientDetailsService" ref="clientDetails" />
    </bean>

    <bean id="userApprovalHandler" class="org.springframework.security.oauth2.provider.approval.TokenServicesUserApprovalHandler">
        <property name="tokenServices" ref="tokenServices" />
    </bean>

    <!-- authorization-server aka AuthorizationServerTokenServices is an interface that defines everything necessary for token management -->
    <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="test" token-services-ref="tokenServices" />
    <!-- ClientsDeailsService: Entry Point to clients database (given is in memory implementation) -->
    <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="test" authorized-grant-types="authorization_code,implicit"
    authorities="ROLE_CLIENT" scope="read,write" secret="secret" />

    <!--Self defined client-->
    <oauth:client client-id="the_client" authorized-grant-types="authorization_code,client_credentials"
    authorities="ROLE_USER" scope="read,write,trust" secret="secret" />

    </oauth:client-details-service>
    <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" />

    <mvc:annotation-driven />   <!-- Declares explicit support for annotation-driven MVC controllers  @RequestMapping, @Controller -->

    <mvc:default-servlet-handler /> 
</beans>

我的 Web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
  <display-name>Spring Secure REST</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring-servlet.xml</param-value>
  </context-param>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>
  <filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <init-param>
      <param-name>contextAttribute</param-name>
      <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.spring</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
  <servlet>
    <servlet-name>RESTService</servlet-name>
    <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>RESTService</servlet-name>
    <url-pattern>/resources/*</url-pattern>
  </servlet-mapping>
  <servlet>
    <servlet-name>spring</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>spring</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

我的资源类包含

package demo.oauth2.authentication.resources;

import javax.ws.rs.GET;
import javax.ws.rs.Path;


@Path("/MyResource")
public class MyResource {


    @GET
    @Path("/createInfo")
    public String createInfo(){
        return "\n\n\t!!!Protected Resource(createInfo) Accessed !!!! Returning from Myresource createInfo\n";

    }

    @GET
    @Path("/getMyInfo")
    public String getMyInfo(){

        return "\n\n\t Protected Resource(getMyInfo) Accessed !!!! Returning from Myresource getMyInfo\n";
    }


    @GET
    @Path("/updateInfo")
    public String updateMyInfo(){
        return "\n\n\t Protected Resource(updateInfo) Accessed !!!! Returning from Myresource updateInfo\n";

    }

}

2 个答案:

答案 0 :(得分:2)

在以下位置尝试双星号:

<http pattern="/resources/**"

而不是

<http pattern="/resources/*"

希望它有所帮助。

答案 1 :(得分:1)

我发现您使用http://www.e-zest.net/blog/rest-authentication-using-oauth-2-0-resource-owner-password-flow-protocol/网站上的相同代码。如果是,那么您还需要使用以下代码

<http pattern="/resources/**" create-session="never" entry-point-ref="oauthAuthenticationEntryPoint"
        xmlns="http://www.springframework.org/schema/security">
        <anonymous enabled="false" />
        <intercept-url pattern="/resources/**" method="GET" />
        <intercept-url pattern="/resources/**" access="IS_AUTHENTICATED_FULLY" />
        <custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
        <access-denied-handler ref="oauthAccessDeniedHandler" />
    </http>

我也面临同样的问题,直到你没有添加上面的xml配置,我也使用相同的代码,它适用于我! 我已经进行了测试并附上了屏幕截图供您参考。 enter image description here

在这种情况下,我没有传递令牌值,它给了我预期的错误 enter image description here

现在,我传递了&#34; access_token&#34;的价值。并且它给了我受保护的资源。 enter image description here

希望这会对你有所帮助..