001: /*
002:
003: This software is OSI Certified Open Source Software.
004: OSI Certified is a certification mark of the Open Source Initiative.
005:
006: The license (Mozilla version 1.0) can be read at the MMBase site.
007: See http://www.MMBase.org/license
008:
009: */
010: package org.mmbase.security;
011:
012: import java.util.Map;
013:
014: import org.mmbase.util.functions.*;
015: import org.mmbase.bridge.Node;
016:
017: import org.mmbase.util.logging.Logger;
018: import org.mmbase.util.logging.Logging;
019:
020: /**
021: * This class is a abstract implementation of the Authentication.
022: *
023: * To make your own implementation of authentication, you have to extend this class.
024: *
025: * @author Eduard Witteveen
026: * @author Michiel Meeuwissen (javadocs)
027: * @version $Id: Authentication.java,v 1.41 2008/01/21 15:25:28 michiel Exp $
028: */
029: public abstract class Authentication extends Configurable implements
030: AuthenticationData {
031: private static final Logger log = Logging
032: .getLoggerInstance(Authentication.class);
033:
034: static {
035: try {
036: PARAMETER_USERNAME.getLocalizedDescription().setBundle(
037: STRINGS);
038: PARAMETER_PASSWORD.getLocalizedDescription().setBundle(
039: STRINGS);
040: ((org.mmbase.datatypes.StringDataType) PARAMETER_PASSWORD
041: .getDataType()).setPassword(true);
042: PARAMETER_USERNAMES.getLocalizedDescription().setBundle(
043: STRINGS);
044: PARAMETER_RANK.getLocalizedDescription().setBundle(STRINGS);
045: PARAMETER_SESSIONNAME.getLocalizedDescription().setBundle(
046: STRINGS);
047: PARAMETER_LOGOUT.getLocalizedDescription().setBundle(
048: STRINGS);
049: PARAMETER_AUTHENTICATE.getLocalizedDescription().setBundle(
050: STRINGS);
051: } catch (Exception e) {
052: log.error(e.getMessage(), e);
053: }
054: }
055:
056: /**
057: * This method will verify the login, and give a UserContext back if the login procedure was successful.
058: * @param application A String that further specifies the login method (one implementation could handle more then one methods)
059: * A typical value might be 'username/password'.
060: * Possible values are returned by {@link #getTypes}.
061: * This is also called 'authentication', or '(authentication) type' in
062: * several contextes.
063: *
064: * @param loginInfo A Map containing the credentials or other objects which might be used to obtain them (e.g. request/response objects).
065: * It might also be 'null', in which case your implementation normally should return the 'anonymous' user (or null, if
066: * no such user can be defined). This Map can (or must) be supplied by
067: * {@link #createParameters} (using the setter-methods and the {@link
068: * Parameters#toMap} method of the resulting Parameters object).
069: *
070: * @param parameters A list of optional parameters, may also (and will often) be null.
071: *
072: * @return <code>null</code> if no valid credentials were supplied, a (perhaps new) UserContext if login succeeded.
073: *
074: * @exception SecurityException When something strange happened, or authentication was unsucessfull.
075: */
076: public abstract UserContext login(String application,
077: Map<String, Object> loginInfo, Object[] parameters)
078: throws SecurityException;
079:
080: /**
081: * {@inheritDoc}
082: * @since MMBase-1.9
083: */
084: public Node getNode(UserContext userContext)
085: throws SecurityException, UnsupportedOperationException {
086: throw new UnsupportedOperationException(
087: "This security implementation does not support mapping from Security usercontexts to MMBase nodes");
088: }
089:
090: /**
091: * {@inheritDoc}
092: * @since MMBase-1.9
093: */
094: public String getUserBuilder() throws UnsupportedOperationException {
095: throw new UnsupportedOperationException(
096: "This security implementation has no builder associated with UserContexts");
097: }
098:
099: /**
100: * {@inheritDoc}
101: * @since MMBase-1.8
102: */
103: public final int getMethod(String m) {
104: if (m == null || m.equals("")) {
105: return METHOD_UNSET;
106: }
107: m = m.toLowerCase();
108: if ("http".equals(m)) {
109: return METHOD_HTTP;
110: } else if ("asis".equals(m)) {
111: return METHOD_ASIS;
112: } else if ("anonymous".equals(m)) {
113: return METHOD_ANONYMOUS;
114: } else if ("logout".equals(m)) {
115: return METHOD_LOGOUT;
116: } else if ("loginpage".equals(m)) {
117: return METHOD_LOGINPAGE;
118: } else if ("delegate".equals(m)) {
119: return METHOD_DELEGATE;
120: } else if ("sessiondelegate".equals(m)) {
121: return METHOD_SESSIONDELEGATE;
122: } else if ("pagelogon".equals(m)) {
123: return METHOD_PAGELOGON;
124: } else if ("sessionlogon".equals(m)) {
125: return METHOD_SESSIONLOGON;
126: } else if ("default".equals(m)) {
127: return METHOD_DEFAULT;
128: //} else if ("given_or_anonymous".equals(m)) {
129: // return METHOD_GIVEN_OR_ANONYMOUS;
130: } else {
131: throw new RuntimeException(
132: "Unknown value for 'method' attribute (" + m + ")");
133: }
134: }
135:
136: /**
137: *
138: * @since MMBase-1.9
139: */
140: public static final String getMethod(int m) {
141: switch (m) {
142: case METHOD_HTTP:
143: return "http";
144: case METHOD_ASIS:
145: return "asis";
146: case METHOD_ANONYMOUS:
147: return "anonymous";
148: case METHOD_LOGOUT:
149: return "logout";
150: case METHOD_DELEGATE:
151: return "delegate";
152: case METHOD_SESSIONDELEGATE:
153: return "sessiondelegate";
154: case METHOD_PAGELOGON:
155: return "pagelogon";
156: case METHOD_SESSIONLOGON:
157: return "sessionlogon";
158: case METHOD_DEFAULT:
159: return "default";
160: default:
161: return "unknown";
162: }
163: }
164:
165: /**
166: * {@inheritDoc}
167: * @since MMBase-1.8
168: */
169: public int getDefaultMethod(String protocol) {
170: if (protocol == null
171: || protocol.substring(0, 4).equalsIgnoreCase("HTTP")) {
172: return METHOD_HTTP;
173: } else {
174: return METHOD_DELEGATE; // leave it completely to the implementation. (using the 'class' application or the request object or so)
175: }
176: }
177:
178: /**
179: * {@inheritDoc}
180: * @since MMBase-1.8
181: */
182: public String[] getTypes() {
183: return getTypes(METHOD_UNSET);
184: }
185:
186: /**
187: * {@inheritDoc}
188: * @since MMBase-1.8
189: */
190: public String[] getTypes(int method) {
191: if (method == METHOD_ASIS) {
192: return new String[] { "anonymous", "name/password", "class" };
193: } else {
194: return new String[] { "name/password", "class" };
195: }
196: }
197:
198: protected static final Parameter[] PARAMETERS_USERS = new Parameter[] {
199: PARAMETER_USERNAMES, PARAMETER_RANK };
200: protected static final Parameter[] PARAMETERS_ANONYMOUS = new Parameter[] {
201: PARAMETER_LOGOUT, PARAMETER_AUTHENTICATE };
202: protected static final Parameter[] PARAMETERS_NAME_PASSWORD = new Parameter[] {
203: PARAMETER_USERNAME, PARAMETER_PASSWORD,
204: new Parameter.Wrapper(PARAMETERS_USERS) };
205:
206: /**
207: * {@inheritDoc}
208: * @since MMBase-1.8
209: */
210: public Parameters createParameters(String application) {
211: application = application.toLowerCase();
212: if ("anonymous".equals(application)) {
213: return new Parameters(PARAMETERS_ANONYMOUS);
214: } else if ("class".equals(application)) {
215: return Parameters.VOID;
216: } else if ("name/password".equals(application)) {
217: return new Parameters(PARAMETERS_NAME_PASSWORD);
218: } else {
219: return new AutodefiningParameters();
220: }
221: }
222:
223: long key = System.currentTimeMillis();
224:
225: /**
226: *<p> Some unique key associated with this security configuration. It can be explicitely set with
227: * the 'key' entry in security.xml. It falls back to the current time in milliseconds at the time of
228: * initialization of authentication.</p>
229: *
230: * <p>The advantage of explicitely configuring it, is that serialized user-contextes remain valid
231: * after a restart of MMBase, and users need not to log in again then.</p>
232: *
233: * @since MMBase-1.8
234: */
235: public long getKey() {
236: return key;
237: }
238: }
|