📄 authsubutil.java
字号:
/* Copyright (c) 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.google.gdata.client.http;import com.google.gdata.util.common.base.StringUtil;import com.google.gdata.util.common.util.Base64;import com.google.gdata.util.AuthenticationException;import java.io.FileInputStream;import java.io.IOException;import java.io.UnsupportedEncodingException;import java.net.HttpURLConnection;import java.net.URL;import java.net.URLEncoder;import java.security.GeneralSecurityException;import java.security.KeyStore;import java.security.PrivateKey;import java.security.SecureRandom;import java.security.Signature;import java.util.Map;/** * Utility functions to support AuthSub (Account Authentication for Web * Applications). * * */public class AuthSubUtil { // The default protocol to use for AuthSub communication private static final String DEFAULT_PROTOCOL = "https"; // The default domain to use for AuthSub communication private static final String DEFAULT_DOMAIN = "www.google.com"; // Secure random number generator to sign requests private static final SecureRandom RANDOM = new SecureRandom(); /** * Signature algorithms supported by AuthSub to sign the requests. */ private enum SignatureAlgorithm { DSA_SHA1("dsa-sha1", "SHA1withDSA"), RSA_SHA1("rsa-sha1", "SHA1withRSA"); SignatureAlgorithm(String authSubName, String jcaName) { this.authSubName = authSubName; this.jcaName = jcaName; } public String toString() { return jcaName; } public String getAuthSubName() { return authSubName; } public String getJCAName() { return jcaName; } private final String authSubName; private final String jcaName; } /** * Creates the request URL to be used to retrieve an AuthSub token. * <p> * On success, the user will be redirected to the next URL with the * AuthSub token appended to the URL. Use {@link #getTokenFromReply(String)} * to retrieve the token from the reply. * * @param nextUrl the URL to redirect to on successful token retrieval * @param scope the scope of the requested AuthSub token * @param secure <code>true</code> if the token will be used securely * @param session <code>true</code> if the token will be exchanged for a * session cookie * @return the URL to be used to retrieve the AuthSub token */ public static String getRequestUrl(String nextUrl, String scope, boolean secure, boolean session) { return getRequestUrl(DEFAULT_PROTOCOL, DEFAULT_DOMAIN, nextUrl, scope, secure, session); } /** * Creates the request URL to be used to retrieve an AuthSub token. * <p> * On success, the user will be redirected to the next URL with the * AuthSub token appended to the URL. Use {@link #getTokenFromReply(String)} * to retrieve the token from the reply. * * @param protocol the protocol to use to communicate with the server * @param domain the domain at which the authentication server exists * @param nextUrl the URL to redirect to on successful token retrieval * @param scope the scope of the requested AuthSub token * @param secure <code>true</code> if the token will be used securely * @param session <code>true</code> if the token will be exchanged for a * session cookie * @return the URL to be used to retrieve the AuthSub token */ public static String getRequestUrl(String protocol, String domain, String nextUrl, String scope, boolean secure, boolean session) { StringBuffer url = new StringBuffer(protocol).append("://"); url.append(domain).append("/accounts/AuthSubRequest"); addParameter(url, "next", nextUrl); addParameter(url, "scope", scope); addParameter(url, "secure", secure ? "1" : "0"); addParameter(url, "session", session ? "1" : "0"); return url.toString(); } /** * Parses and returns the AuthSub token returned by Google on a successful * AuthSub login request. The token will be appended as a query parameter * to the next URL specified while making the AuthSub request. * * @param url the redirected-to next URL with the token * @return the AuthSub token returned by Google */ public static String getTokenFromReply(URL url) { return getTokenFromReply(url.getQuery()); } /** * Parses and returns the AuthSub token returned by Google on a successful * AuthSub login request. The token will be appended as a query parameter * to the next URL specified while making the AuthSub request. * * @param queryString the query portion of the redirected-to URL containing * the token * @return the AuthSub token returned by Google */ public static String getTokenFromReply(String queryString) { // Parse the query parameters Map<String, String> params = StringUtil.string2Map(queryString, "&", "=", true /*stripEntry*/); params = StringUtil.lowercaseKeys(params); return params.get("token"); } /** * Retrieves the private key from the specified keystore. * * @param keystore the path to the keystore file * @param keystorePass the password that protects the keystore file * @param keyAlias the alias under which the private key is stored * @param keyPass the password protecting the private key * @return the private key from the specified keystore * @throws GeneralSecurityException if the keystore cannot be loaded * @throws IOException if the file cannot be accessed */ public static PrivateKey getPrivateKeyFromKeystore(String keystore, String keystorePass, String keyAlias, String keyPass) throws IOException, GeneralSecurityException { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStream keyStream = null; try { keyStream = new FileInputStream(keystore); keyStore.load(keyStream, keystorePass.toCharArray()); return (PrivateKey) keyStore.getKey(keyAlias, keyPass.toCharArray()); } finally { if (keyStream != null) { keyStream.close(); } } } /** * Exchanges the one time use token returned in the URL for a session * token. * <p> * If the <code>key</code> is non-null, the token will be used securely * and the request to make the exchange will be signed. * * @param onetimeUseToken the one time use token sent by Google in the URL * @param key the private key to sign the request * @return the session token. <code>null</code> if the request failed * @throws IOException if error in writing/reading the request * @throws GeneralSecurityException if error in signing the request * @throws AuthenticationException if one time use token is rejected */ public static String exchangeForSessionToken(String onetimeUseToken, PrivateKey key) throws IOException, GeneralSecurityException, AuthenticationException { return exchangeForSessionToken(DEFAULT_PROTOCOL, DEFAULT_DOMAIN, onetimeUseToken, key); } /** * Exchanges the one time use token returned in the URL for a session * token. * <p> * If the <code>key</code> is non-null, the token will be used securely * and the request to make the exchange 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 onetimeUseToken the one time use token sent by Google in the URL * @param key the private key to sign the request * @return the session token. <code>null</code> if the request failed * @throws IOException if error in writing/reading the request * @throws GeneralSecurityException if error in signing the request * @throws AuthenticationException if one time use token is rejected */ public static String exchangeForSessionToken(String protocol, String domain, String onetimeUseToken, PrivateKey key) throws IOException, GeneralSecurityException, AuthenticationException { String sessionUrl = getSessionTokenUrl(protocol, domain); URL url = new URL(sessionUrl); HttpURLConnection httpConn = (HttpURLConnection) url.openConnection(); String header = formAuthorizationHeader(onetimeUseToken, key, url, "GET"); httpConn.setRequestProperty("Authorization", header); if (httpConn.getResponseCode() != HttpURLConnection.HTTP_OK) { throw new AuthenticationException(httpConn.getResponseCode() + ": " + httpConn.getResponseMessage()); } // Parse the response String body = StringUtil.stream2String(httpConn.getInputStream(), -1); Map<String, String> parsedTokens = StringUtil.string2Map(body, "\n", "=", true /*stripEntry*/); parsedTokens = StringUtil.lowercaseKeys(parsedTokens); return parsedTokens.get("token"); } /** * 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 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -