0

I am using AFNetworking to perform login and the url format is like this:

http://xxx/mobile?function=login&req={username:xxx,password:xxx}

So firstly I created the parameters using a NSDictionary within a NSDictionary, like below:

@{@"function" : @"login",
  @"req" : @{@"username" : @"xxx", @"password" : @"xxx"}}

But the query comes out is wrong

function=login&req[password]=xxx&req[username]=xxx

After this, I used JSONKit to package the parameter

NSDictionary *userInfo = @{@"userName" : [username URLEncodedString],
                           @"password" : [password URLEncodedString]};

NSDictionary *parameters = @{@"function" : @"login",
                           @"req" : [userInfo JSONString]};

And the results seem alike but "{}" encoded

function=login&req=%7B%22userName%22%3A%22xxx%22%2C%22password%22%3A%22xxx%22%7D

Where did I goes wrong? How can I correct it? Many Thanks!

Mr. Crow
  • 21
  • 2
  • 6
  • Try `POST` instead of `URL rewriting` or `GET`, because the characters you are passing in as parameters are not readable so it gets converted to its equivalent ASCII code.. – iphonic Apr 03 '14 at 06:11
  • I doubt that a server will accept a query which is some kind of JSON and which is encoded with the algorithm recommended by W3C `application/x-www-form-urlencoded`. AFN's implementation doesn't strictly follow this rule anyway. So, what you actually have to do depends on the server: find the documentation and read the API which is purposefully defined in terms of HTTP. – CouchDeveloper Apr 03 '14 at 06:39
  • @iphonic I did use `POST` method, the query string is what I find after traced into the AFNetworking – Mr. Crow Apr 03 '14 at 07:14
  • @Rob Hi Rob, this login function is under testing and my friend working on Android told me that the "{" "}" and ":" in the query string are not encoded and it works – Mr. Crow Apr 03 '14 at 08:06

1 Answers1

0

There are a couple of issues here.

  1. You seemed to be concerned about the percent escapes in the portion of the URL that looks like:

    function=login&req=%7B%22userName%22%3A%22xxx%22%2C%22password%22%3A%22xxx%22%7D
    

    You shouldn't be concerned about that, because when the server receives it, it will automatically convert that to:

    function=login&req={"userName":"xxx","password":"xxx"}
    

    You report that an associate is telling you that the percent escapes are not needed. Technically, he might be right (you might get away without percent-escaping in this case, as long as the username and password do not have certain particular reserved characters, notably +, & or #, which can cause problems in URLs), but per the RFC's regarding URLs, all of those characters really should be percent-escaped. And the the server will automatically un-percent-escape the parameter, so you shouldn't worry about the fact that the request was percent-escaped. And, in fact, if you want this interface to be robust, both the iOS and Android clients really should be percent-escaping values like this that you add to the URL.

  2. What would appear to be problematic, though, is that the above example includes double quotes, whereas you suggested that the server is expecting something like:

    {username:xxx,password:xxx}
    

    But that's not valid JSON. Valid JSON would be:

    {"userName":"xxx","password":"xxx"}
    

    So, are you really confident that your web service wants/needs invalid JSON? If you absolutely need invalid JSON (and I'd be shocked if that's where you want to go on this), you'd have to build it manually with stringWithFormat, as any JSON class worth its weight in salt would not be able to generate the JSON without the quotes.

  3. I'd discourage you from sending userid and password information in the URL. That represents a security risk, where this information can easily be compromised. You really should be putting these authentication details in the body of a POST request, not in the URL of a GET request. (And, obviously, you'd want to use HTTPS, not HTTP.)

  4. I also question, with all due respect, the approach of mixing x-www-form-urlencoded style parameters (for function and req), but then using JSON for the userName and password. Generally you'd either use x-www-form-urlencoded style requests, or JSON requests, but it's very curious to combine the two together. You can, but it's just a little strange.

So, bottom line, while you can build the URL you describe (doing it manually with stringWithFormat), I'd really encourage you to redesign your web service to (a) receive POST requests with authentication details in the body of the request; and (b) use either JSON or x-www-form-urlencoded, but you probably don't want to mix-and-match.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • 1
    Thanks for your **Careful** answer! Learned a lot! For the second issue you mentioned, it is my fault. I just want to explain the structure but forgot the JSON format rules. The server will run **HTTPS** later but use **HTTP** for testing. – Mr. Crow Apr 04 '14 at 02:33
  • @Mr.Crow That's great that your production server will be running HTTPS. Just make sure to move the request parameters into the body, though, or it will be for naught. Good luck! – Rob Apr 04 '14 at 03:36