I. Preface
HTTP authentication is a way for Web servers to authenticate client permissions, which can provide a certain degree of security protection for Web applications. At present, some Web application projects have put forward the need to adopt HTTP authentication. Although Web containers generally provide basic and abstract authentication APIs, the APIS provided by different Web containers are also different, therefore, we provide a set of APIs in the ZX Web platform toolkit. With this set of APIS, developers can use a unified interface in their applications to easily implement HTTP authentication, instead of relying on Web containers.
Ii. HTTP Authentication Mechanism
HTTP Authentication adopts the "Question-response (challenge-response)" mechanism. "Question" refers to the question from the server to the client, that is, the client is required to send authentication information; "response" refers to the client's response to the "Question", that is, an HTTP request with authentication information is sent.
Generally, when the client requests a URI for the first time, it does not know whether authentication is required. Therefore, authentication information is always not required. In this case, the server cannot find the authentication information and authentication fails, then, a "Question" is sent to the client ".
The so-called "issue a question" is to send an HTTP Response to the client, whose status code is 401 (Unauthorized) and contains the message header WWW-Authenticate, when the client sees this response, it will know that the URI needs authentication. The format of the WWW-Authenticate message header is
WWW-Authenticate: challenge
<Challenge> indicates the question information, which is defined in RFC2617:
Challenge = auth-scheme 1 * SP 1 # auth-param
Auth-scheme = token
Auth-param = token "=" (token | quoted-string)
In the definition of challenge, auth-scheme is the authentication scheme, which is defined as a token, that is, a predefined symbol. The so-called token is some strings, but these strings are not random, but agreed by everyone, they have specific meanings. The value of auth-scheme can only be Basic or Digest, indicating Basic authentication and Digest authentication respectively. The two words are tokens. Auth-scheme is not defined as Basic | Digest, but a token, which indicates that it can be extended and other symbols can be used-as long as the server and client can understand each other.
Then, "1 * SP" indicates one or more space characters. "1 *" indicates one to multiple characters, and "SP" indicates a space character (ASCII code 32 ).
Then "1 # auth-param" represents a list of auth-param. "1 #" also indicates that the following elements are 1 to multiple, but unlike "1 *", "1 #" indicates a "list ", that is, the elements are separated by commas. Each auth-param in the list is defined as a value pair, that is
Symbol = symbol
Or
Symbol = "string in quotation marks"
These two forms.
Both Basic Authentication and digest authentication define the same auth-param, namely, realm, as follows:
Realm = "realm" "=" realm-value
Realm-value = quoted-string
Realm-value is a case-sensitive string with quotation marks on both ends, indicating the "realm (realm)" that requires authentication )". The field is determined by the server itself. Different servers can set their own fields. The same server can also have multiple fields. In RFC2617, we recommend that the domain contain at least the Host Name and user groups with permissions, such as registered_users@www.news.com, to allow the client to know which range of user names are valid ".
After receiving the question, the client should return a "response" to the server, that is, re-send a new HTTP request. The difference between this new HTTP request and the previous HTTP request is that an Authorization message header is added, and the format of the message header is Authorization: credentials. The credentials is the authentication information, the format of authentication information varies according to different authentication schemes.
The server determines the authentication information. Only when the authentication succeeds will the server respond to the client's request.
1. Basic Authentication
Only one auth-param (realm) is defined in the basic authentication question. Therefore, the Basic Authentication question is also defined
Challenge = "Basic" realm
Question example:
When the server fails authentication, a response message with the status code 401 (Unautherized) is returned with the following message header:
WWW-Authenticate: Basic realm = "My Secret World"
The credentials of basic authentication is defined:
Credentials = "Basic" basic-credentials
Basic-credentials = base-user-pass
Base-user-pass = <base encoding of user-pass,
Limit t not limited to 76 char/line>
User-pass = userid ":" password
Userid = *
Password = * TEXT
Simply put, the authentication information is the Base encoding followed by "<user name >:< password>, however, the Base encoding here does not limit the maximum number of characters in each line to 76.
Example of authentication information:
If the user name is "abc" and the password is "abcd", perform Base encoding on "abc: abcd" to get "YWJjOmFiY2Q =". Therefore, the authentication information in the message header is
Authorization: Basic YWJjOmFiY2Q =
2. Digest Authentication
Abstract authentication is developed as an alternative because basic authentication is considered insecure. In digest authentication, the user name and password are not transmitted in plain text, but encrypted. The name indicates that an information digest is generated. The client and server generate an information digest using the same password as the server. You can compare the two to determine whether the client password is correct.
The Digest Authentication still uses the WWW-Authenticate and Authorization message headers, and also specifies the message header Authentication-Info. The message header Authentication-Info is used to return some information to the client after the Authentication is passed. For example, it can be used to specify the temporary value for the next Authentication or generate a summary, indicates that the server knows the user password, and so on. However, this message header is not required and is generally not used in actual applications. Therefore, it is not implemented on the Web platform. We will not introduce it here. If you are interested, please refer to RFC2617.
Iii. HTTP authentication security
1. Security of Basic Authentication
Basic authentication is not a secure authentication method, because Base encoding is only code, rather than encryption. The danger of passing user names and passwords on the internet is obvious. However, if the security requirements are not high, you can use this authentication method as the simplest security measure-after all, it is better than no security measure.
Of course, if we can ensure that no data packet is intercepted in the middle, such as in an internal LAN, or the underlying protocol is secure (such as using SSL or some other security mechanisms ), it can make up for the security deficiency of basic HTTP authentication.
2. Security of digest Authentication
Abstract authentication is an alternative because basic authentication is too dangerous. However, it is only a substitute for basic authentication, because it is not very safe and has some weaknesses.
(1) digest authentication can only be used as a permission authentication mechanism, rather than a confidentiality measure, because the message body is not encrypted. Qop uses "auth-int" to ensure that the message body is not modified and cannot be peeked.
(2) Replay attack: attackers may intercept abstract information and then use the same summary information to request the same URI. If the URI can be accessed through the POST or PUT method, attackers may modify the message body. Controlling the timestamp and nc count in nonce helps reduce the chance of a replay attack. Using a new nonce value (with the Authentication-Info message header) can avoid the replay attack and increase the overhead.
(3) MITM (Man in the Middle) Attack: attackers intercept network packets and send a false question to the client. Only the client needs to use basic authentication to obtain the password. The most common method for MITM is to provide a "free" but actually a malicious proxy server. To prevent such attacks, both parties agree to only use digest authentication, and basic authentication is not allowed. However, generally, browsers do not support specifying authentication methods unless they are self-developed clients.
There are also some other attack methods, such as searching the dictionary and guessing the password. Although digest certification has these weaknesses, it is still useful in many cases, at least much better than basic certification.
IV. Implementation of HTTP authentication on ZX Web platform
HTTP Authentication APIs are provided in the ZX Web platform package. These APIs include an API HttpAuth and two implementation classes HttpBasicAuth and HttpDigestAuth, which implement basic authentication and digest authentication respectively. Developers can use interfaces or directly use two implementation classes. Class 1.
1. HttpAuth Interface
This interface should provide a method to obtain the user name and password submitted by the user, so that the application can verify its correctness. This can be done in basic authentication, but in Digest authentication, the server does not know the password submitted by the client, all we can get is to perform MD5 encoding on the data containing the password to get a digest. Therefore, in order to take care of digest authentication, the HttpAuth interface does not design such a method, but provides another method, authenticate, the caller passes in the username and correct password as parameters of this method and returns the authentication result. This method also requires another parameter, that is, an instance of the HTTP request HttpServletRequest, because the authentication information submitted by the user needs to be obtained from it. This parameter is required for all methods of the HttpAuth interface.
In most cases, there are more than one legal user, so you must know the user name submitted by the client before calling the authenticate Method. The getUserName method of the HttpAuth interface completes this function. The two methods are described as follows:
GetUserName
Function:
Obtain the user name in the authentication information sent from the user.
Prototype:
Public String getUserName (HttpServletRequest req)
Parameters:
Req-HTTP request
Return Value:
Returns the username in the authentication information. If no authentication information is obtained (the request does not contain the authentication information or the authentication information format is incorrect), null is returned.
Authenticate
Function:
Determine whether the user name and password in the authentication information of an HTTP request are consistent with the specified one.
Prototype:
Public boolean authenticate (HttpServletRequest req,
String userName,
String password)
Parameters:
Req-HTTP request
UserName-the specified user name
Password-the specified password
Return Value:
True-Authentication passed
False-authentication failed
When the authenticate method is called and the authentication fails, you should send a question to the client, that is, set the response status code to 401 and set the message header www-authenticate. The setunauth method of the httpauth interface is responsible for completing this function.
Setunauth
Function:
Set the status code 401 unauthorized and add the WWW-authenticate message header.
Prototype:
Public void setunauth (httpservletrequest req,
Httpservletresponse RSP,
String realm)
Parameters:
Req-HTTP request
Rsp-HTTP Response
The value of realm in the realm-WWW-Authenticate message header. If it is null, servername: port is used by default.
Return: None
The setUnauth method sets the status code of the HTTP Response object rsp to 401, and adds the WWW-Authenticate message header. As for the content of the message header, the HttpBasicAuth and HttpDigestAuth classes are implemented differently based on the Basic Authentication and digest authentication specifications. The realm value is required to set the WWW-Authenticate message header. The caller uses the realm parameter to specify the realm value. If you do not want to specify the realm value, you can set the realm parameter to null or directly call the setUnauth method in the form of another parameter:
Public void setUnauth (HttpServletRequest req, HttpServletResponse rsp)
If the realm value is not specified, the setUnauth method retrieves the server name and port from the request object req and combines them by servername: port to use this value as the realm value.
Finally, the HttpAuth interface provides the getAuth method to obtain the authentication information submitted by the user in the HTTP request, that is, the information after the "Basic" or "Digest" mark in the Authorization message header; if it is Basic authentication, if the string is BASE encoded, the decoded string is returned. This method is not required for developers, but can be used for debugging.
GetAuth
Function:
Obtain the authentication information submitted by the user.
Prototype:
Public String getAuth (HttpServletRequest req)
Parameters:
Req-HTTP request
Return Value:
The "Digest" or "Basic" information in the Digest authentication information submitted by the user. If it is BASE encoding, the decoded string is returned.
2. HttpBasicAuth class
The HttpBasicAuth class implements basic HTTP authentication.
In addition to all methods used to implement the HttpAuth interface, HttpBasicAuth also adds the getUserNamePwd method to obtain the user name and password submitted by the client. In some cases, the server database or file does not save the plaintext of the user password, but saves the password through some irreversible encryption algorithm (MD5 or other) and the obtained information abstract (such as UNIX system ). In this case, the server cannot call the authenticate Method for authentication. You can only call the getUserNamePwd method to obtain the username and password in the HTTP request, and then calculate the abstract according to the same encryption algorithm in the database or file, check whether the obtained summary is the same as that in the database or file. In this case, you cannot use digest authentication, but you can only use basic authentication.
GetUserNamePwd
Function:
Obtains an array of username and password strings.
Prototype:
Public String [] getUserNamePwd (HttpServletRequest req)
Parameters:
Req-HTTP request
Return Value:
String Array. The first element is the user name, and the second element is the password. If the user name and password are not obtained, null is returned.
HttpBasicAuth only has one member variable:
Protected static BASEDecoder baseDecoder = new BASEDecoder ();
That is, an instance of the sun. misc. BASEDecoder class for BASE decoding.
3. HttpDigestAuth class
The HttpDigestAuth class implements HTTP digest authentication. In addition to implementing the HttpAuth interface, the HttpDigestAuth class also provides other methods based on the digest authentication features.
There is an nc value in the authentication information submitted by the client, which indicates the number of times the temporary value nonce has been used. The value can be obtained by the HttpDigestAuth class method getNonceCount.
GetNonceCount
Function:
Obtain the nc (NonceCount) value in the authentication information sent by the user.
Prototype:
Public int getNonceCount (HttpServletRequest req)
Parameters:
Req-HTTP request
Return Value:
Returns the nc value. If no value is obtained, 0 is returned.
For this nc value, the server can choose not to limit or limit a maximum value based on its own policies. If the abstract is correct but the nonce usage exceeds the upper limit, you can return an "expired" question response to the client. The WWW-Authorize message header contains a new nonce value, set the stale field to true, so that the client uses the new nonce value to recalculate the summary. In this case, the client will not re-pop up the dialog box asking the user to enter the password. Instead, it will re-calculate the digest with the original password and the new nonce value, and then re-send the request. This process is transparent to client users. HttpDigestAuth provides a parameter-based setUnauth method to return an "expired" question to the client.
SetUnauth
Function:
Set the status code 401 Unauthorized and add the WWW-Authenticate message header.
Prototype:
Public void setUnauth (HttpServletRequest req,
HttpServletResponse rsp,
String realm,
Boolean stale)
Parameters:
Req-HTTP request
Rsp-HTTP Response
Realm-specifies the value of the realm field. If it is null, the default value servername: port is used.
Stale-specifies the value of the stale field. true indicates that the client abstract is correct, but the nonce value expires, causing authentication failure. false indicates that authentication fails not because the nonce value expires.
Return Value:
None
Call this method and set the stale parameter to true, that is, to issue an "expired" question to the client. There are several other setUnau methods in HttpDigestAuth. If stale is not specified, the default value is false.
Either way, the setUnauth method must generate a new nonce value each time. The RFC2617 Algorithm for generating nonce is not specified. The HttpDigestAuth class generates nonce in the generateNonce method. The algorithm is
NOnce = BCD (MD5 (<client-IP >:< time-stamp >:< private-key> ))
That is, connect the Client IP address, current time (in milliseconds), and a private key with a colon to obtain its MD5 Digest, then convert the byte array to a hexadecimal string (BCD code ).
V. Application Examples
Here is an example to illustrate how to use the APIS provided by the Web platform to implement HTTP authentication.
Create a new JSP file AuthTest. jsp. The source code is as follows (you can copy a column on the right of the table to a text file and save it as AuthTest. jsp ). Deploy the file to an application server (such as Tomcat). After starting the server, use IE to request the JSP. Then, the browser dialog box prompts you to enter the user name and password.
During verification, you can try to enter the correct or wrong user name and password in IE, and select "cancel" in the dialog box to see how it works. Note: If you enter the correct user name and password, after the authentication is passed, the IE dialog box will not pop up, unless you restart an IE window or modify the user name and password string in the JSP file, resulting in authentication failure.
Line 3 generates an instance of the HttpAuth interface, that is, an HttpBasicAuth object, to test basic authentication. Obtain the username in row 12th, and then determine whether the username is "abc". If not, set the unauthenticated response in row 15th and specify the realm value as "BasicAuthUser ", the string is displayed in the dialog box of the client. If the user name is correct, line 3 calls the authenticate Method to Determine whether the user name/password is "abc"/"abcd". If not, set the unauthenticated response in line 3, this time, specify the realm as "BasicAuthPwd" (here two different realm values are specified only for verification, which should be the same in actual applications ). If the authentication succeeds, a string is output from row 3 on the page to indicate that the authentication is successful. In either case, the client returns the authentication information submitted by the client in line 3.
From row 25th to row 49th is the test of HTTP digest authentication, which is commented out here. It can be restored during verification, and the part for testing basic authentication from line 11th to line 23 is commented out. Similar to basic authentication, the first step is to generate an HttpAuth interface instance, but this time it is an HttpDigestAuth object, and then determine whether the user name and password are correct. If both are correct, retrieve the nc value in row 38th and determine if it exceeds the upper limit of 10. If it exceeds the upper limit, set the non-pass (nonce expired) response in row 45th.
VII. Summary
This article introduces the concepts and specifications of HTTP authentication and the APIS provided by ZX Web platform. RFC2617 also involves some HTTP Authentication specifications when using proxy servers, which will not be described here.
Although HTTP authentication is not a secure authentication method, HTTP authentication is still a simple and easy-to-use security measure and is used in many places. In project development, when determining whether to adopt HTTP authentication, you must consider the security of the solution and the security requirements of the project. In addition, you must consider the support of browsers for HTTP authentication. When RFC2617 is released, General browsers support basic authentication, while only Microsoft's IE supports digest authentication.