使用 http auth 从 iOS 访问 RESTful django 时处理非 ascii 登录

handling non-ascii logins when accessing RESTful django from iOS with http auth

我有以下架构:iOS 客户端使用 NSURLConnection 和 willSendRequestForAuthenticationChallenge 来验证基于 Django-rest-framework 的 REST 服务。当登录仅是 ascii 时它工作正常,但是当我使用非 ascii 字母时,它甚至不发送 HTTP_AUTHORIZATION !

这可能是因为 RFC 没有涵盖 HTTP 基本身份验证中的非 ascii 字符。

解决它的最佳方法是什么?摘要认证有帮助吗?

我无法对 url 的登录进行编码,因为我不希望它显示在服务器日志中。我也想留在 willSendRequestForAuthenticationChallenge.

PS:我可以在 Django 端使用基于表单的身份验证或基于 json(通过实施 BaseAuthentication),但在 iOS 上我需要创建NSURLAuthenticationChallenge 这似乎是个大问题

一般来说,HTTP Basic 和 Digest 身份验证都不行,它只是 ASCII 字符,根本没有办法解决这个问题。

但是,因为你在控制后端,所以你可以使用这个技巧:在 iOS 端以 base64 编码用户名和密码,如下所示:

NSData *usernameData = [username dataUsingEncoding:NSUTF8StringEncoding];
NSString *usernameBase64 = [usernameData base64EncodedStringWithOptions:0];

然后使用编码的字符串创建您的 NSURLCredential。由于 HTTP Basic Authentication 已经在 base64 中对凭据进行编码,通过这样做,您将在将凭据发送到服务器之前对凭据进行 两次 编码。

现在在 DRF 端,创建一个 BasicAuthentication 的子 class 并命名为 Base64BasicAuthentication 例如。像这样覆盖 authenticate_credentials

def authenticate_credentials(self, userid, password):
    userid = base64.b64decode(userid)
    password = base64.b64decode(password)
    return super(Base64BasicAuthentication, self).authenticate_credentials(userid, password)

然后只需使用 Base64BasicAuthentication 作为 Django REST Framework 中的默认身份验证 class。这有点 hack,但它应该可以完成工作。