2014-10-29 83 views
2

我收到错误:的oauth2坏凭据春季启动

“错误”: “invalid_grant”, “ERROR_DESCRIPTION”: “坏凭据”

这里是我发出请求:

POST /oauth/token HTTP/1.1 
Host: localhost:8443 
Authorization: Basic bW9iaWxlOg== 
Cache-Control: no-cache 
Content-Type: application/x-www-form-urlencoded 

username=admin&password=pass&client_id=mobile&grant_type=password&client_secret= 

我的代码是从这里:https://github.com/juleswhite/mobilecloud-14/tree/master/examples/9-VideoServiceWithOauth2

下面是代码: Application.java:

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.ComponentScan; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.context.annotation.Import; 
import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; 
import org.springframework.web.servlet.config.annotation.EnableWebMvc; 

import com.capstone.auth.OAuth2SecurityConfiguration; 
import com.google.common.io.BaseEncoding; 

@Configuration 
@EnableAutoConfiguration 
@ComponentScan 
@EnableWebMvc 
@Import(OAuth2SecurityConfiguration.class) 
public class Application extends RepositoryRestMvcConfiguration{ 

    public static void main(String[] args) { 
     ApplicationContext ctx = SpringApplication.run(Application.class, args); 

    } 

} 

ClientAndUserDetailsS​​ervice.java

​​

OAuth2SecurityConfiguration.java

@Configuration 
public class OAuth2SecurityConfiguration { 
    // This first section of the configuration just makes sure that Spring 
    // Security picks 
    // up the UserDetailsService that we create below. 
    @Configuration 
    @EnableWebSecurity 
    protected static class WebSecurityConfiguration extends 
      WebSecurityConfigurerAdapter { 

     @Autowired 
     private UserDetailsService userDetailsService; 

     @Autowired 
     protected void registerAuthentication(
       final AuthenticationManagerBuilder auth) throws Exception { 
      auth.userDetailsService(userDetailsService); 
     } 
    } 

    /** 
    * This method is used to configure who is allowed to access which parts of 
    * our resource server (i.e. the "/video" endpoint) 
    */ 
    @Configuration 
    @EnableResourceServer 
    protected static class ResourceServer extends 
      ResourceServerConfigurerAdapter { 

     // This method configures the OAuth scopes required by clients to access 
     // all of the paths in the video service. 
     @Override 
     public void configure(HttpSecurity http) throws Exception { 

      http.csrf().disable(); 

      http.authorizeRequests().antMatchers("/oauth/token").anonymous(); 

      // If you were going to reuse this class in another 
      // application, this is one of the key sections that you 
      // would want to change 

      // Require all GET requests to have client "read" scope 
      http.authorizeRequests().antMatchers(HttpMethod.GET, "/**") 
        .access("#oauth2.hasScope('read')"); 

      // Require all other requests to have "write" scope 
      http.authorizeRequests().antMatchers("/**") 
        .access("#oauth2.hasScope('write')"); 
     } 

    } 

    /** 
    * This class is used to configure how our authorization server (the 
    * "/oauth/token" endpoint) validates client credentials. 
    */ 
    @Configuration 
    @EnableAuthorizationServer 
    @Order(Ordered.LOWEST_PRECEDENCE - 100) 
    protected static class OAuth2Config extends 
      AuthorizationServerConfigurerAdapter { 

     // Delegate the processing of Authentication requests to the framework 
     @Autowired 
     private AuthenticationManager authenticationManager; 

     // A data structure used to store both a ClientDetailsService and a 
     // UserDetailsService 
     private ClientAndUserDetailsService combinedService_; 

     /** 
     * 
     * This constructor is used to setup the clients and users that will be 
     * able to login to the system. This is a VERY insecure setup that is 
     * using hard-coded lists of clients/users/passwords and should 
     * never be used for anything other than local testing on a machine that 
     * is not accessible via the Internet. Even if you use this code for 
     * testing, at the bare minimum, you should consider changing the 
     * passwords listed below and updating the VideoSvcClientApiTest. 
     * 
     * @param auth 
     * @throws Exception 
     */ 
     public OAuth2Config() throws Exception { 

      // If you were going to reuse this class in another 
      // application, this is one of the key sections that you 
      // would want to change 

      // Create a service that has the credentials for all our clients 
      ClientDetailsService csvc = new InMemoryClientDetailsServiceBuilder() 
        // Create a client that has "read" and "write" access to the 
        // video service 
        .withClient("mobile") 
        .authorizedGrantTypes("password") 
        .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") 
        .scopes("read", "write") 
        .resourceIds("test") 
        .and() 
        // Create a second client that only has "read" access to the 
        // video service 
        .withClient("mobileReader") 
        .authorizedGrantTypes("password") 
        .authorities("ROLE_CLIENT").scopes("read") 
        .resourceIds("test").accessTokenValiditySeconds(3600) 
        .and().build(); 

      // Create a series of hard-coded users. 
      UserDetailsService svc = new InMemoryUserDetailsManager(
        Arrays.asList(
          User.create("admin", "pass", "ADMIN", "USER"), 
          User.create("user0", "pass", "USER"), 
          User.create("username", "password", "USER"))); 

      // Since clients have to use BASIC authentication with the client's 
      // id/secret, 
      // when sending a request for a password grant, we make each client 
      // a user 
      // as well. When the BASIC authentication information is pulled from 
      // the 
      // request, this combined UserDetailsService will authenticate that 
      // the 
      // client is a valid "user". 
      combinedService_ = new ClientAndUserDetailsService(csvc, svc); 
     } 

     /** 
     * Return the list of trusted client information to anyone who asks for 
     * it. 
     */ 
     @Bean 
     public ClientDetailsService clientDetailsService() throws Exception { 
      return combinedService_; 
     } 

     /** 
     * Return all of our user information to anyone in the framework who 
     * requests it. 
     */ 
     @Bean 
     public UserDetailsService userDetailsService() { 
      return combinedService_; 
     } 

     /** 
     * This method tells our AuthorizationServerConfigurerAdapter to use the 
     * delegated AuthenticationManager to process authentication requests. 
     */ 
     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
       throws Exception { 
      endpoints.authenticationManager(authenticationManager); 
     } 

     /** 
     * This method tells the AuthorizationServerConfigurerAdapter to use our 
     * self-defined client details service to authenticate clients with. 
     */ 
     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) 
       throws Exception { 
      clients.withClientDetails(clientDetailsService()); 
     } 

    } 

    // This version uses the Tomcat web container and configures it to 
    // support HTTPS. The code below performs the configuration of Tomcat 
    // for HTTPS. Each web container has a different API for configuring 
    // HTTPS. 
    // 
    // The app now requires that you pass the location of the keystore and 
    // the password for your private key that you would like to setup HTTPS 
    // with. In Eclipse, you can set these options by going to: 
    // 1. Run->Run Configurations 
    // 2. Under Java Applications, select your run configuration for this app 
    // 3. Open the Arguments tab 
    // 4. In VM Arguments, provide the following information to use the 
    // default keystore provided with the sample code: 
    // 
    // -Dkeystore.file=src/main/resources/private/keystore 
    // -Dkeystore.pass=changeit 
    // 
    // 5. Note, this keystore is highly insecure! If you want more securtiy, you 
    // should obtain a real SSL certificate: 
    // 
    // http://tomcat.apache.org/tomcat-7.0-doc/ssl-howto.html 
    // 
    @Bean 
    EmbeddedServletContainerCustomizer containerCustomizer(
      @Value("${keystore.file:src/main/resources/private/keystore}") String keystoreFile, 
      @Value("${keystore.pass:changeit}") final String keystorePass) 
      throws Exception { 

     // If you were going to reuse this class in another 
     // application, this is one of the key sections that you 
     // would want to change 

     final String absoluteKeystoreFile = new File(keystoreFile) 
       .getAbsolutePath(); 

     return new EmbeddedServletContainerCustomizer() { 

      @Override 
      public void customize(ConfigurableEmbeddedServletContainer container) { 
       TomcatEmbeddedServletContainerFactory tomcat = (TomcatEmbeddedServletContainerFactory) container; 
       tomcat.addConnectorCustomizers(new TomcatConnectorCustomizer() { 
        @Override 
        public void customize(Connector connector) { 
         connector.setPort(8443); 
         connector.setSecure(true); 
         connector.setScheme("https"); 

         Http11NioProtocol proto = (Http11NioProtocol) connector 
           .getProtocolHandler(); 
         proto.setSSLEnabled(true); 
         proto.setKeystoreFile(absoluteKeystoreFile); 
         proto.setKeystorePass(keystorePass); 
         proto.setKeystoreType("JKS"); 
         proto.setKeyAlias("tomcat"); 
        } 
       }); 

      } 
     }; 
    } 

} 

感谢您的关注和时间!

+0

这ClientAndUserDetailsS​​ervice看起来像一个反模式,我最近看到它很多。你有没有问过你是否只是从同一个地方(其中)复制代码? – 2014-10-29 17:43:56

+0

不,我没有请问!但是我提到代码的来源,这是错误的吗? – KostasC 2014-10-29 17:52:58

+0

好的,谢谢,我不知道这是你的代码还是其他人奇怪的身份验证管理器的来源 – 2014-10-29 17:53:48

回答

2

简短回答:如果您使用的是Spring Boot(尚未),则不能将@AutowiredAuthenticationManager转换为AuthorizationServerConfigurerAdapter

Long anwswer:this sample可以工作,因为它会自动装入AuthenticationManagerBuilder,并构建AuthenticationManager的懒惰初始版本,以供令牌创建者使用。随着春天的OAuth2 2.0.3你必须自己(创建懒AuthenticationManagerthis

authenticationManager = new AuthenticationManager() { 
     @Override 
     public Authentication authenticate(Authentication authentication) throws AuthenticationException { 
      return auth.getOrBuild().authenticate(authentication); 
     } 
    }; 

通过快照(或2.0.4当它被释放),你可以使用新的重载方法AuthorizationServerConfigurerAdapter

+0

感谢您的回复,我会看看! – KostasC 2014-10-29 18:04:26

+0

我发现我的错误是什么,在我使用springBootVersion ='1.1.8.RELEASE'的build.gradle文件中,我将其更改为'1.0.2.RELEASE',它的工作原理!感谢您的时间Dave Syer。 – KostasC 2014-10-29 19:44:15

+0

这不是一个真正的修复,它只是推迟了这个问题。有趣的是,它在1.0.2中工作。 – 2014-10-30 07:47:51