10

In my Android app I have to call a web service which looks like this

http://mywesite.com/demo/mob/getmenubycategory/1

I am using the volley to send the request but the result is VolleyError 401. I have overridden the getParams() method to add the header, but it is not working.

Here is my code.

RequestQueue requestQueue = volleySingleton.getRequestQueue();
    requestQueue.add(new JsonObjectRequest(Request.Method.GET, url, new Response.Listener<JSONObject>() {
        @Override
        public void onResponse(JSONObject response) {
            Log.e(TAG, "onResponse = \n " + response.toString());
        }
    }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            Log.e(TAG, "response error \n" + error.networkResponse.statusCode);
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            try {
                Map<String, String> map = new HashMap<String, String>();
                String key = "Authorization";
                String encodedString = Base64.encodeToString(String.format("%s:%s", "USERNAME", "Password").getBytes(), Base64.NO_WRAP);
                String value = String.format("Basic %s", encodedString);
                map.put(key, value);
                return map;
            } catch (Exception e) {
                Log.e(TAG, "Authentication Filure" );
            }
            return super.getParams();
        }
    });

When I use my browser it shows a dialogue to enter my username and password. How can I send the username and password with the request using Volley.

halfer
  • 19,824
  • 17
  • 99
  • 186
Sony
  • 7,136
  • 5
  • 45
  • 68

3 Answers3

31

For authentication, IMHO, you should override getHeaders instead of getParams, please try the following:

@Override
public Map<String, String> getHeaders() throws AuthFailureError {
       Map<String, String> headers = new HashMap<>();                
       String credentials = "username:password";
       String auth = "Basic "
                        + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
       headers.put("Content-Type", "application/json");
       headers.put("Authorization", auth);
       return headers;
}

Hope it helps!

BNK
  • 23,994
  • 8
  • 77
  • 87
  • 2
    Thanks! Using `getHeaders()` instead of `getParams()` solved my problem. – Sdghasemi Aug 12 '16 at 16:41
  • So this means creating your own Request extension? How do you pass the username:password data and where do the tokens go? – G_V Aug 25 '16 at 20:07
  • @G_V the question is about basic authentication and as you see in my sample code `String credentials = "username:password";`, about the tokens, do you mean access token sent to web service? If yes, it's also in `getHeaders();` – BNK Aug 26 '16 at 02:54
  • @BNK I am completely new to doing anything security but this means storing the username and password, putting them in the header, sending them, getting a token and then clearing user/pass out in favor of storing the token then? – G_V Aug 27 '16 at 08:00
  • @G_V yes, however, it depends on the web service that your android app sending requests, for example, if your web service is ASP.NET Web API, you can see some flows at https://www.asp.net/web-api/overview/security/individual-accounts-in-web-api – BNK Aug 27 '16 at 08:16
  • 1
    @G_V please read http://stackoverflow.com/questions/31466653/how-to-use-security-authentication-authorization-in-asp-web-api/31471027#31471027 – BNK Aug 27 '16 at 08:20
1

just override this method

 @Override
        public Map<String, String> getHeaders() {
            String username ="danish@gmail.com";
            String password = "dani3173";
            String auth =new String(username + ":" + password);
            byte[] data = auth.getBytes();
            String base64 = Base64.encodeToString(data, Base64.NO_WRAP);
            HashMap<String, String> headers = new HashMap<String, String>();
            headers.put("Authorization",base64);
            headers.put("accept-language","EN");
            headers.put("Content-type","application/json");
            headers.put("Accept","application/json");
            return headers;
        }
Syed Danish Haider
  • 1,334
  • 11
  • 15
0

Use CustomVolleyRequest as I use below

public class CustomVollyRequest extends Request<JSONObject> {
    private Listener<JSONObject> listener;
    private Map<String, String> params;

    public CustomVollyRequest(String url, Map<String, String> params, 
            Listener<JSONObject> reponseListener, 
            ErrorListener errorListener) {
        super(Method.GET, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    public CustomVollyRequest(int method, String url, Map<String, String> params, 
            Listener<JSONObject> reponseListener, 
            ErrorListener errorListener) {
        super(method, url, errorListener);
        this.listener = reponseListener;
        this.params = params;
    }

    @Override
    protected Map<String, String> getParams() throws com.android.volley.AuthFailureError {
        return params;
    }

    @Override
    protected void deliverResponse(JSONObject response) {
        listener.onResponse(response);
    }

    @Override
    protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
        try {
            String jsonString = new String(response.data,     HttpHeaderParser.parseCharset(response.headers));
            return Response.success(new JSONObject(jsonString),
                HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException je) {
            return Response.error(new ParseError(je));
    }
}

Use the above class as below

Map<String, String> params = new HashMap<>();
params.put("key",value);//put your parameters here
CustomVollyRequest jsObjRequest = new CustomVollyRequest(
        Request.Method.POST, url, params,
        new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject response) {
                //Log.d("Response: ", response.toString());
            }
        }, 
        new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError response)
            {
                Log.d("Response: Error", response.toString());
            }
        }
);
Hadi Note
  • 1,386
  • 17
  • 16
Muhammad Younas
  • 1,543
  • 1
  • 22
  • 32