简体   繁体   English

没有这样的客户端例外Spring Oauth2

[英]No Such Client Exception Spring Oauth2

I am trying to implement Spring Security OAuth2 using Java config. 我正在尝试使用Java配置实现Spring Security OAuth2。

My usecase requires the use of password grant_type. 我的用例需要使用密码grant_type。

I have configured this so far without the need for a web.xml and would prefer to keep it that way 到目前为止,我已经配置了这个,而不需要web.xml,并且希望保持这种方式

Versions I am using: 我正在使用的版本:

  • Spring Framework: 4.1.6 Spring框架:4.1.6
  • Spring Security: 4.0.1 Spring Security:4.0.1
  • Spring Security OAuth:2.0.7 Spring Security OAuth:2.0.7

To make explaining this easier I have enabled GET on the token endpoint 为了使解释更容易,我在令牌端点上启用了GET

    @Override
    public void configure
        (AuthorizationServerEndpointsConfigurer endpoints) throws Exception
    {
            endpoints
                .tokenStore(tokenStore)
                .authenticationManager(authenticationManager)
                .allowedTokenEndpointRequestMethods(HttpMethod.GET); //<-- Enable GET
    }

The request that I am making is as follows: 我正在提出的要求如下:

http://localhost:8080/project/oauth/token?
    client_id=testClient&
    grant_type=password&
    username=user&
    password=password

The header includes an Authorization header that contains the encoded version of: 标头包含一个Authorization标头,其中包含以下编码版本:

Username: user
Password: password

The exception I get is: 我得到的例外是:

HTTP Status 500 - Request processing failed; nested exception is
   org.springframework.security.oauth2.provider.NoSuchClientException:
   No client with requested id: user

From the exception description it appears that OAuth is looking in the ClientDetailsService for the client: user . 从异常描述中可以看出,OAuth正在查找client: user的ClientDetailsS​​ervice。 However user is a user credential. 但是, 用户是用户凭证。 I am obviously missunderstanding something about the configuration. 我显然很想知道有关配置的一些事情。

My configuration is as follows; 我的配置如下;

ServletInitializer.java ServletInitializer.java

public class ServletInitializer extends AbstractDispatcherServletInitializer {

    @Override
    protected WebApplicationContext createServletApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.scan(ClassUtils.getPackageName(getClass()));
        return context;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected WebApplicationContext createRootApplicationContext() {
        return null;
    }

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException{
        super.onStartup(servletContext);
        DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain");
    filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");
        servletContext.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null, false, "/*");
    }
}

WebMvcConfig.java WebMvcConfig.java

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
    }
}

SecurityConfiguration.java SecurityConfiguration.java

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception{
        auth.
            inMemoryAuthentication()
            .withUser("user")
            .password("password")
            .roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception{
        http
            .authorizeRequests()
            .antMatchers("/Services/*")
            .authenticated()
        .and()
            .httpBasic();
    }

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

}

OAuth2ServerConfig.java OAuth2ServerConfig.java

@Configuration
public class OAuth2ServerConfig {

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter{

        @Autowired 
        private TokenStore tokenStore;

        @Autowired
        @Qualifier("authenticationManagerBean")
        private AuthenticationManager authenticationManager;

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception{

            clients
                .inMemory()
                    .withClient("testClient")
                    .secret("secret")
                    .scopes("read", "write")
                    .authorities("ROLE_CLIENT")
                    .authorizedGrantTypes("password", "refresh_token")
                    .accessTokenValiditySeconds(60)
                    .refreshTokenValiditySeconds(3600);
        }

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

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

        @Override 
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

        }
    }

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources){
            resources.resourceId("SomeResourseId").stateless(false);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception{

            http
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
            .and()
                .authorizeRequests()
                    .antMatchers("/secure/**").access("#oauth2.hasScope('read')");
        }
    }
}

Code in gitrepo for ease of access: https://github.com/dooffas/springOauth2 gitrepo中的代码,以便于访问: https//github.com/dooffas/springOauth2

I'm not sure where the 500 comes from in your case. 在你的情况下,我不确定500来自哪里。 I see a 406 because there is no JSON converter for the access token (Spring used to register one by default for Jackson 1.* but now it only does it for Jackson 2.*). 我看到一个406,因为没有JSON转换器用于访问令牌(Spring用于默认注册一个用于Jackson 1. *但现在它只用于Jackson 2. *)。 You token endpoint works for me if I add jackson-databind to the classpath, eg 如果我将jackson-databind添加到类路径中,您的令牌端点适用于我,例如

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.4</version>
    <scope>runtime</scope>
</dependency>

This works for me: 这对我有用:

$ curl -v testClient:secret@localhost:8080/oauth/token?'grant_type=password&username=user&password=password'

PS you really ought not to use GET for a token request. PS你真的不应该使用GET作为令牌请求。

You have defined different authorities 您已定义了不同的权限

try this: 试试这个:

@Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception{
        auth.
            inMemoryAuthentication()
            .withUser("user")
            .password("password")
            .roles("USER", "CLIENT");
    }

And add param grant_type=password to your request 并在您的请求中添加param grant_type=password

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM