TokenEndpoint:处理空指针异常

时间:2016-05-16 01:31:10

标签: java spring spring-security oauth2 spring-oauth2

我尝试通过curl执行此命令从我的oauth2服务器请求代码

 curl -X POST -k -vu clientapp:123456 http://localhost:8080/oauth/token -H "Accept: application/json" -d "grant_type=authorization_code&scope=read%20write&client_secret=123456&client_id=clientapp&code=appcode&redirect_uri=localhost:3000"

回应是

* Adding handle: conn: 0x608860
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x608860) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 8080 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 8080 (#0)
* Server auth using Basic with user 'clientapp'
> POST /oauth/token HTTP/1.1
> Authorization: Basic Y2xpZW50YXBwOjEyMzQ1Ng==
> User-Agent: curl/7.30.0
> Host: localhost:8080
> Accept: application/json
> Content-Length: 131
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 131 out of 131 bytes
< HTTP/1.1 400 Bad Request
< Date: Mon, 16 May 2016 01:02:09 GMT
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT,DELETE
< Access-Control-Max-Age: 3600
< Access-Control-Allow-Headers: Authorization,Content-Disposition,Content-Description,Content-Type,Accept, X-Requested-With, remember-me
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 1; mode=block
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Cache-Control: no-store
< Pragma: no-cache
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
* Server Jetty(9.2.14.v20151106) is not blacklisted
< Server: Jetty(9.2.14.v20151106)
<
{"error":"invalid_grant","error_description":"Invalid authorization code: appcode"}*

检查我的日志后,我收到了此错误。

2016-05-16 09:26:43.826  INFO 9688 --- [tp1276746636-47] o.s.s.o.provider.endpoint.TokenEndpoint  : Handling error: NullPointerException, null

我的配置要点

@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends
        AuthorizationServerConfigurerAdapter {

    @Value("${client.secret}")
    private String clientSecret;

    @Value("${client}")
    private String clientId;

    @Autowired
    private TokenStore tokenStore;

    @Autowired
    private JdbcAuthorizationCodeServices jdbcAuthorizationCodeServices;

    /**
     * By default,
     * it uses the JDBCUserDetails, we exposed our own authentication manager bean
     */
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JdbcClientDetailsService jdbcClientDetailsService;

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception {
        endpoints
                .tokenStore(this.tokenStore)
                .authenticationManager(this.authenticationManager)
                .authorizationCodeServices(this.jdbcAuthorizationCodeServices).userApprovalHandler(new DefaultUserApprovalHandler());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(jdbcClientDetailsService);
                /*.inMemory()
                .withClient(clientId)
                .authorizedGrantTypes("password", "refresh_token")
                .authorities("USER")
                .scopes("read", "write")
                .resourceIds(RESOURCE_ID)
                .secret(clientSecret);*/
    }

    @Bean
    @Primary
    public DefaultTokenServices tokenServices() {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setSupportRefreshToken(true);
        tokenServices.setTokenStore(this.tokenStore);
        return tokenServices;
    }
}

1 个答案:

答案 0 :(得分:15)

如上所述,您需要打印出完整的堆栈跟踪。最简单的方法是将自定义的异常转换器注入到Auth服务器配置中。请参阅下面的示例。

定义新的异常翻译器:

    @Bean
    public WebResponseExceptionTranslator loggingExceptionTranslator() {
        return new DefaultWebResponseExceptionTranslator() {
            @Override
            public ResponseEntity<OAuth2Exception> translate(Exception e) throws Exception {
                // This is the line that prints the stack trace to the log. You can customise this to format the trace etc if you like
                e.printStackTrace();

                // Carry on handling the exception
                ResponseEntity<OAuth2Exception> responseEntity = super.translate(e);
                HttpHeaders headers = new HttpHeaders();
                headers.setAll(responseEntity.getHeaders().toSingleValueMap());
                OAuth2Exception excBody = responseEntity.getBody();
                return new ResponseEntity<>(excBody, headers, responseEntity.getStatusCode());
            }
        };
    }

然后将异常转换器添加到配置它们的方法中的端点:

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
            endpoints
            // Your usual config here .....
            .exceptionTranslator(loggingExceptionTranslator());
}

然后,您应该在日志中看到一些有用的信息,可以帮助您诊断问题。