📄 digestscheme.java
字号:
* @throws AuthenticationException if authorization string cannot * be generated due to an authentication failure * * @return a digest authorization string * * @since 3.0 */ public String authenticate(Credentials credentials, HttpMethod method) throws AuthenticationException { LOG.trace("enter DigestScheme.authenticate(Credentials, HttpMethod)"); UsernamePasswordCredentials usernamepassword = null; try { usernamepassword = (UsernamePasswordCredentials) credentials; } catch (ClassCastException e) { throw new InvalidCredentialsException( "Credentials cannot be used for digest authentication: " + credentials.getClass().getName()); } getParameters().put("methodname", method.getName()); StringBuffer buffer = new StringBuffer(method.getPath()); String query = method.getQueryString(); if (query != null) { if (query.indexOf("?") != 0) { buffer.append("?"); } buffer.append(method.getQueryString()); } getParameters().put("uri", buffer.toString()); String charset = getParameter("charset"); if (charset == null) { getParameters().put("charset", method.getParams().getCredentialCharset()); } String digest = createDigest( usernamepassword.getUserName(), usernamepassword.getPassword()); return "Digest " + createDigestHeader(usernamepassword.getUserName(), digest); } /** * Creates an MD5 response digest. * * @param uname Username * @param pwd Password * @param charset The credential charset * * @return The created digest as string. This will be the response tag's * value in the Authentication HTTP header. * @throws AuthenticationException when MD5 is an unsupported algorithm */ private String createDigest(final String uname, final String pwd) throws AuthenticationException { LOG.trace("enter DigestScheme.createDigest(String, String, Map)"); final String digAlg = "MD5"; // Collecting required tokens String uri = getParameter("uri"); String realm = getParameter("realm"); String nonce = getParameter("nonce"); String qop = getParameter("qop"); String method = getParameter("methodname"); String algorithm = getParameter("algorithm"); // If an algorithm is not specified, default to MD5. if (algorithm == null) { algorithm = "MD5"; } // If an charset is not specified, default to ISO-8859-1. String charset = getParameter("charset"); if (charset == null) { charset = "ISO-8859-1"; } if (qopVariant == QOP_AUTH_INT) { LOG.warn("qop=auth-int is not supported"); throw new AuthenticationException( "Unsupported qop in HTTP Digest authentication"); } MessageDigest md5Helper; try { md5Helper = MessageDigest.getInstance(digAlg); } catch (Exception e) { throw new AuthenticationException( "Unsupported algorithm in HTTP Digest authentication: " + digAlg); } // 3.2.2.2: Calculating digest StringBuffer tmp = new StringBuffer(uname.length() + realm.length() + pwd.length() + 2); tmp.append(uname); tmp.append(':'); tmp.append(realm); tmp.append(':'); tmp.append(pwd); // unq(username-value) ":" unq(realm-value) ":" passwd String a1 = tmp.toString(); //a1 is suitable for MD5 algorithm if(algorithm.equals("MD5-sess")) { // H( unq(username-value) ":" unq(realm-value) ":" passwd ) // ":" unq(nonce-value) // ":" unq(cnonce-value) String tmp2=encode(md5Helper.digest(EncodingUtil.getBytes(a1, charset))); StringBuffer tmp3 = new StringBuffer(tmp2.length() + nonce.length() + cnonce.length() + 2); tmp3.append(tmp2); tmp3.append(':'); tmp3.append(nonce); tmp3.append(':'); tmp3.append(cnonce); a1 = tmp3.toString(); } else if(!algorithm.equals("MD5")) { LOG.warn("Unhandled algorithm " + algorithm + " requested"); } String md5a1 = encode(md5Helper.digest(EncodingUtil.getBytes(a1, charset))); String a2 = null; if (qopVariant == QOP_AUTH_INT) { LOG.error("Unhandled qop auth-int"); //we do not have access to the entity-body or its hash //TODO: add Method ":" digest-uri-value ":" H(entity-body) } else { a2 = method + ":" + uri; } String md5a2 = encode(md5Helper.digest(EncodingUtil.getAsciiBytes(a2))); // 3.2.2.1 String serverDigestValue; if (qopVariant == QOP_MISSING) { LOG.debug("Using null qop method"); StringBuffer tmp2 = new StringBuffer(md5a1.length() + nonce.length() + md5a2.length()); tmp2.append(md5a1); tmp2.append(':'); tmp2.append(nonce); tmp2.append(':'); tmp2.append(md5a2); serverDigestValue = tmp2.toString(); } else { if (LOG.isDebugEnabled()) { LOG.debug("Using qop method " + qop); } String qopOption = getQopVariantString(); StringBuffer tmp2 = new StringBuffer(md5a1.length() + nonce.length() + NC.length() + cnonce.length() + qopOption.length() + md5a2.length() + 5); tmp2.append(md5a1); tmp2.append(':'); tmp2.append(nonce); tmp2.append(':'); tmp2.append(NC); tmp2.append(':'); tmp2.append(cnonce); tmp2.append(':'); tmp2.append(qopOption); tmp2.append(':'); tmp2.append(md5a2); serverDigestValue = tmp2.toString(); } String serverDigest = encode(md5Helper.digest(EncodingUtil.getAsciiBytes(serverDigestValue))); return serverDigest; } /** * Creates digest-response header as defined in RFC2617. * * @param uname Username * @param digest The response tag's value as String. * * @return The digest-response as String. */ private String createDigestHeader(final String uname, final String digest) throws AuthenticationException { LOG.trace("enter DigestScheme.createDigestHeader(String, Map, " + "String)"); String uri = getParameter("uri"); String realm = getParameter("realm"); String nonce = getParameter("nonce"); String opaque = getParameter("opaque"); String response = digest; String algorithm = getParameter("algorithm"); List params = new ArrayList(20); params.add(new NameValuePair("username", uname)); params.add(new NameValuePair("realm", realm)); params.add(new NameValuePair("nonce", nonce)); params.add(new NameValuePair("uri", uri)); params.add(new NameValuePair("response", response)); if (qopVariant != QOP_MISSING) { params.add(new NameValuePair("qop", getQopVariantString())); params.add(new NameValuePair("nc", NC)); params.add(new NameValuePair("cnonce", this.cnonce)); } if (algorithm != null) { params.add(new NameValuePair("algorithm", algorithm)); } if (opaque != null) { params.add(new NameValuePair("opaque", opaque)); } StringBuffer buffer = new StringBuffer(); for (int i = 0; i < params.size(); i++) { NameValuePair param = (NameValuePair) params.get(i); if (i > 0) { buffer.append(", "); } boolean noQuotes = "nc".equals(param.getName()) || "qop".equals(param.getName()); this.formatter.setAlwaysUseQuotes(!noQuotes); this.formatter.format(buffer, param); } return buffer.toString(); } private String getQopVariantString() { String qopOption; if (qopVariant == QOP_AUTH_INT) { qopOption = "auth-int"; } else { qopOption = "auth"; } return qopOption; } /** * Encodes the 128 bit (16 bytes) MD5 digest into a 32 characters long * <CODE>String</CODE> according to RFC 2617. * * @param binaryData array containing the digest * @return encoded MD5, or <CODE>null</CODE> if encoding failed */ private static String encode(byte[] binaryData) { LOG.trace("enter DigestScheme.encode(byte[])"); if (binaryData.length != 16) { return null; } char[] buffer = new char[32]; for (int i = 0; i < 16; i++) { int low = (int) (binaryData[i] & 0x0f); int high = (int) ((binaryData[i] & 0xf0) >> 4); buffer[i * 2] = HEXADECIMAL[high]; buffer[(i * 2) + 1] = HEXADECIMAL[low]; } return new String(buffer); } /** * Creates a random cnonce value based on the current time. * * @return The cnonce value as String. * @throws HttpClientError if MD5 algorithm is not supported. */ public static String createCnonce() { LOG.trace("enter DigestScheme.createCnonce()"); String cnonce; final String digAlg = "MD5"; MessageDigest md5Helper; try { md5Helper = MessageDigest.getInstance(digAlg); } catch (NoSuchAlgorithmException e) { throw new HttpClientError( "Unsupported algorithm in HTTP Digest authentication: " + digAlg); } cnonce = Long.toString(System.currentTimeMillis()); cnonce = encode(md5Helper.digest(EncodingUtil.getAsciiBytes(cnonce))); return cnonce; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -