Java 改装1.9以使用jhipster oauth,响应未填充

Java 改装1.9以使用jhipster oauth,响应未填充,java,android,oauth-2.0,jhipster,Java,Android,Oauth 2.0,Jhipster,我遇到了一个奇怪的Json转换问题,我有一个基于jhipster的webapp实现oauth身份验证,还有一个简单的android应用;我的编程逻辑基于这篇文章 对于android应用程序,我有以下代码: public class RestAdapterManager { public static final String API_BASE_URL = "http://192.168.0.102:8080/"; private static RestAdapter.Buil

我遇到了一个奇怪的Json转换问题,我有一个基于jhipster的webapp实现oauth身份验证,还有一个简单的android应用;我的编程逻辑基于这篇文章

对于android应用程序,我有以下代码:

public class RestAdapterManager {

    public static final String API_BASE_URL = "http://192.168.0.102:8080/";

    private static RestAdapter.Builder builder = new RestAdapter.Builder()
            .setEndpoint(API_BASE_URL);
            //.setClient(new OkClient(new OkHttpClient()));

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null, null);
    }

    public static <S> S createService(Class<S> serviceClass, String username, String password) {
        if (username != null && password != null) {
            // concatenate username and password with colon for authentication
            String credentials = username + ":" + password;
            // create Base64 encodet string
            final String basic =
                    "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

            builder.setRequestInterceptor(new RequestInterceptor() {
                @Override
                public void intercept(RequestFacade request) {
                    request.addHeader("Accept", "applicaton/json");
                    request.addHeader("Authorization", basic);
                }
            });
        }

        RestAdapter adapter = builder.setLogLevel(RestAdapter.LogLevel.FULL).build();
        return adapter.create(serviceClass);
    }
}
公共类RestAdapterManager{
公共静态最终字符串API_BASE_URL=”http://192.168.0.102:8080/";
私有静态RestAdapter.Builder=new RestAdapter.Builder()
.setEndpoint(API_BASE_URL);
//.setClient(新的OkClient(新的OkHttpClient());
公共静态S createService(类serviceClass){
返回createService(serviceClass,null,null);
}
公共静态S createService(类serviceClass、字符串用户名、字符串密码){
如果(用户名!=null和密码!=null){
//将用户名和密码与冒号连接以进行身份验证
字符串凭据=用户名+“:”+密码;
//创建Base64编码字符串
最终字符串基本=
“Basic”+Base64.encodeToString(credentials.getBytes(),Base64.NO_WRAP);
setRequestInterceptor(新的RequestInterceptor(){
@凌驾
公共无效截获(请求门面请求){
addHeader(“接受”、“应用程序/json”);
请求.addHeader(“授权”,基本);
}
});
}
RestAdapter adapter=builder.setLogLevel(RestAdapter.LogLevel.FULL).build();
返回adapter.create(serviceClass);
}
}
使用oauth服务本身的接口

public class AuthorizeService {

    private static IAuthorizeService authorizeService;

    public static IAuthorizeService getAuthorizeService() {
        return RestAdapterManager.createService(IAuthorizeService.class, "RikuyWebapp", "mySecretOAuthSecret" );
    }

    /**/

    public interface IAuthorizeService {

        @POST("/oauth/token")
        public void authorize(@Body Object dummy, @Query("username") String userName,
                              @Query("password") String password,
                              @Query("grant_type") String grantType,
                              @Query("scope") String scope,
                              @Query("client_id") String client_id,
                              @Query("client_secret") String client_secret,
                              Callback<UserToken> callback);
    }
}
公共类授权服务{
私有静态IAuthorizeService授权服务;
公共静态IAuthorizeService getAuthorizeService(){
返回RestAdapterManager.createService(IAuthorizeService.class,“rikuywapp”,“mySecretOAuthSecret”);
}
/**/
公共接口IAuthorizeService{
@POST(“/oauth/token”)
public void authorize(@Body Object dummy,@Query(“用户名”)字符串用户名,
@查询(“密码”)字符串密码,
@查询(“授权类型”)字符串授权类型,
@查询(“范围”)字符串范围,
@查询(“客户端id”)字符串客户端id,
@查询(“客户端密码”)字符串客户端密码,
回调(回调);
}
}
以及对服务的实际调用:

Button loginButton = (Button) findViewById(R.id.loginbutton);
        loginButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                AuthorizeService.getAuthorizeService().authorize("", "username",
                        "password", "password", "read", "appId", "appSecret", new Callback<UserToken>() {
                            @Override
                            public void success(UserToken result, Response response) {
                                Log.d("sucees!", result.getAccessToken());
                            }

                            @Override
                            public void failure(RetrofitError error) {
                                Log.d("Fail!", error.getBody().toString());
                            }
                        });

            }
        });
Button loginButton=(Button)findviewbyd(R.id.loginButton);
loginButton.setOnClickListener(新视图.OnClickListener(){
@凌驾
公共void onClick(视图v){
AuthorizeService.getAuthorizeService().authorize(“,”用户名“,
“密码”、“密码”、“读取”、“appId”、“appSecret”、新回调(){
@凌驾
public void成功(UserToken结果、响应){
Log.d(“sucees!”,result.getAccessToken());
}
@凌驾
公共无效失败(错误){
Log.d(“Fail!”,error.getBody().toString());
}
});
}
});
我试着用这个对象捕捉响应,这个对象是用curl生成的,我从curl得到的响应

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
        "access_token",
        "token_type",
        "refresh_token",
        "expires_in",
        "scope"
})
public class UserToken {

    @JsonProperty("access_token")
    private String accessToken;
    @JsonProperty("token_type")
    private String tokenType;
    @JsonProperty("refresh_token")
    private String refreshToken;
    @JsonProperty("expires_in")
    private long expiresIn;
    @JsonProperty("scope")
    private String scope;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     *
     * @return
     * The accessToken
     */
    @JsonProperty("access_token")
    public String getAccessToken() {
        return accessToken;
    }
..........
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
“访问令牌”,
“令牌类型”,
“刷新令牌”,
“在中过期”,
“范围”
})
公共类用户令牌{
@JsonProperty(“访问令牌”)
私有字符串访问令牌;
@JsonProperty(“令牌类型”)
私有字符串类型;
@JsonProperty(“刷新令牌”)
私有字符串刷新令牌;
@JsonProperty(“到期日”)
私人长呼气素;
@JsonProperty(“范围”)
私有字符串范围;
@杰索尼奥雷
私有映射additionalProperties=new HashMap();
/**
*
*@返回
*accessToken
*/
@JsonProperty(“访问令牌”)
公共字符串getAccessToken(){
返回accessToken;
}
..........
根据改装日志,所有接缝均应良好:

10-24 10:54:44.365  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ ---> HTTP POST http://192.168.0.102:8080/oauth/token?username=username&password=password&grant_type=password&scope=read&client_id=webappId&client_secret=webAppSecret
10-24 10:54:44.365  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Authorization: Basic UmlrdXlXZWJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==
10-24 10:54:44.365  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Content-Type: application/json; charset=UTF-8
10-24 10:54:44.365  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Content-Length: 2
10-24 10:54:44.368  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ ""
10-24 10:54:44.368  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ ---> END HTTP (2-byte body)
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ <--- HTTP 200 http://192.168.0.102:8080/oauth/token?username=username&password=password&grant_type=password&scope=read&client_id=webappId&client_secret=webAppSecret (208ms)
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Server: Apache-Coyote/1.1
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ X-Content-Type-Options: nosniff
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ X-XSS-Protection: 1; mode=block
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Cache-Control: no-cache, no-store, max-age=0, must-revalidate
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Pragma: no-cache
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Expires: 0
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ X-Frame-Options: DENY
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ X-Application-Context: application:dev:8080
10-24 10:54:44.576  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Cache-Control: no-store
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Pragma: no-cache
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Content-Type: application/json;charset=UTF-8
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Transfer-Encoding: chunked
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ Date: Sat, 24 Oct 2015 15:54:44 GMT
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ OkHttp-Selected-Protocol: http/1.1
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ OkHttp-Sent-Millis: 1445702084460
10-24 10:54:44.577  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ OkHttp-Received-Millis: 1445702084573
10-24 10:54:44.578  29537-29815/mobile.rikuy.com.co.androidoauthclient D/Retrofit﹕ {"access_token":"26eb7fa0-16fc-4a78-8977-19d2d4125e74","token_type":"bearer","refresh_token":"f657059b-c85e-4021-8600-7f8990243a6f","expires_in":1759,"scope":"read"}
10-24 10:54:44.365 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ ---> HTTP POSThttp://192.168.0.102:8080/oauth/token?username=username&password=password&grant_type=password&scope=read&client_id=webappId&client_secret=webAppSecret
10-24 10:54:44.365 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ 授权:基本UmlrdXlXZWJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==
10-24 10:54:44.365 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ 内容类型:application/json;字符集=UTF-8
10-24 10:54:44.365 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ 内容长度:2
10-24 10:54:44.368 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ ""
10-24 10:54:44.368 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ ---> 结束HTTP(2字节正文)

10-24 10:54:44.576 29537-29815/mobile.rikuy.com.co.androidoauthclient D/改装﹕ 经过几天的努力寻找解决方案后,我发现不仅@JsonProperty(“access_token”)字段与转换过程相关,而且字段和方法名称对转换过程也很重要,因此当我将pojo从

@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
        "access_token",
        "token_type",
        "refresh_token",
        "expires_in",
        "scope"
})
public class UserToken {

    @JsonProperty("access_token")
    private String accessToken;
    @JsonProperty("token_type")
    private String tokenType;
    @JsonProperty("refresh_token")
    private String refreshToken;
    @JsonProperty("expires_in")
    private long expiresIn;
    @JsonProperty("scope")
    private String scope;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    /**
     *
     * @return
     * The accessToken
     */
    @JsonProperty("access_token")
    public String getAccessToken() {
        return accessToken;
    }
..........
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
“访问令牌”,
“令牌类型”,
“刷新令牌”,
“在中过期”,
“范围”
})
公共类用户令牌{
@JsonProperty(“访问令牌”)
私有字符串访问令牌;
@JsonProperty(“令牌类型”)
私有字符串类型;
@JsonProperty(“刷新令牌”)
私有字符串刷新令牌;
@JsonProperty(
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({
        "access_token",
        "token_type",
        "refresh_token",
        "expires_in",
        "scope"
})
public class UserToken {

    @JsonProperty("access_token")
    private String access_token;
    @JsonProperty("token_type")
    private String token_type;
    @JsonProperty("refresh_token")
    private String refresh_token;
    @JsonProperty("expires_in")
    private long expires_in;
    @JsonProperty("scope")
    private String scope;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();

    public String getAccess_token() {
        return access_token;
    }