📄 authsubutil.java
字号:
* attribute to the value of the attribute. */ public static Map<String, String> getTokenInfo(String token, PrivateKey key) throws IOException, GeneralSecurityException, AuthenticationException { return getTokenInfo(DEFAULT_PROTOCOL, DEFAULT_DOMAIN, token, key); } /** * Retrieves information about the AuthSub token. * <p> * If the <code>key</code> is non-null, the token will be used securely * and the request to revoke the token will be signed. * * @param protocol the protocol to use to communicate with the server * @param domain the domain at which the authentication server exists * @param token the AuthSub token for which to receive information * @param key the private key to sign the request * @throws IOException if error in writing/reading the request * @throws GeneralSecurityException if error in signing the request * @throws AuthenticationException if the token is rejected * @return the token information in the form of a Map from the name of the * attribute to the value of the attribute. */ public static Map<String, String> getTokenInfo(String protocol, String domain, String token, PrivateKey key) throws IOException, GeneralSecurityException, AuthenticationException { String tokenInfoUrl = getTokenInfoUrl(protocol, domain); URL url = new URL(tokenInfoUrl); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); String header = formAuthorizationHeader(token, key, url, "GET"); httpConn.setRequestProperty("Authorization", header); if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new AuthenticationException(httpConn.getResponseCode() + ": " + httpConn.getResponseMessage()); } String body = StringUtil.stream2String(httpConn.getInputStream(), -1); return StringUtil.string2Map(body.trim(), "\n", "=", true); } /** * Revokes the specified token. * <p> * If the <code>key</code> is non-null, the token will be used securely * and the request to revoke the token will be signed. * * @param token the AuthSub token to revoke * @param key the private key to sign the request * @throws IOException if error in writing/reading the request * @throws GeneralSecurityException if error in signing the request * @throws AuthenticationException if the token is rejected */ public static void revokeToken(String token, PrivateKey key) throws IOException, GeneralSecurityException, AuthenticationException { revokeToken(DEFAULT_PROTOCOL, DEFAULT_DOMAIN, token, key); } /** * Revokes the specified token. * <p> * If the <code>key</code> is non-null, the token will be used securely * and the request to revoke the token will be signed. * * @param protocol the protocol to use to communicate with the server * @param domain the domain at which the authentication server exists * @param token the AuthSub token to revoke * @param key the private key to sign the request * @throws IOException if error in writing/reading the request * @throws GeneralSecurityException if error in signing the request * @throws AuthenticationException if the token is rejected */ public static void revokeToken(String protocol, String domain, String token, PrivateKey key) throws IOException, GeneralSecurityException, AuthenticationException { String revokeUrl = getRevokeTokenUrl(protocol, domain); URL url = new URL(revokeUrl); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); String header = formAuthorizationHeader(token, key, url, "GET"); httpConn.setRequestProperty("Authorization", header); if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new AuthenticationException(httpConn.getResponseCode() + ": " + httpConn.getResponseMessage()); } } /** * Forms the AuthSub authorization header. * <p> * If the <code>key</code> is null, the token will be used in insecure mode. * If the <code>key</code> is non-null, the token will be used securely and * the header will contain a signature. * * @param token the AuthSub token to use in the header * @param key the private key used to sign the request * @param requestUrl the URL of the request being issued * @param requestMethod the HTTP method being used to issue the request * @return the authorization header * @throws GeneralSecurityException if error occurs while creating signature */ public static String formAuthorizationHeader(String token, PrivateKey key, URL requestUrl, String requestMethod) throws GeneralSecurityException { if (key == null) { return String.format("AuthSub token=\"%s\"", token); } else { // Form signature for secure mode long timestamp = System.currentTimeMillis() / 1000; long nonce = RANDOM.nextLong(); String dataToSign = String.format("%s %s %d %s", requestMethod, requestUrl.toExternalForm(), timestamp, unsignedLongToString(nonce)); SignatureAlgorithm sigAlg = getSigAlg(key); byte[] signature = sign(key, dataToSign, sigAlg); String encodedSignature = Base64.encode(signature); return String.format("AuthSub token=\"%s\" data=\"%s\" sig=\"%s\" " + "sigalg=\"%s\"", token, dataToSign, encodedSignature, sigAlg.getAuthSubName()); } } /** * Adds the query parameter with the given name and value to the URL. */ private static void addParameter(StringBuffer url, String name, String value) { try { name = URLEncoder.encode(name, "UTF-8"); value = URLEncoder.encode(value, "UTF-8"); } catch (UnsupportedEncodingException uee) { throw new IllegalStateException("Unable to encode parameters", uee); } // Make sure the url currently ends with the correct delimiter if (url.indexOf("?") == -1) { url.append('?'); } else { switch (url.charAt(url.length() - 1)) { case '?': case '&': break; default: url.append('&'); } } // Append the name/value pair url.append(name).append('=').append(value); } /** * Signs the data with the given key and the provided algorithm. */ private static byte[] sign(PrivateKey key, String data, SignatureAlgorithm algorithm) throws GeneralSecurityException { Signature signature = Signature.getInstance(algorithm.getJCAName()); signature.initSign(key); signature.update(data.getBytes()); return signature.sign(); } /** * Returns the signature algorithm to be used for the provided private key. */ private static SignatureAlgorithm getSigAlg(PrivateKey key) { String algorithm = key.getAlgorithm(); if ("dsa".equalsIgnoreCase(algorithm)) { return SignatureAlgorithm.DSA_SHA1; } else if ("rsa".equalsIgnoreCase(algorithm)) { return SignatureAlgorithm.RSA_SHA1; } else { throw new IllegalArgumentException("Unknown algorithm in private key."); } } /** * Returns the URL to use to exchange the one-time-use token for * a session token. * * @param protocol the protocol to use to communicate with the server * @param domain the domain at which the authentication server exists * @return the URL to exchange for the session token */ private static String getSessionTokenUrl(String protocol, String domain) { return protocol + "://" + domain + "/accounts/AuthSubSessionToken"; } /** * Returns the URL that handles token revocation. * * @param protocol the protocol to use to communicate with the server * @param domain the domain at which the authentication server exists * @return the URL that handles token revocation. */ private static String getRevokeTokenUrl(String protocol, String domain) { return protocol + "://" + domain + "/accounts/AuthSubRevokeToken"; } /** * Returns the URL that handles token revocation. * * @param protocol the protocol to use to communicate with the server * @param domain the domain at which the authentication server exists * @return the URL that handles token revocation. */ private static String getTokenInfoUrl(String protocol, String domain) { return protocol + "://" + domain + "/accounts/AuthSubTokenInfo"; } /** * Treats the provided long as unsigned and converts it to a string. */ private static String unsignedLongToString(long value) { if (value >= 0) { return Long.toString(value); } else { // Split into two unsigned halves. As digits are printed out from // the bottom half, move data from the top half into the bottom // half int max_dig = 20; char[] cbuf = new char[max_dig]; int radix = 10; int dst = max_dig; long top = value >>> 32; long bot = value & 0xffffffffl; bot += (top % radix) << 32; top /= radix; while (bot > 0 || top > 0) { cbuf[--dst] = Character.forDigit((int)(bot % radix), radix); bot = (bot / radix) + ((top % radix) << 32); top /= radix; } return new String(cbuf, dst, max_dig-dst); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -