0

我正在尝试使用 AA 使用 RESTful API。我的 API 接收电子邮件和密码请求参数(不是 JSON!)并返回一个APIKey(我使用 Jackson2 反序列化)。

理想情况下,我想使用普通的旧Map<String, String>来发送电子邮件和密码,但似乎 AA 要求我使用 a MultiValueMap(即 a Map<K,List<V>>)或自定义类(Event,未显示源)。

使用 aMultiValueMap时,array发送 an。我不是在发送一系列电子邮件和密码,而是发送一个电子邮件和密码:

// LoginFragment.java            
MultiValueMap<String, String> credentials = new LinkedMultiValueMap<String, String>();
credentials.add("email", email);
credentials.add("password", password);
APIKey resp = userRest.login(credentials);


// UserRest.java
@Post("user/login")
public APIKey login(MultiValueMap credentials);

这让我的 API 出错了,因为它需要一个字符串而不是字符串数组。

所以我想我必须创建一个自定义Credentials对象来保存我的电子邮件和密码,并以某种方式将其序列化以发送到服务器。有人可以帮我解决这个问题吗?

4

2 回答 2

1

您是否没有考虑过使用 Android Annotations 提供的内置身份验证机制?喜欢基本身份验证或 OAuth?这可能是一个更清洁的解决方案。

https://github.com/excilys/androidannotations/wiki/Authenticated-Rest-Client

我使用了基本身份验证选项 - https://github.com/excilys/androidannotations/wiki/Rest%20API

您只需要在界面中添加一个方法:

void setHttpBasicAuth(String username, String password);

然后在进行 API 调用之前调用它。OAuth 应该有类似的选项。

编辑: 您可以创建一个登录 POJO 以发布到您的 API:

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
        "name",
        "password"

})
public class Login{
    @JsonProperty("name")
    private String name;
    @JsonProperty("password")
    private String password;

}

然后在您的 API 接口中,您可以执行以下操作:

  @Post("user/login")
    public APIKey login(Login credentials);

然后,这会将您的数据发布到 /user/login 方法。您可能需要添加一个拦截器,具体取决于您希望解析的数据类型converters = { MappingJacksonHttpMessageConverter.class }等。

于 2014-05-21T09:06:53.843 回答
1

我知道您已经弄清楚了,但请查看我使用的其余拦截器。基本上,它将一个 api_key、access_token 和一个 hmac_sig 附加到标头中的每个请求。然后您可以验证凭据服务器端

@EBean(scope = Scope.Singleton)
public class RestInterceptor implements ClientHttpRequestInterceptor {

private int requestCount = 0;

@Pref
MyPrefs_ myPrefs;

private RequestListener mRequestListener;

public interface RequestListener {
    void report(int count);
}

public void setOnRequestListener(RequestListener requestListener) {
    this.mRequestListener = requestListener;
}

public ClientHttpResponse intercept(HttpRequest request, byte[] data, ClientHttpRequestExecution execution)
        throws IOException {

    if (mRequestListener != null) {
        requestCount++;
        mRequestListener.report(requestCount);
    }

    HttpHeaders headers = request.getHeaders();

    long unixTime = System.currentTimeMillis() / 1000L;

    headers.add("request_time", String.valueOf(unixTime));

    if (myPrefs.accessToken().exists()) {

        headers.add("access_token", myPrefs.accessToken().get());


        String hmacInput; //left this part out but basically do something unique to the request here and do the same on the other side.

        String hmacKey = myPrefs.accessToken().getOr("");


        try {
            String hmacSig = hmacSha1(hmacInput, hmacKey);

            headers.add("hmac_sig", hmacSig);

        }
        catch (InvalidKeyException e) {

            e.printStackTrace();
        }
        catch (NoSuchAlgorithmException e) {

            e.printStackTrace();
        }


    }
    if (myPrefs.userId().exists()) {
        headers.add("user_id", String.valueOf(myPrefs.userId().get()));
    }

    headers.add("api_key", "somerandomstring");

    ClientHttpResponse t = execution.execute(request, data);

    if (mRequestListener != null) {

        requestCount--;
        mRequestListener.report(requestCount);
    }

    return t;
}


public void resetRequestCount() {
    this.requestCount = 0;
}

public static String hmacSha1(String value, String key) throws UnsupportedEncodingException,
        NoSuchAlgorithmException, InvalidKeyException {
    String type = "HmacSHA1";
    SecretKeySpec secret = new SecretKeySpec(key.getBytes(), type);
    Mac mac = Mac.getInstance(type);
    mac.init(secret);
    byte[] bytes = mac.doFinal(value.getBytes());
    return bytesToHex(bytes);
}

private final static char[] hexArray = "0123456789abcdef".toCharArray();

private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

}

于 2014-06-05T00:33:20.147 回答