IOS Communicating with Authenticating official document translation of HTTP Servers and HTTP Server Communication certification (6)

Source: Internet
Author: User
Tags http authentication

IOS Communicating with Authenticating official document translation of HTTP Servers and HTTP Server Communication certification (6)

 

 

 

 

Communication authentication with HTTP servers

 

 

This chapter describes how to use CFHTTPAuthentication API for HTTP Server Authentication. It explains how to locate matching verification objects and creden。, apply them to an HTTP request, and store them for future use.

 

 

In general, if an HTTP server returns a 401 or 407 response to your HTTP request, this means that the server requires creden。 for authentication. In the CFHTTPAuthentication API, each set of creden。 is stored in a CFHTTPAuthentication object. Therefore, a separate CFHTTPAuthentication object is required for connecting different servers and different users to the server for authentication. To communicate with the server, the CFHTTPAuthentication object must be applied to HTTP requests. These steps are explained in more detail.

 

 

 

Process Authentication

 

 

Adding support for authentication will allow your application and HTTP server to perform authentication (if the server returns a 401 or 407 response ). Although HTTP authentication is not a difficult concept, it is a complex process for execution. The process is as follows:

 

1. The client sends an HTTP request to the server.

2. The server returns a request to the client.

3. Original requests of the client package credential and send them back to the server.

4. Negotiate between the client and the server.

5. When the server authenticates the client, it returns the response.

 

 

This process requires many steps. The entire graph process is shown in steps 4-1 and 4-2.

 

Figure 4-1 process authentication



 

 

 

Figure 4-2 locate an authentication object


 

When an HTTP request returns a 401 or 407 response, the first step is to find a valid CFHTTPAuthentication object for the customer. The authentication object contains creden。 and other information. When used for HTTP message requests, you can verify your identity with the server. If you have already verified your identity with the server, you will have a valid authentication object. However, in most cases, you will need to create this object with the CFHTTPAuthenticationCreateFromResponse response function. See Listing 4.

 

 

Note: All sample codes about identity authentication are adapted from the ImageClient application.

 

 

 

 

 

 

 

 

Listing 4 Create an authentication object

 

 

 

 

If (! Authentication ){

CFHTTPMessageRef responseHeader =

(CFHTTPMessageRef) CFReadStreamCopyProperty (

ReadStream,

KCFStreamPropertyHTTPResponseHeader

);

 

// Get the authentication information from the response.

Authentication = CFHTTPAuthenticationCreateFromResponse (NULL, responseHeader );

CFRelease (responseHeader );

}

 

 

 

 

 

If the new authentication object is valid, you have completed the authentication and can proceed to Figure 4-1 in step 2. If the authentication object is not valid, then the authentication object and credential are discarded to check whether the credential is bad. For more information about certificates, read Security Credentials ".

 

 

 

The bad credential means that the server does not accept the logon information, and it will continue to listen for new creden. However, if the server certificate is good but still rejects your request, and then the server refuses to talk to you, you must give up. If the credential is bad, retry the entire process and start creating the authentication object until you get the work credential and valid Verification object. In the code, this process should be similar to listing 4-2.

 

 

 

List 4-2 find a valid authentication object

 

CFStreamError err;

If (! Authentication ){

// The newly created authentication object is bad, must return

Return;

 

} Else if (! CFHTTPAuthenticationIsValid (authentication, & err )){

 

// Destroy authentication and credentials

If (credentials ){

CFRelease (credentials );

Credentials = NULL;

}

CFRelease (authentication );

Authentication = NULL;

 

// Check for bad credentials (to be treated separately)

If (err. domain = kCFStreamErrorDomainHTTP &&

(Err. error = kCFStreamErrorHTTPAuthenticationBadUserName

| Err. error = kCFStreamErrorHTTPAuthenticationBadPassword ))

{

RetryAuthorizationFailure (& authentication );

Return;

} Else {

Erroccurredloadingimage (err );

}

}

 

 

 

Listing 4-4 authentication Objects requested by the application

 

Void resumeWithCredentials (){

// Apply whatever credentials we 've built up to the old request

If (! CFHTTPMessageApplyCredentialDictionary (request, authentication,

Credentials, NULL )){

Erroccurredloadingimage ();

} Else {

// Now that we 've updated our request, retry the load

LoadRequest ();

}

}

 

 

 

Keep creden in memory

 

 

If you want to communicate with an authentication server frequently, it is worth reusing the credential to avoid prompting the user for the username and password of the server multiple times. The changes explained in this section should be one-time use of authentication code (such as processing authentication) to store creden。 in memory for reuse.

 

 

Reuse creden. There are three data structure changes you need to make your code.

 

1. Create a variable array to save all authentication objects.

 

CFMutableArrayRef authArray;

 

Instead:

 

CFHTTPAuthenticationRef authentication;

 

2. Create a dictionary to map an authentication object to the credential.

 

 

CFMutableDictionaryRef credentialsDict;

 

Instead:

 

CFMutableDictionaryRef credentials;

 

 

 

3. Maintain these structures to modify the current verification object and the current credential.

 

CFDictionaryRemoveValue (credentialsDict, authentication );

 

Instead:

 

 

CFRelease (credentials );

 

 

Now, after creating an HTTP request, find a matching verification object before each load. A simple, non-optimized method to find the right object can be shown in Listing 4-5.

 

 

 

Listing 4-5 looks for a matching validation object

 

 

CFHTTPAuthenticationRef findAuthenticationForRequest {

Int I, c = CFArrayGetCount (authArray );

For (I = 0; I <c; I ++ ){

CFHTTPAuthenticationRef auth = (CFHTTPAuthenticationRef)

CFArrayGetValueAtIndex (authArray, I );

If (CFHTTPAuthenticationAppliesToRequest (auth, request )){

Return auth;

}

}

Return NULL;

}

 

 

If the authentication array has a matching verification object, then check whether the credential is properly stored. This prevents you from prompting the user to enter the user name and password again. Use the CFDictionaryGetValue function to find the credential, as shown in Listing 4-6.

 

Listing 4-6 search Credential Storage

 

Credentials = CFDictionaryGetValue (credentialsDict, authentication );

 

 

 

Then the app matches the original HTTP request of the verification object and credential and resends it.

 

 

 

Warning: Invalid creden。 are required before the HTTP request receiving server. Since your server may change during the last authentication, you can create a security risk.

 

 

 

With these changes, your application will be able to store authentication objects and creden。 in memory for future use.

 

 

 

 

 

 

 

 

 

Persistence storage creden

 

 

 

 

 

Storing creden in the memory prevents users from re-entering the server user name and password to start in this specific application. However, when the application exits, these certificates will be released. To avoid losing creden, save them in a persistent storage, and the certificates of each server must be generated only once. Key chains are recommended for storing creden. Even if you can have multiple keys, this document refers to your default key chain. Using a key chain means authentication information. You can also use other applications to try to access the same server, and vice versa.

 

 

 

The key chain for storing and retrieving creden requires two functions: one is used to find the credential dictionary for identity authentication and the other is used to save the most recent request of the credential. These functions are declared:

 

 

CFMutableDictionaryRef findCredentialsForAuthentication (

CFHTTPAuthenticationRef auth );

 

Void saveCredentialsForRequest (void );

 

 

 

The findCredentialsForAuthentication function first checks whether the credential dictionary is stored in the memory and whether the credential is locally cached. Listing 4-6 shows how to implement this.

 

 

 

If the credential is not cached in the memory, search for the key chain. SecKeychainFindInternetPassword: used to search for the key chain. This function requires a large number of parameters. Parameters, and a brief description of how they use HTTP Authentication creden,, including:

 

 

KeychainOrArray

NULL is used to specify the user's default key chain list.

 

 

 

ServerNameLength

The length of serverName, usually strlen (serverName ).

 

 

ServerName

Parses the server name from the HTTP request.

 

 

 

SecurityDomainLength

The length of the security domain, or 0 if there is no domain. In the sample code, realm? Strlen (realm): 0 is passed to the account in two cases.

 

 

 

SecurityDomain

The domain object of identity authentication, which is obtained from CFHTTPAuthenticationCopyRealm.

 

 

 

 

AccountNameLength

The length of the accountName. Since accountName is NULL, this value is 0.

 

 

AccountName

If no account name is available to obtain the key chain item, this should be NULL.

 

 

PathLength

Path length, or 0 if no path exists. In the sample code, path? Strlen (path): 0 is passed to the account in two cases ..

 

 

Path

Path of the authentication object, which is obtained from CFURLCopyPath.

 

 

Port

Port Number, obtained from the CFURLGetPortNumber function.

 

 

Protocol

A string represents the protocol type, such as HTTP or HTTPS. The obtained protocol type is by calling the CFURLCopyScheme function.

 

AuthenticationType

Authentication Type, obtained from the CFHTTPAuthenticationCopyMethod function.

 

 

PasswordLength

0. It is necessary to obtain the key chain item because there is no password.

 

 

PasswordData

NULL. It is necessary to obtain the key chain item because there is no password.

 

ItemRef

SecKeychainItemRef specifies the object to be referenced by the key chain entry. The correct key chain entry is found when the return result is returned.

 

 

 

 

 

 

 

 

 

 

 

 

The code shown in Listing 4 should be correct.

 

Listing 4-7 key chain search

 

 

DidFind =

SecKeychainFindInternetPassword (NULL,

Strlen (host), host,

Realm? Strlen (realm): 0, realm,

0, NULL,

Path? Strlen (path): 0, path,

Port,

ProtocolType,

AuthenticationType,

0, NULL,

& ItemRef );

 

 

Assuming that SecKeychainFindInternetPassword is returned successfully, the SecKeychainAttributeList contains a key chain attribute (SecKeychainAttribute ). The key chain property list contains the user name and password. Load the key chain attribute list, call the SecKeychainItemCopyContent function, and pass it to the key chain item reference object (itemRef), which is returned by SecKeychainFindInternetPassword. This function fills in the User Name of the key chain property account and uses a void ** as the password.

 

The username and password can be used to create a new group credential. Listing 4-8 shows the process.

 

Listing 4-8 loading server creden8 from the key chain

If (didFind = noErr ){

 

SecKeychainAttribute attr;

SecKeychainAttributeList attrList;

UInt32 length;

Void * outData;

 

// To set the account name attribute

Attr. tag = kSecAccountItemAttr;

Attr. length = 0;

Attr. data = NULL;

 

AttrList. count = 1;

AttrList. attr = & attr;

 

If (SecKeychainItemCopyContent (itemRef, NULL, & attrList, & length, & outData)

= NoErr ){

 

// Attr. data is the account (username) and outdata is the password

CFStringRef username =

CFStringCreateWithBytes (kCFAllocatorDefault, attr. data,

Attr. length, kCFStringEncodingUTF8, false );

CFStringRef password =

CFStringCreateWithBytes (kCFAllocatorDefault, outData, length,

KCFStringEncodingUTF8, false );

SecKeychainItemFreeContent (& attrList, outData );

 

// Create credentials dictionary and fill it with the user name & password

Credentials =

CFDictionaryCreateMutable (NULL, 0,

& KCFTypeDictionaryKeyCallBacks,

& KCFTypeDictionaryValueCallBacks );

CFDictionarySetValue (credentials, kCFHTTPAuthenticationUsername,

Username );

CFDictionarySetValue (credentials, kCFHTTPAuthenticationPassword,

Password );

 

CFRelease (username );

CFRelease (password );

}

CFRelease (itemRef );

}

 

 

 

 

Retrieving creden from a key chain is only useful. You can store the creden。 in the key chain first. Perform similar steps to load the certificate. First, check whether the credential is stored in the key chain. Contact SecKeychainFindInternetPassword, but the user name is the length of the account name and account name of accountnamelength.

 

 

If the entry exists, modify it to change the password. The data field attribute of the key chain is set to include the user name, so that you can modify the correct attribute. Then call the SecKeychainItemModifyContent function and reference the object (itemRef), key chain attribute list, and new password through the key chain item. By modifying key chain items rather than rewriting, entries on the key chain will be correctly updated and any related metadata will be retained. The entry should be similar to listing 4-9.

 

 

Listing 4-9 modifying the key chain entry

 

// Set the attribute to the account name

Attr. tag = kSecAccountItemAttr;

Attr. length = strlen (username );

Attr. data = (void *) username;

 

// Modify the keychain entry

SecKeychainItemModifyContent (itemRef, & attrList, strlen (password ),

(Void *) password );

 

 

 

 

If the entry does not exist, you need to create it from the beginning. The SecKeychainAddInternetPassword function completes this task. The SecKeychainFindInternetPassword parameter is the same, but you supply the SecKeychainAddInternetPassword user name and password compared to calling SecKeychainFindInternetPassword. The released key chain item reference object successfully calls SecKeychainAddInternetPassword unless you need to use something else. For details, see function call in steps 4 to 10.

 

 

 

 

 

 

 

 

Listing 4 to 10 stores a new key chain entry

 

SecKeychainAddInternetPassword (NULL,

Strlen (host), host,

Realm? Strlen (realm): 0, realm,

Strlen (username), username,

Path? Strlen (path): 0, path,

Port,

ProtocolType,

AuthenticationType,

Strlen (password), password,

& ItemRef );

 

 

 

Verify Firewall

 

The authentication firewall is very similar to the authentication server except that each failed HTTP request proxy authentication and server authentication must be checked. This means that you need a separate (local and persistent) proxy server and a source server. Therefore, the failed HTTP Response Process will:

 

Determine the response status code 407 (a proxy requirement ). If yes, find a matching verification object and credential by checking the local proxy store and persistent proxy store. If none of these match objects and creden。, then request the certificate from the user. Apply the authentication object to the HTTP request and try again.

 

 

Determine the response Status Code 401 (a server challenge ). If yes, follow the same process with a 407 response, but use the store of the original server.

 

 

There are also some minor differences when using the proxy server for execution. First, the parameters called by the key chain come from the proxy host and port, instead of the URL from the source server. The second is to require the user to enter the user name and password to ensure that the password is identified in a timely manner.

 

By following these instructions, your application should be able to process the authentication firewall.


 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.