我正在尝试使用AA来使用RESTful API。我的API接收电子邮件和密码请求参数(不是JSON!)并返回APIKey
(我使用Jackson2反序列化)。
理想情况下,我想使用常规的旧Map<String, String>
发送电子邮件和密码,但似乎AA要求我使用MultiValueMap
(Map<K,List<V>>
),或者自定义类(Event
,未显示任何来源)。
使用MultiValueMap
时,会发送array
。我没有发送一系列电子邮件和密码,我发送一封电子邮件和密码:
// 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绊倒,因为它需要一个String而不是一个字符串数组。
所以我认为我必须创建一个自定义Credentials
对象来保存我的电子邮件和密码,并以某种方式将其序列化以发送到服务器。有人可以帮我解决这个问题吗?
答案 0 :(得分:1)
您是否未使用Android Annotations提供的内置身份验证机制?像Basic Auth或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以POST到您的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 }
等。
答案 1 :(得分: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);
}
}