第一部分:http认证介绍
摘要认证 digest authentication ← HTTP1.1提出的基本认证的替代方法
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Digest
realm="testrealm@host.com",
qop="auth,auth-int",
nonce="dcd98b7102dd2f0e8b11d0f6
opaque="5ccc069c403ebaf9f0171e95
? realm : 响应中包含信息
? nonce
? username
? digest-uri
? response
Authorization: Digest
username="Mufasa", ← 客户端已知信息
realm="testrealm@host.com", ← 服务器端质询响应信息
nonce="dcd98b7102dd2f0e8b11d0f6
uri="/dir/index.html", ← 客户端已知信息
qop=auth, ← 服务器端质询响应信息
nc=00000001, ← 客户端计算出的信息
cnonce="0a4f113b", ← 客户端计算出的客户端nonce
response="6629fae49393a05397450978
opaque="5ccc069c403ebaf9f0171e95
上面摘自:http://blog.csdn.net/hotnet522/article/details/5824716
第二部分:摘要认证在ios中实现
备注:我实现的摘要认证是针对某一个特定的服务器。如果是别的服务器我觉得步骤大同小异,有什么不对请多多指教。
第一步:先发一个请求给服务器:
第二步:从-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response方法中得到状态码401.然后编码[request1 addValue:auth forHTTPHeaderField:@"Authorization"];
注意我当时auth字符串中
中添加了\r\n。结果Authorization显示不出来。
第三步:再重新请求发给同一个服务器地址。
demo:
viewController.m
#import "HttpConnection"
-(void)click
{
}
HttpConnection.h
#import
@class HttpConnection;
@protocol HttpConnectionDelegate
-(void)downloadComplete:(HttpConnection*)hc;
-(void)downloadFail:(HttpConnection*)hc;
@end
@interface HttpConnection : NSObject,NSURLConnectionDataDeleg
{
}
@property(nonatomic,assign)id<>HttpConnectionDelegate>delegate;
@property(nonatomic,retain)NSMutableData *downloadData;
-(void)downLoadFromUrl:(NSString *)urlStr;
@end
HttpConnection.m
#import "HttpConnection.h"
#import "NSString+Hashing.h"//这个是MD5算法类
@implementation HttpConnection
{
}
@synthesize delegate=_delegate;
@synthesize downloadData=_downloadData;
- (void)dealloc
{
}
-(id)init
{
}
//下载
-(void)downLoadFromUrl:(NSString *)urlStr
{
}
#pragma mark -
#pragma mark - NSUrlConnect delegate method
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
-(void)connectionDidFinishLoadi
{
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}
#pragma mark 解析401得到Authorization字段
-(NSString*)handle401Code:(NSHTTPURLResponse *)response
{
}
@end
************************************************************************************************************************************
背景:项目做的差不多了,不过在http认证这块有一个很大的隐患:当第一个启动程序时 http认证没有问题,之后当程序安装到手机上时,再次启动就有可能出现循环401 并且代码没变 用户名和密码都没错。终于有时间下定决心好好研究这块
第一:第一次运行xcode,把程序安装到iphone模拟器上,使用Wireshark抓包发现:401-401-》200 ok。两次401,一次200 ok。
当程序装到iphone虚拟器上时,再次运行xcode,使用Wireshark抓包发现:401-401-27304 ok。两次401,一次27304.ok。
疑问:为什么会出现两次401呢,我检查程序中我只实现一次。
决定重新研究一下401这块,看苹果sdk发现
1.Authentication Challenges and TLS Chain Validation
An NSURLRequest object often encounters an authentication challenge, or a request for credentials from the server it is connecting to. The NSURLSession, NSURLConnection, and NSURLDownload classes notify their delegates when a request encounters an authentication challenge, so that they can act accordingly.
Important:
URL调用系统类除非是服务器响应中带有www-Authenticate 头域,否则不会使代理来处理请求挑战。
2.Deciding How to Respond to an Authentication Challenge
If an NSURLRequest object requires authentication, the way that the challenge is presented to your app varies depending on whether the request is performed by an NSURLSession object, an NSURLConnection object, or an NSURLDownload object:
- If the request is associated with an NSURLSession object, all authentication requests are passed to the delegate, regardless of authentication type.
- If the request is associated with an NSURLConnection or NSURLDownload object, that object’s delegate receives a connection:canAuthenticateAgainstPr
otectionSpace: (or download:canAuthenticateAgainstPr otectionSpace:) message. This allows the delegate to analyze properties of the server, including its protocol and authentication method, before attempting to authenticate against it. If your delegate is not prepared to authenticate against the server’s protection space, you can return NO, and the system attempts to authenticate with information from the user’s keychain. - If the delegate of an NSURLConnection or NSURLDownload object does not implement the connection:canAuthenticateAgainstPr
otectionSpace: (or download:canAuthenticateAgainstPr otectionSpace:) method and the protection space uses client certificate authentication or server trust authentication, the system behaves as if you had returned NO. The system behaves as if you returned YES for all other authentication types.
Next, if your delegate agrees to handle authentication and there are no valid credentials available, either as part of the requested URL or in the shared NSURLCredentialStorage, the delegate receives one of the following messages:
- URLSession:didReceiveChallenge:completionHandler:
- URLSession:task:didReceiveChallenge:completionHandler:
- connection:didReceiveAuthentication
Challenge: - download:didReceiveAuthentication
Challenge: - 第一步是NSURLConnection类的代理,下一步是connection:didReceiveAuthentication
Challenge: 而这个后来被connection:willSendRequestForAuthen ticationChallenge: 替代
3.备注:If connection:willSendRequestForAuthen
4.Responding to an Authentication Challenge
Providing Credentials
To attempt to authenticate, the application should create an NSURLCredential object with authentication information of the form expected by the server. You can determine the server’s authentication method by calling authenticationMethod on the protection space of the provided authentication challenge. Some authentication methods supported by NSURLCredential are:
- HTTP basic authentication (NSURLAuthenticationMetho
dHTTPBasic) requires a user name and password. Prompt the user for the necessary information and create an NSURLCredential object with credentialWithUser:password:persistence:. - HTTP digest authentication (NSURLAuthenticationMetho
dHTTPDigest), like basic authentication, requires a user name and password. (The digest is generated automatically.) Prompt the user for the necessary information and create an NSURLCredential object with credentialWithUser:password:persistence:. - Client certificate authentication (NSURLAuthenticationMetho
dClientCertificate) requires the system identity and all certificates needed to authenticate with the server. Create an NSURLCredential object with credentialWithIdentity:certificates:persistence:. - Server trust authentication (NSURLAuthenticationMetho
dServerTrust) requires a trust provided by the protection space of the authentication challenge. Create an NSURLCredential object with credentialForTrust:.
After you’ve created the NSURLCredential object:
- For NSURLSession, pass the object to the authentication challenge’s sender using the provided completion handler block.
- For NSURLConnection and NSURLDownload, pass the object to the authentication challenge’s sender with useCredential:forAuthenticationChallen
ge:.
5.An Authentication Example
The implementation shown in Listing 6-1 responds to the challenge by creating an NSURLCredential instance with a user name and password supplied by the application’s preferences. If the authentication has failed previously, it cancels the authentication challenge and informs the user.
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthen
{
}
6.demo:
#pragma mark -
#pragma mark - NSUrlConnect delegate method
-(void)connection:(NSURLConnection *)connection willSendRequestForAuthen
{
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
}
-(void)connectionDidFinishLoadi
{
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}
//通过上面输出可以看出这是http 摘要认证。_password.MD5Hash用户密码传的是经过md5编码后的,因为服务器上的密码也是经过md5使用的。
原理很简单:当发送一个异步request时,收到response里面含有www-Authenticate头域,则执行connection:willSendRequestForAuthen
总结:
1.网络编程时多使用wireshark这样的抓包工具来进行抓包测试。
2.iphone的sDK还需要细心的读。其实第一次在connection: didReceiveResponse:里面截图到401进行重新发送request时,我已经看到上述方法是用在http 基本认证中,当时不是很理解再加上在NSCredential类中的password没有进行md5编码就放弃了,改用在didReceiveResponse中处理401.才造成两次发送401的局面。还是应该锲而不舍。