【问题标题】:Handling POST requests with Android Annotations使用 Android 注解处理 POST 请求
【发布时间】:2014-05-14 17:40:12
【问题描述】:

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

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

使用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,因为它需要一个字符串而不是字符串数组。

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

【问题讨论】:

    标签: java android serialization android-annotations spring-android


    【解决方案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 以 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 } 等。

    【讨论】:

    • 这个 API 不支持基本身份验证,并且 login() 是一个 POST 请求,所以附加到 URL 不应该解决我的问题(我也不确定这是否安全)。事实上,我确实使用该页面中的拦截器模式为所有请求注入必要的 API 密钥。但是,我的问题是关于发送带有 Android 注释的 POST 数据,而不是身份验证。我正在专门寻找一种方式(可能是 POJO?)通过 POST 发送电子邮件和密码(即:email=me@example.com,password=example)。他们在示例中使用的 Event 类无处可寻。
    【解决方案2】:

    我知道你已经弄清楚了,但请查看我使用的其余拦截器。基本上,它将一个 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);
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      • 1970-01-01
      • 2016-09-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多