001: /*
002: * Copyright 2001 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005: package com.sun.portal.desktop.context;
006:
007: import com.sun.portal.desktop.ROC;
008: import com.sun.portal.desktop.RequestThreadLocalizer;
009: import com.sun.portal.desktop.util.Base64;
010: import com.sun.portal.desktop.util.PIParser;
011: import com.sun.portal.log.common.PortalLogger;
012:
013: import javax.servlet.http.Cookie;
014: import javax.servlet.http.HttpServletRequest;
015: import javax.servlet.http.HttpServletResponse;
016: import java.util.Collections;
017: import java.util.HashMap;
018: import java.util.Iterator;
019: import java.util.Map;
020: import java.util.Random;
021: import java.util.logging.Level;
022: import java.util.logging.Logger;
023:
024: /**
025: * Implements SessionContext and SessionAppContext
026: * for Desktop authless mode.
027: * <p/>
028: * There are 5 possible authless modes, based on the
029: * combination of the client properties "cookieSupport"
030: * and "authlessState".
031: * <ul>
032: * <li>cookiesSupport=true, authlessState=server.
033: * Client properties are stored on the server in a table.
034: * A cookie is set as an index into the table.
035: * <li>cookiesSupport=false, authlessState=server.
036: * Client properties are stored on the server in a table.
037: * URLs are encoded with the client SID to index into the table.
038: * <li>cookiesSupport=true, authlessState=client.
039: * Client properties are stored on the client.
040: * Client properties are encoded into a cookie value.
041: * <li>cookiesSupport=false, authlessState=client.
042: * Client properties are stored on the client.
043: * Client properties are encoded into URL.
044: * <li>cookiesSupport=[true|false], authlessState=none.
045: * No client properties are stored.
046: * No URLs are encoded, no cookies are set.
047: * </ul>
048: */
049:
050: public class AuthlessSessionContext implements SessionContext,
051: SessionAppContext {
052: //
053: // key values that start with ROC are used to store into
054: // the request object cache. they need not be prefixed
055: // with "desktop" because the ROC is desktop private.
056: //
057: // the non-ROC keys are initialized in the static
058: // constructor block below, to be namespaced
059: // by the cookie prefix.
060: //
061:
062: //
063: // key used to store map of cookies into request, so we
064: // don't have to build it >1 times per request
065: //
066: private static final String ROC_COOKIES = "cookies";
067:
068: //
069: // constants that determine if the data need to be written as
070: // Cookie or URL Parmaneter
071: //
072: private static final short MODE_COOKIE = 0;
073: private static final short MODE_URL = 1;
074: private static final short MODE_BOTH = 2;
075:
076: //
077: // key used to detect support for cookie
078: //
079: private static final String KEY_COOKIE_DETECT = "_eikooc_tceted_";
080: private static final String COOKIE_DETECT_VALUE = "check";
081: private static final String ATTR_COOKIE_DETECT = "com.sun.portal.desktop.context.authless.cookiedetect";
082:
083: //
084: // Key used for storing the detected cookiesupport as request attribute
085: //
086: private static final String ATTR_COOKIE_SUPPORT_MODE = "com.sun.portal.desktop.context.authless.cookiesupport";
087:
088: // key used to store suid into request, so we don't
089: // have ot dervice it >1 times per request
090: //
091: private static final String ROC_SUID = "suid";
092: private static final String SUID;
093:
094: //
095: // key used to store client SID in request
096: // while authless state is server
097: //
098: private static final String CLIENT_SID;
099: private static final String ROC_CLIENT_SID = "clientSID";
100:
101: //
102: // key used to store client properties in request
103: // while authless state is client
104: //
105: private static final String CLIENT_PROPERTIES;
106: private static final String ROC_CLIENT_PROPERTIES = "clientProperties";
107:
108: //
109: // key used to store session validity, so we don't
110: // have to make multiple calls per request
111: //
112: private static final String ROC_SESSION_VALID = "sessionValid";
113:
114: //
115: // key used to store the base 64 encoded client properties
116: // string. this is used only when the authless state
117: // is client. otherwise, they are stored in a
118: // table.
119: //
120: private static final String ROC_CLIENT_PROPERTIES_ENCODED = "clientPropertiesEncoded";
121:
122: //
123: // used to implement client properties
124: // in authless mode.
125: //
126: private static HashMap clientProperties = null;
127: private static Map syncClientProperties = null;
128: private static long lastClientSessionReap = 0;
129: private static Random random = null;
130:
131: private static DesktopAppContext dac = null;
132:
133: private static Logger debugLogger = PortalLogger
134: .getLogger(AuthlessSessionContext.class);
135:
136: static {
137: //
138: // one-time initialization.
139: //
140:
141: dac = DesktopAppContextThreadLocalizer.get();
142: String cookiePrefix = dac.getCookiePrefix();
143:
144: //
145: // the namespace on these must be configurable
146: //
147: CLIENT_PROPERTIES = cookiePrefix + ROC_CLIENT_PROPERTIES;
148: CLIENT_SID = cookiePrefix + ROC_CLIENT_SID;
149: SUID = cookiePrefix + ROC_SUID;
150:
151: //
152: // we hold on to the wrapped hash map because we
153: // need to clone it before we do the reap.
154: //
155: clientProperties = new HashMap();
156: syncClientProperties = Collections
157: .synchronizedMap(clientProperties);
158:
159: //
160: // used to generate pseudo-random portion of sid
161: //
162: random = new Random(System.currentTimeMillis());
163: }
164:
165: /**
166: * This class is used to store data pertaining
167: * to a client session. this is only used
168: * when the authless state is "server", and we're
169: * storing client properties on the server
170: */
171: private static class ClientSessionData {
172: private Map properties = null;
173: private long lastAccess = -1;
174:
175: public ClientSessionData() {
176: // nothing
177: }
178:
179: public Map getProperties() {
180: if (properties == null) {
181: //
182: // note: this table should technically be synchronized
183: // however, the only time when we'd have contention
184: // is if the same client made two nearly
185: // simultaneous requests ... which is unlikely.
186: //
187: properties = new HashMap();
188: }
189:
190: return properties;
191: }
192:
193: public long getLastAccess() {
194: return lastAccess;
195: }
196:
197: public void setLastAccess() {
198: this .lastAccess = System.currentTimeMillis();
199: }
200: }
201:
202: public void init(HttpServletRequest req, String portalId) {
203: // nothing
204: }
205:
206: private static ClientSessionData getClientSessionData(String sid) {
207: ClientSessionData csd = (ClientSessionData) syncClientProperties
208: .get(sid);
209: if (csd != null) {
210: csd.setLastAccess();
211: }
212:
213: return csd;
214: }
215:
216: private static String getParameter(HttpServletRequest req,
217: String name) {
218: return req.getParameter(name);
219: }
220:
221: private static Map getCookieMap(HttpServletRequest req) {
222: Map cookieMap = (Map) ROC.getObject(ROC_COOKIES);
223: if (cookieMap == null) {
224: Cookie[] cookies = req.getCookies();
225: if (cookies != null) {
226: cookieMap = new HashMap();
227: for (int i = 0; i < cookies.length; i++) {
228: Cookie c = cookies[i];
229: cookieMap.put(c.getName(), c);
230: }
231: ROC.setObject(ROC_COOKIES, cookieMap);
232: }
233: }
234:
235: return cookieMap;
236: }
237:
238: private static Cookie getCookie(HttpServletRequest req, String name) {
239: Map cookieMap = getCookieMap(req);
240: if (cookieMap == null) {
241: return null;
242: }
243:
244: return (Cookie) cookieMap.get(name);
245: }
246:
247: private static String getCookieValue(HttpServletRequest req,
248: String name) {
249: Cookie c = getCookie(req, name);
250: String value = null;
251:
252: if (c != null) {
253: value = c.getValue();
254: }
255:
256: return value;
257: }
258:
259: public String getStringProperty(String name) {
260: HttpServletRequest req = RequestThreadLocalizer.getRequest();
261: return getStringProperty(req, name);
262: }
263:
264: private static Map decodeClientProperties(HttpServletRequest req) {
265: Map cp = null;
266: String p;
267: short mode = getCookieSupportMode();
268: if (mode == MODE_COOKIE || mode == MODE_BOTH) {
269: p = getCookieValue(req, CLIENT_PROPERTIES);
270: cp = PIParser.decodeKeyValueString(p);
271: }
272: if (mode == MODE_URL || mode == MODE_BOTH) {
273: String pi = req.getPathInfo();
274: Map piMap = PIParser.parse(pi);
275: cp = (Map) piMap.get(PIParser.DESKTOP_AUTHLESS);
276: }
277: //dac.debugError("AuthlessSessionContext.decodeClientProperties:map cp=" + cp);
278:
279: return cp;
280: }
281:
282: private static String getStringPropertyServer(
283: HttpServletRequest req, String name) {
284: String clientSID = getClientSID(req);
285: String value = null;
286:
287: if (clientSID != null) {
288: ClientSessionData csd = getClientSessionData(clientSID);
289: if (csd != null) {
290: Map properties = csd.getProperties();
291: value = (String) properties.get(name);
292: }
293: }
294:
295: return value;
296: }
297:
298: private static String getStringPropertyClient(
299: HttpServletRequest req, String name) {
300: String value = null;
301: Map cp = getClientProperties(req, false);
302:
303: if (cp != null) {
304: value = (String) cp.get(name);
305: }
306:
307: return value;
308: }
309:
310: private static String getStringProperty(HttpServletRequest req,
311: String name) {
312: String value = null;
313: short authlessState = dac.getAuthlessState(dac
314: .getClientType(req));
315:
316: if (authlessState == ClientContext.AUTHLESS_STATE_SERVER) {
317: value = getStringPropertyServer(req, name);
318: } else if (authlessState == ClientContext.AUTHLESS_STATE_CLIENT) {
319: value = getStringPropertyClient(req, name);
320: }
321:
322: if (value == null) {
323: //
324: // either authless state is none, or we could
325: // not get the value from the server or client
326: // try to get from request attr
327: //
328: value = (String) req.getAttribute(name);
329: }
330:
331: return value;
332: }
333:
334: public void setStringProperty(String name, String val) {
335:
336: HttpServletRequest req = RequestThreadLocalizer.getRequest();
337: HttpServletResponse res = RequestThreadLocalizer.getResponse();
338:
339: setStringProperty(req, res, name, val);
340: }
341:
342: private static String getNewClientSID(HttpServletRequest req) {
343: //
344: // verify we have room for another client session
345: //
346: String sid = null;
347: long clientSessionsMax = dac.getClientSessionsMax();
348: if (syncClientProperties.size() >= clientSessionsMax) {
349: debugLogger.log(Level.FINE, "PSDT_CSPDC0001", Long
350: .toString(clientSessionsMax));
351:
352: } else {
353: String server = req.getServerName();
354: String pr = Integer.toString(random.nextInt());
355: sid = pr + "@" + server;
356: sid = Base64.encode(sid);
357:
358: //dac.debugError("AuthlessSessionContext.getNewClientSID(): got new sid=" + sid);
359: }
360:
361: return sid;
362: }
363:
364: protected static void setCookie(HttpServletResponse res,
365: String key, String val) {
366: Cookie c = new Cookie(key, val);
367: c.setPath("/");
368: res.addCookie(c);
369: }
370:
371: protected static void setClientSID(HttpServletRequest req,
372: HttpServletResponse res, String sid) {
373: short mode = getCookieSupportMode();
374: if (mode == MODE_COOKIE || mode == MODE_BOTH) {
375: setCookie(res, CLIENT_SID, sid);
376: }
377:
378: //
379: // if we're not in cookie mode, we don't have to do anything.
380: // the magic happens in encodeURL()
381: //
382:
383: //
384: // set the client sid in the request so we remember for this request
385: //
386: ROC.setObject(ROC_CLIENT_SID, sid);
387:
388: //dac.debugError("AuthlessSessionContext.setClientSID(): set sid=" + sid);
389: }
390:
391: private static void setStringPropertyServer(HttpServletRequest req,
392: HttpServletResponse res, String name, String val) {
393: String clientSID = getClientSID(req);
394: if (clientSID == null) {
395: //
396: // no client sid for this client, we need
397: // one now
398: //
399: clientSID = getNewClientSID(req);
400: }
401:
402: //
403: // if client SID is null, that means we've reached
404: // the max client sessions limit.
405: //
406:
407: if (clientSID != null) {
408: setClientSID(req, res, clientSID);
409: ClientSessionData csd = getClientSessionData(clientSID);
410: if (csd == null) {
411: csd = new ClientSessionData();
412: syncClientProperties.put(clientSID, csd);
413: }
414:
415: Map properties = csd.getProperties();
416: properties.put(name, val);
417: }
418: }
419:
420: private static synchronized void setStringPropertyClient(
421: HttpServletRequest req, HttpServletResponse res,
422: String name, String val) {
423: Map cp = getClientProperties(req, true);
424: cp.put(name, val);
425: setEncodedClientProperties(cp);
426: }
427:
428: private static void setStringProperty(HttpServletRequest req,
429: HttpServletResponse res, String name, String val) {
430: short authlessState = dac.getAuthlessState(dac
431: .getClientType(req));
432: if (authlessState == ClientContext.AUTHLESS_STATE_SERVER) {
433: setStringPropertyServer(req, res, name, val);
434: } else if (authlessState == ClientContext.AUTHLESS_STATE_CLIENT) {
435: setStringPropertyClient(req, res, name, val);
436: }
437:
438: //
439: // always set in request ... for the authless state
440: // none case, and for the cookie case where
441: // the value won't be available until the
442: // next request
443: //
444: req.setAttribute(name, val);
445: }
446:
447: public String getSessionID() {
448: return getUserID();
449: }
450:
451: public String getSessionID(HttpServletRequest req) {
452: return getUserID(req);
453: }
454:
455: public String getUserID() {
456: HttpServletRequest req = RequestThreadLocalizer.getRequest();
457: return getUserID(req);
458: }
459:
460: public String getUserID(HttpServletRequest req) {
461: return getSUID(req);
462: }
463:
464: public void addSessionListener(SessionListener sl) {
465: }
466:
467: public void addUserReference() {
468: }
469:
470: public void addUserListener(UserListener sl) {
471: }
472:
473: private static Map getClientProperties(HttpServletRequest req,
474: boolean create) {
475: Map cp;
476:
477: if (!ROC.containsObject(ROC_CLIENT_PROPERTIES)) {
478: cp = decodeClientProperties(req);
479: if (cp == null && create) {
480: cp = Collections.synchronizedMap(new HashMap());
481: }
482:
483: if (cp != null) {
484: ROC.setObject(ROC_CLIENT_PROPERTIES, cp);
485: }
486: } else {
487: cp = (Map) ROC.getObject(ROC_CLIENT_PROPERTIES);
488: }
489:
490: return cp;
491: }
492:
493: private static void setEncodedClientProperties() {
494: Map m = (Map) ROC.getObject(ROC_CLIENT_PROPERTIES);
495: setEncodedClientProperties(m);
496: }
497:
498: private static void setEncodedClientProperties(Map m) {
499: if (m != null) {
500: Map piMap = Collections.synchronizedMap(new HashMap());
501: piMap.put(PIParser.DESKTOP_AUTHLESS, m);
502: String pathInfo = PIParser.getPathInfoString(piMap);
503: ROC.setObject(ROC_CLIENT_PROPERTIES_ENCODED, pathInfo);
504: }
505: }
506:
507: private static String getEncodedClientProperties() {
508: if (!ROC.containsObject(ROC_CLIENT_PROPERTIES_ENCODED)) {
509: setEncodedClientProperties();
510: }
511: return (String) ROC.getObject(ROC_CLIENT_PROPERTIES_ENCODED);
512: }
513:
514: public String encodeURL(String url) {
515: HttpServletRequest req = RequestThreadLocalizer.getRequest();
516: short mode = getCookieSupportMode();
517: if (mode == MODE_URL || mode == MODE_BOTH) {
518: // we need to detect if cookie is not supported
519: String detect = (String) req
520: .getAttribute(ATTR_COOKIE_DETECT);
521: if (detect != null && detect.equals("true")) {
522: StringBuffer sb = new StringBuffer();
523: sb.append(KEY_COOKIE_DETECT).append("=").append(
524: COOKIE_DETECT_VALUE);
525: url = appendPI(url, sb.toString());
526: }
527: //
528: // no cookie support, URL must be encoded with sid
529: //
530: if (dac.getAuthlessState(dac.getClientType(req)) == ClientContext.AUTHLESS_STATE_SERVER) {
531: //
532: // encode only the client SID
533: //
534: String clientSID = getClientSID(req);
535: if (clientSID != null) {
536: //
537: // if there's no client sid, that means
538: // there's no client properties being
539: // set, so we don't need to
540: // encode anything.
541: //
542: StringBuffer piBuffer = new StringBuffer();
543: piBuffer.append(ROC_CLIENT_SID).append("=").append(
544: clientSID);
545: url = appendPI(url, piBuffer.toString());
546: }
547: } else if (dac.getAuthlessState(dac.getClientType(req)) == ClientContext.AUTHLESS_STATE_CLIENT) {
548: //
549: // no cookies, url must be encoded with properties
550: //
551: String p = getEncodedClientProperties();
552: if (p != null) {
553: url = appendPI(url, p);
554: }
555: }
556: //
557: // authless state none, do nothing
558: //
559: }
560: //
561: // don't do anything if we're in cookie mode
562: //
563:
564: //dac.debugError("AuthlessSessionContext.encodeURL(): url=" + url);
565: return url;
566: }
567:
568: private String appendPI(String url, String pi) {
569: String updatedURL;
570: String sep = PIParser.SEPARATOR;
571:
572: // check for query string in url.
573: HttpServletRequest req = RequestThreadLocalizer.getRequest();
574: String servletPath = req.getServletPath();
575: int i = url.indexOf("?");
576: if (i != -1) {
577: String uri = url.substring(0, i);
578: String query = url.substring(i, url.length());
579: if (servletPath != null && uri.endsWith(servletPath)) {
580: sep = "/";
581: }
582: updatedURL = uri + sep + pi + query;
583: } else {
584: if (servletPath != null && url.endsWith(servletPath)) {
585: sep = "/";
586: }
587: updatedURL = url + sep + pi;
588: }
589: return updatedURL;
590: }
591:
592: private static String getClientSID(HttpServletRequest req) {
593: //
594: // try to get from request
595: //
596: String clientSID = (String) ROC.getObject(ROC_CLIENT_SID);
597:
598: if (clientSID == null) {
599: short mode = getCookieSupportMode();
600: if (mode == MODE_COOKIE || mode == MODE_BOTH) {
601: clientSID = getCookieValue(req, CLIENT_SID);
602: }
603: if (mode == MODE_URL || mode == MODE_BOTH) {
604: String pi = req.getPathInfo();
605: //dac.debugError("AuthlessSessionContext.getClientSID(): pathInfo=" + pi);
606: // remove the leading "/"
607: if (pi != null && pi.length() > 1) {
608: pi = pi.substring(1);
609: int index = pi.indexOf(ROC_CLIENT_SID);
610: if (index != -1) {
611: int startIndex = pi.indexOf('=', index) + 1;
612: if (pi.indexOf(PIParser.SEPARATOR, index) == -1) {
613: clientSID = pi.substring(startIndex);
614: } else {
615: clientSID = pi
616: .substring(startIndex, pi.indexOf(
617: PIParser.SEPARATOR, index));
618: }
619: }
620: }
621: }
622:
623: if (clientSID != null) {
624: if (!syncClientProperties.containsKey(clientSID)) {
625: //
626: // only this class can hand out client sids
627: // this is to prevent user from typing in
628: // their own client sid into the pathinfo
629: //
630: clientSID = null;
631: } else {
632: ROC.setObject(ROC_CLIENT_SID, clientSID);
633: }
634: }
635: }
636:
637: return clientSID;
638: }
639:
640: private static void reapClientSessions() {
641: boolean needReap;
642: long now = System.currentTimeMillis();
643:
644: synchronized (syncClientProperties) {
645: //
646: // synchronize the check to see if we need to reap.
647: // since we set last = now in the sync block, we
648: // are guaranteed that only one thread will find
649: // now > last
650: //
651: // this should not cause contention, because we do very
652: // minimal work while we are synced.
653: //
654: // the alternative is to not sync this, and deal with multiple
655: // clients deciding they need to reap. this could be expensive
656: // because reaping is quite expensive.
657: //
658: long reapInterval = dac.getClientSessionReapInterval();
659: needReap = ((reapInterval != -1) && (now > lastClientSessionReap
660: + reapInterval * 1000));
661: if (needReap) {
662: lastClientSessionReap = now;
663: }
664: }
665:
666: if (needReap) {
667: Map cpClone;
668:
669: //
670: // sync of sync client properties, because that is
671: // what everyone else syncs on when accessing the
672: // client properties.
673: //
674: // do explicit sync and access the inner non-sync
675: // map here, because we can type it as a HashMap,
676: // and therefore use the clone() method implemented
677: // there.
678: //
679: synchronized (syncClientProperties) {
680: cpClone = (HashMap) clientProperties.clone();
681: }
682:
683: for (Iterator i = cpClone.keySet().iterator(); i.hasNext();) {
684: String sid = (String) i.next();
685: ClientSessionData csd = (ClientSessionData) cpClone
686: .get(sid);
687:
688: long lastAccess = csd.getLastAccess();
689: if ((lastAccess != -1)
690: && ((lastAccess + dac
691: .getClientSessionInactiveMax() * 1000) < now)) {
692: syncClientProperties.remove(sid);
693: //dac.debugError("AuthlessSessionContext.reapClientSessions(): removed sid=" + sid);
694: }
695: }
696: //dac.debugError("AuthlessSessionContext.reapClientSessions(): reaping complete, syncClientProperties.size()=" + syncClientProperties.size());
697: }
698: }
699:
700: private static short getCookieSupportMode() {
701: short retval = MODE_BOTH;
702:
703: HttpServletRequest req = RequestThreadLocalizer.getRequest();
704: HttpServletResponse res = RequestThreadLocalizer.getResponse();
705:
706: Short mode = null;
707: if (req != null) {
708: mode = (req.getAttribute(ATTR_COOKIE_SUPPORT_MODE)) == null ? null
709: : (Short) (req
710: .getAttribute(ATTR_COOKIE_SUPPORT_MODE));
711: }
712:
713: if (mode != null) {
714: retval = mode.shortValue();
715: } else {
716: short cookieSupport = dac.getCookieSupport(dac
717: .getClientType(req));
718: if (cookieSupport == ClientContext.COOKIE_SUPPORT_TRUE) {
719: retval = MODE_COOKIE;
720: } else if (cookieSupport == ClientContext.COOKIE_SUPPORT_FALSE) {
721: retval = MODE_URL;
722: } else {
723: retval = detectCookieSupport(req, res);
724: }
725: if (req != null) {
726: req.setAttribute(ATTR_COOKIE_SUPPORT_MODE, new Short(
727: retval));
728: }
729: }
730: debugLogger.log(Level.FINE, "PSDT_CSPDC0002", Integer
731: .toString(retval));
732: return retval;
733: }
734:
735: private static short detectCookieSupport(HttpServletRequest req,
736: HttpServletResponse res) {
737: short retval = MODE_BOTH;
738:
739: //Check if there is any cookie as part of the request,
740: // if so, we know, the client does support cookies.
741: Cookie[] cookies = req.getCookies();
742: if (cookies != null && cookies.length > 0) {
743: retval = MODE_COOKIE;
744: } else {
745: //need to find out if it's a new request, without cookies, or
746: //further request from a client which doesn't support cookies
747: // we check the PathInfo for presence of KEY_COOKIE_DETECT,
748: // if found, we know that the client doesn't support cookies,
749: // else it's a new request, so put the KEY_COOKIE_DETECT bot as Cookie as well as PathInfo.
750: if (isCookieDetectFoundInURI(req.getRequestURI())) {
751: retval = MODE_URL;
752: } else {
753: retval = MODE_BOTH;
754: setCookie(res, KEY_COOKIE_DETECT, COOKIE_DETECT_VALUE);
755: }
756: req.setAttribute(ATTR_COOKIE_DETECT, "true");
757: }
758: return retval;
759: }
760:
761: private static boolean isCookieDetectFoundInURI(String reqUri) {
762: boolean retval = false;
763: if (reqUri != null) {
764: if (reqUri.indexOf(KEY_COOKIE_DETECT) != -1) {
765: retval = true;
766: }
767: }
768: return retval;
769: }
770:
771: public boolean validateSession(HttpServletRequest req) {
772: Boolean valid = (Boolean) ROC.getObject(ROC_SESSION_VALID);
773: if (valid == null) {
774: //dac.debugError("AuthlessSessionContext.validateSession(): validating ...");
775: String suid = getSUID(req);
776: if (suid == null) {
777: valid = Boolean.FALSE;
778: } else {
779: boolean v = dac.isAuthorizedAuthlessUID(suid);
780:
781: if (v) {
782: //
783: // if we're authorized, set the suid as
784: // a client property, so we remember
785: // the setting for the next request
786: //
787: valid = Boolean.TRUE;
788: setStringProperty(SUID, suid);
789: } else {
790: //
791: // found an suid, but it was not authorized
792: // clear out the value, so we don't
793: // keep making request with the invalid
794: // sid, and instead will use the default
795: // next request
796: //
797: valid = Boolean.FALSE;
798: setStringProperty(SUID, null);
799: }
800: }
801:
802: ROC.setObject(ROC_SESSION_VALID, valid);
803: }
804:
805: reapClientSessions();
806:
807: return valid.booleanValue();
808: }
809:
810: protected static String getSUID(HttpServletRequest req) {
811: //
812: // try to get the SUID from ROC first,
813: // then from an http parameter,
814: // then from a client property, and finally, use the default
815: // if there is one
816: //
817:
818: String value;
819:
820: // try to get from ROC
821: value = (String) ROC.getObject(ROC_SUID);
822:
823: if (value == null || value.length() == 0) {
824: // try to get from parameter
825: value = getSUIDParameter(req);
826:
827: if (value == null || value.length() == 0) {
828: // try to get from client properties
829: value = getStringProperty(req, SUID);
830: }
831:
832: if (value == null || value.length() == 0) {
833: // try to get default
834: value = dac.getDefaultAuthlessUID();
835: }
836:
837: if (value != null) {
838: ROC.setObject(ROC_SUID, value);
839: }
840:
841: }
842:
843: return value;
844: }
845:
846: protected static String getSUIDParameter(HttpServletRequest req) {
847: return getParameter(req, SUID);
848: }
849:
850: public String getAuthenticationType() {
851: return "desktop.authless";
852: }
853:
854: /* Properties that are stored as Cookie on client browser.
855: * AuthlessAnonymous user state is managed via such cookie.
856: * Authenticated users use AM/DSAME session to manage user state, returns null in such case.
857: */
858: public Cookie getClientProperties() {
859: Cookie cookie = null;
860:
861: short mode = getCookieSupportMode();
862: if (mode == MODE_COOKIE || mode == MODE_BOTH) {
863: //
864: // cookie mode, make sure and add the
865: // newly created cookie, and set
866: // the base-64 encoded string in the ROC
867: // so it can be used by encodeURL()
868: //
869: String pathInfo = getEncodedClientProperties();
870: if (pathInfo != null) {
871: int startIndex = pathInfo.indexOf('=', pathInfo
872: .indexOf(PIParser.DESKTOP_AUTHLESS)) + 1;
873: String p = pathInfo.substring(startIndex);
874: //
875: // client properties exist, store in cookie
876: // note: this section may be reached
877: // multiple times per request resulting
878: // in the same cookie key being set
879: // multiple times. this is not a problem
880: // though, because the browser will honor
881: // the last value set.
882: //
883: cookie = new Cookie(CLIENT_PROPERTIES, p);
884: cookie.setPath("/");
885: }
886: }
887:
888: //
889: // if cookies are not supported, don't do anything
890: // we've put the new property into the client
891: // properties table for this request. the magic
892: // happens in encodeURL() where the table is used
893: //
894: return cookie;
895: }
896: }
|