7

我正在尝试将 Spring OAuth2 用于我的休息应用程序。但看起来我犯了一个错误,我可以找到我做错的地方。流程应该是: 1. 使用用户名和密码从 /oauth/token 获取令牌 2. 使用提供的令牌向 /security 发出请求

方法安全配置:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

    @Autowired
    private SecurityConfiguration securityConfig;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

OAuth2服务器配置:

@Configuration
public class OAuth2ServerConfig {

    private static final String RESOURCE_ID = "nessnity";

    @Configuration
    @Order(10)
    protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                    .requestMatchers().antMatchers("/security")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/security").access("hasRole('USER')");
        }
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources.resourceId(RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http
                    .requestMatchers().antMatchers("/security/")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/security").access("#oauth2.hasScope('read')");
      }

    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

        @Autowired
        private TokenStore tokenStore;

        @Autowired
        private UserApprovalHandler userApprovalHandler;

        @Autowired
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory()
                    .withClient("my-client")
                    .resourceIds(RESOURCE_ID)
                    .authorizedGrantTypes("client_credentials")
                    .authorities("ROLE_CLIENT")
                    .scopes("read")
                    .secret("password")
                    .accessTokenValiditySeconds(60);
        }

        @Bean
        public TokenStore tokenStore() {
            return new InMemoryTokenStore();
        }

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
                    .tokenStore(tokenStore)
                    .userApprovalHandler(userApprovalHandler)
                    .authenticationManager(authenticationManager);
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.realm("sparklr2/client");
        }

    }

    protected static class Stuff {

        @Autowired
        private ClientDetailsService clientDetailsService;

        @Autowired
        private TokenStore tokenStore;

        @Bean
        public ApprovalStore approvalStore() throws Exception {
            TokenApprovalStore store = new TokenApprovalStore();
            store.setTokenStore(tokenStore);
            return store;
        }

        @Bean
        @Lazy
        @Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
        public SparklrUserApprovalHandler userApprovalHandler() throws Exception {
            SparklrUserApprovalHandler handler = new SparklrUserApprovalHandler();
            handler.setApprovalStore(approvalStore());
            handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
            handler.setClientDetailsService(clientDetailsService);
            handler.setUseApprovalStore(true);
            return handler;
        }
    }

}

安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("root")
                .password("password")
                .roles("USER");
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/oauth/uncache_approvals", "/oauth/cache_approvals");
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().hasRole("USER");
    }
}

问题:当我尝试获取令牌时

curl --user root:password --data "grant_type=client_credentials" http://localhost:8080/oauth/token

我收到消息:

{"error":"invalid_client","error_description":"错误的客户端凭据"}

第二个问题是如何在 /oauth/token?username=root&password=password 之类的 url 参数中传递用户名/密码?

谢谢。

更新

我决定从头开始并使用 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"
       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/security http://www.springframework.org/schema/security/spring-security-3.2.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="authenticationManager"
          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"/>
        <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="authenticationManager"/>
    </bean>

    <authentication-manager alias="authenticationManager"
                            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>

    <bean id="clientDetails" class="com.nessnity.api.security.OAuthClienDetailsService">
        <property name="id" value="testuser"/>
        <property name="secretKey" value="secret" />
    </bean>

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

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

    <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 authentication-manager-ref="userAuthenticationManager"/>
    </oauth:authorization-server>

    <authentication-manager id="userAuthenticationManager"
                            xmlns="http://www.springframework.org/schema/security">
        <authentication-provider ref="customUserAuthenticationProvider">
        </authentication-provider>
    </authentication-manager>

    <bean id="customUserAuthenticationProvider"
          class="com.nessnity.api.security.OAuthUserAuthenticationProvider">
    </bean>

    <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="900000000"/>
        <property name="clientDetailsService" ref="clientDetails"/>
    </bean>

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

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

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

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

</beans>
4

2 回答 2

6

在进行以下更改后,我遇到了类似的情况

在您的AuthorizationServerConfiguration类中替换

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            oauthServer.realm("sparklr2/client");
        }

使用以下代码

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        //oauthServer.realm("sparklr2/client");
        oauthServer.allowFormAuthenticationForClients();
    }

并且请求应该喜欢

/oauth/token?grant_type=password&scope=read+write&client_id=yourclientId&client_secret=secret&username=userName&password=pwd

于 2015-01-21T12:07:03.440 回答
0

在您的访问令牌请求中,您使用的是客户端凭据授予类型。OAuth 规范说,在 client_credentials 授权类型的情况下,您需要提供 base64 编码client_id:client_secret为基本授权标头。例如,如果您的 client_id 是google并且 client_secret 是x23r-ss56-rfg8-6yt6,那么您需要将这些字符串添加为google:x23r-ss56-rfg8-6yt6,使用 Base64 编码器对其进行编码并将请求发送为

curl --header "Authorization: Basic <base64 encoded_string>" --data "grant_type=client_credentials" http://localhost:8080/oauth/token

于 2015-01-30T07:46:41.043 回答