001: /**********************************************************************************
002: *
003: * Copyright (c) 2003, 2004 The Regents of the University of Michigan, Trustees of Indiana University,
004: * Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation
005: *
006: * Licensed under the Educational Community License Version 1.0 (the "License");
007: * By obtaining, using and/or copying this Original Work, you agree that you have read,
008: * understand, and will comply with the terms and conditions of the Educational Community License.
009: * You may obtain a copy of the License at:
010: *
011: * http://cvs.sakaiproject.org/licenses/license_1_0.html
012: *
013: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
014: * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
015: * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
016: * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
017: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
018: *
019: **********************************************************************************/package edu.indiana.lib.twinpeaks.net;
020:
021: import edu.indiana.lib.twinpeaks.util.*;
022:
023: import java.io.*;
024: import java.net.*;
025: import java.util.*;
026:
027: /**
028: * Handle network authentication.
029: *<p>
030: * When we try to access a protected site,
031: * <code>getPasswordAuthentication()</code> is called by the network
032: * connection code (<code>HttpURLConnection</code> in our case) to obtain
033: * any credentials (username and password) required to access the site.
034: *<p>
035: * Note:
036: * This only occurs until we successfully "log in" - after that, we are
037: * not invoked again for the site in question.
038: */
039: public class HttpAuthenticator extends java.net.Authenticator {
040:
041: private static org.apache.commons.logging.Log _log = LogUtils
042: .getLog(HttpAuthenticator.class);
043:
044: private HashMap credentialMap = new HashMap();
045:
046: /**
047: * Establish realm login credentials
048: * @param realm Realm for authentication (<code>ADS</code>)
049: * @param username User for login
050: * @param password Password
051: */
052: public synchronized void setCredentials(String realm,
053: String username, String password) {
054: credentialMap.put(realm, new Credentials(username, password));
055: }
056:
057: /**
058: * Override the default implementation to provide the credentials required
059: * for our network authentication
060: */
061: protected synchronized PasswordAuthentication getPasswordAuthentication() {
062: Credentials credential;
063: int attempts;
064:
065: _log.debug("Authorization requested for \""
066: + getRequestingPrompt() + "\", scheme: \""
067: + getRequestingScheme() + "\", site: \""
068: + getRequestingSite() + "\"");
069:
070: credential = (Credentials) credentialMap
071: .get(getRequestingPrompt());
072: if (credential == null) {
073: _log.warn("No credentials configured");
074: return null;
075: }
076:
077: /*
078: * If the login has been rejected once, quit now. This avoids a
079: * "redirect loop" with the server. Reset the counter every few
080: * attempts to allow an an occasional authorization "retry".
081: */
082: attempts = credential.getAuthorizationAttempts() + 1;
083: credential.setAuthorizationAttempts(attempts);
084:
085: if (attempts > 1) {
086: if ((attempts % 3) == 0) {
087: credential.setAuthorizationAttempts(0);
088: }
089: _log.warn("Authorization refused");
090: return null;
091: }
092: _log.warn("Returning credentials for authorization");
093: return new PasswordAuthentication(credential.getUsername(),
094: credential.getPassword());
095: }
096:
097: /**
098: * Store authentication information
099: */
100: private static class Credentials {
101: private String username;
102: private char[] password;
103: private int attempts;
104:
105: private Credentials() {
106: }
107:
108: /**
109: * Constructor
110: * @param username This user
111: * @param password And password
112: */
113: public Credentials(String username, String password) {
114: this .username = username;
115: this .password = password.toCharArray();
116: this .attempts = 0;
117: }
118:
119: /**
120: * Get this username
121: * @return The username
122: */
123: public String getUsername() {
124: return username;
125: }
126:
127: /**
128: * Get the password for this user
129: * @return The password
130: */
131: public char[] getPassword() {
132: return password;
133: }
134:
135: /**
136: * Set the number of attempted logins for this user
137: * @param value The number of attempted logins
138: */
139: public synchronized void setAuthorizationAttempts(int value) {
140: attempts = value;
141: }
142:
143: /**
144: * Get the number of attempted logins for this user
145: * @return The number of attempted logins
146: */
147: public synchronized int getAuthorizationAttempts() {
148: return attempts;
149: }
150: }
151: }
|