Java 使用Android注释处理POST请求
我正在尝试使用AA使用RESTful API。我的API接收电子邮件和密码请求参数(不是JSON!),并返回一个Java 使用Android注释处理POST请求,java,android,serialization,android-annotations,spring-android,Java,Android,Serialization,Android Annotations,Spring Android,我正在尝试使用AA使用RESTful API。我的API接收电子邮件和密码请求参数(不是JSON!),并返回一个APIKey(我使用Jackson2进行反序列化) 理想情况下,我希望使用常规的映射发送电子邮件和密码,但AA似乎要求我使用多值映射(这是映射),或自定义类(事件,没有显示源代码) 使用多值映射时,会发送一个数组。我发送的不是一系列电子邮件和密码,而是单个电子邮件和密码: // LoginFragment.java MultiValueMap<String
APIKey
(我使用Jackson2进行反序列化)
理想情况下,我希望使用常规的映射
发送电子邮件和密码,但AA似乎要求我使用多值映射
(这是映射
),或自定义类(事件
,没有显示源代码)
使用多值映射
时,会发送一个数组
。我发送的不是一系列电子邮件和密码,而是单个电子邮件和密码:
// 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);
//LoginFragment.java
多值映射凭据=新建LinkedMultiValueMap();
凭证。添加(“电子邮件”,电子邮件);
凭证。添加(“密码”,密码);
APIKey resp=userRest.login(凭证);
//UserRest.java
@Post(“用户/登录”)
公钥登录(多值映射凭证);
这会破坏我的API,因为它需要的是字符串而不是字符串数组
因此,我想我必须创建一个自定义的
凭证
对象来保存我的电子邮件和密码,并以某种方式将其序列化以发送到服务器。有人能帮我解决这个问题吗?你没有考虑过使用Android注解提供的内置身份验证机制吗?像Basic Auth还是OAuth?这可能是一个更干净的解决方案
我使用了基本的身份验证选项-
您只需向接口添加一个方法:
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方法。您可能需要添加一个拦截器,这取决于您希望解析ie
converters={MappingJacksonHttpMessageConverter.class}
等的数据类型。我知道您已经找到了它,但请查看我使用的其余拦截器。基本上,它将一个api_密钥、访问_令牌和一个hmac_sig附加到头中的每个请求。然后您可以验证credientials服务器端
@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);
}
@EBean(scope=scope.Singleton)
公共类RestInterceptor实现ClientHttpRequestInterceptor{
private int requestCount=0;
@优先股
MyPrefs_uuMyPrefs;
私有请求侦听器mRequestListener;
公共接口请求侦听器{
无效报告(整数计数);
}
public void setOnRequestListener(RequestListener RequestListener){
this.mRequestListener=requestListener;
}
公共ClientHttpResponse截获(HttpRequest请求,字节[]数据,ClientHttpPrequesteExecution执行)
抛出IOException{
if(mRequestListener!=null){
requestCount++;
mRequestListener.report(requestCount);
}
HttpHeaders=request.getHeaders();
long unixTime=System.currentTimeMillis()/1000L;
headers.add(“request_time”,String.valueOf(unixTime));
如果(myPrefs.accessToken().exists()){
headers.add(“access_token”,myPrefs.accessToken().get());
String hmacInput;//省略了这一部分,但基本上是在这里执行请求特有的操作,并在另一端执行相同的操作。
字符串hmacKey=myPrefs.accessToken().getOr(“”);
试一试{
字符串hmacSig=hmacSha1(hmaciput,hmacKey);
标题。添加(“hmac_sig”,hmacSig);
}
捕获(InvalidKeyException e){
e、 printStackTrace();
}
捕获(无算法异常){
e、 printStackTrace();
}
}
如果(myPrefs.userId().exists()){
headers.add(“user_id”,String.valueOf(myPrefs.userId().get());
}
添加(“api_键”、“somerandomstring”);
ClientHttpResponse t=execution.execute(请求、数据);
if(mRequestListener!=null){
请求计数--;
mRequestListener.report(requestCount);
}
返回t;
}
public void resetRequestCount(){
this.requestCount=0;
}
公共静态字符串hmacSha1(字符串值,字符串键)引发UnsupportedEncodingException,
NoSuchAlgorithmException,InvalidKeyException{
字符串类型=“HmacSHA1”;
SecretKeySpec secret=新的SecretKeySpec(key.getBytes(),type);
Mac Mac=Mac.getInstance(类型);
mac.init(秘密);
byte[]bytes=mac.doFinal(value.getBytes());
返回bytesToHex(字节);
}
私有最终静态字符[]hexArray=“0123456789abcdef”.toCharArray();
私有静态字符串bytesToHex(字节[]字节){
char[]hexChars=新字符[bytes.length*2];
INTV;
对于(int j=0;j>>4];
hexChars[j*2+1]=hexArray[v&0x0F];
}
返回新字符串(hexChars);
}
}此API不支持基本身份验证,而login()是一个POST请求,因此附加到URL不会解决我的问题(我也不确定这是否安全)。事实上,我确实使用了该页面中的拦截器模式为所有请求注入必要的API密钥。然而,我的问题是关于发送带有Android注释的POST数据,而不是验证。我特别寻找一种方法(可能是POJO?)通过POST发送电子邮件和密码(即:电子邮件)=me@example.com,密码=示例)。他们在示例中使用的事件类找不到。