且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

iOS:使用XMLHttpRequest进行身份验证 - 处理401响应

更新时间:2023-12-03 10:25:34

这在iOS上。一个是iOS有一个与基本的验证有关的错误,所以如果你的密码有一些特殊的字符,你永远不会从你的服务器回应,因为你的服务器永远不会得到身份验证的挑战。也就是说,如果您在打开方法中使用用户名和密码字段。

A few things became apparent to me while trying to do this on iOS. One is that iOS has a bug relating to basic auth, so if your password has certain special characters in it you'll never get a response back from your server because your server will never get an authentication challenge. That is, if you're using the username and password field in the "open" method.

我的猜测是,他们正在做一些愚蠢的事情, http:// username:password@myorigin.com/etc ,他们应该使用http头和base64编码的凭证,如

My guess is they are doing something stupid like sending it via http://username:password@myorigin.com/etc when they should be using http headers and base64 encoding the creds like so

req.setRequestHeader("Authorization", "Basic " + base64(username) + ':' + base64(password));

我学到的另一件事是,Basic Auth非常安全,容易出现一百万个问题。其中一个会让你烦恼的是,客户端将缓存用户名和密码,这将覆盖您通过req.open(...)发送的任何新值。

The other thing I learned is that Basic Auth isnt very secure and is prone to a million and one problems. One of which that will annoy you is that the client will cache the username and password, which will override any new values you send via "req.open(...)". Good luck getting around that using javascript alone, you'll have to do some magic in ObjC to clear the cache.

如果你可以控制你的服务器,我会建议你使用令牌认证。通过SSL连接,然后发送包含用户名和密码的JSON数据的POST。服务器然后可以发回带有认证令牌的JSON数据(基本上一堆足够长的随机字符,它不能被猜到,UUID工作良好。这由服务器生成,并且只能被客户端知道,服务器)。然后将令牌和用户名存储在钥匙串中,这样用户无需在每次启动应用程序时输入其凭据。

If you have control over your server, I would suggest using token authentication. Connect over SSL and then send a POST with JSON data containing the username and password. The server could then send back JSON data with an authentication token (essentially a bunch of random characters long enough that it can't ever be guessed, a UUID works well. this is generated by the server and can only be known to the client and the server). Then store the token and the username in the keychain so the user doesnt need to enter their creds everytime they start your app.

我的服务器将始终发送200响应,但是JSON数据将包含重试或存储身份验证令牌所需的信息。一般来说...基本的auth基本上很糟糕。

My server will always send back a 200 response but the JSON data will contain the information needed to either retry or to store the auth token. In general... basic auth basically sucks.

try {
    var req = new XMLHttpRequest();
    req.onload = function(ev) {
        var response = JSON.parse(this.responseText);
        if (response.success === true) {
            // The server will respond with a token that will allow us to login
            storeCredentials(userValue, response.token);
            // redirect with token
        else if (req.status == 401) {
            alert("Invalid Username/Password");
            document.getElementById('password').focus();
        } else {
            alert("Some other status");
        }
    }
    req.ontimeout = setTimeout(function(ev) { navigator.notification.alert('Timeout trying to contact the server'); }, 10000);
    req.onerror = function(ev) { clearTimeout(this.ontimeout); navigator.notification.alert('Error connecting to the server during authentication.'); };

    var uri = myWebOrigin + '/authenticate';
    req.open('POST', uri, true);
    req.setRequestHeader('Cache-Control', 'no-cache');
    req.setRequestHeader('Content-Type', 'application/json');
    json_data = {username : Base64.encode(userValue), password : Base64.encode(passValue)};
    req.send(JSON.stringify(json_data));
} catch(error) {
    navigator.notification.alert('Uh oh, an error occurred trying to login! ' + error);
    return;
}