001: /* Copyright 2004-2006 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.security.provider.cas;
007:
008: import java.util.Enumeration;
009:
010: import org.jasig.portal.ChannelRuntimeData;
011: import org.jasig.portal.ChannelStaticData;
012: import org.jasig.portal.security.IPerson;
013: import org.jasig.portal.security.ISecurityContext;
014: import org.jasig.portal.security.LocalConnectionContext;
015:
016: /**
017: * A LocalConnectionContext using the Central Authentication Service.
018: * This connection context places CAS proxy tickets on the URLs it
019: * processes. It searches for and uses any security context implementing
020: * ICasSecurityContext. This means that it supports both the filtered and the
021: * traditional CAS security context approaches and that this connection context
022: * can be used with any other security context scheme implementing CAS-like
023: * proxy ticket functionality if the corresponding security context implements
024: * ICasSecurityContext.
025: */
026: public class CasConnectionContext extends LocalConnectionContext {
027:
028: private ChannelStaticData staticData = null;
029:
030: private IPerson person = null;
031:
032: private ICasSecurityContext casSecurityContext = null;
033:
034: public void init(ChannelStaticData sd) {
035: this .staticData = sd;
036: this .person = sd.getPerson();
037:
038: ISecurityContext ic = this .person.getSecurityContext();
039: if (ic instanceof ICasSecurityContext && ic.isAuthenticated())
040: this .casSecurityContext = (ICasSecurityContext) ic;
041:
042: // loop through subcontexts to find implementations of
043: // ICasSecurityContext
044: Enumeration en = ic.getSubContexts();
045: while (en.hasMoreElements()) {
046: ISecurityContext sctx = (ISecurityContext) en.nextElement();
047: if (sctx instanceof ICasSecurityContext
048: && sctx.isAuthenticated())
049: this .casSecurityContext = (ICasSecurityContext) sctx;
050: }
051:
052: if (this .casSecurityContext == null)
053: log
054: .error("Unable to find authenticated ICasSecurityContext");
055: }
056:
057: public String getDescriptor(String descriptor, ChannelRuntimeData rd) {
058: if (log.isTraceEnabled()) {
059: log.trace("getDescriptor(" + descriptor + ", " + rd + ")");
060: }
061: if (rd.getHttpRequestMethod().equals("GET")) {
062: // get proxy service ticket for the service if needed
063: String proxyTicket = null;
064: if (this .casSecurityContext != null)
065: try {
066: proxyTicket = this .casSecurityContext
067: .getCasServiceToken(descriptor);
068: } catch (CasProxyTicketAcquisitionException casex) {
069: log
070: .error(
071: "getDescriptor() - Error retreiving proxy ticket.",
072: casex);
073: }
074:
075: // if the descriptor was null then at least return
076: // the proxy service ticket as a unique string
077: if (descriptor == null) {
078: return proxyTicket;
079: }
080:
081: if (proxyTicket != null) {
082: // append ticket parameter and value to query string
083: if (descriptor.indexOf("?") != -1) {
084: descriptor = descriptor + "&ticket=" + proxyTicket;
085: } else {
086: descriptor = descriptor + "?ticket=" + proxyTicket;
087: }
088: }
089: }
090:
091: if (log.isTraceEnabled()) {
092: log.trace("returning from getDescriptor() with ["
093: + descriptor + "]");
094: }
095: return descriptor;
096:
097: }
098:
099: /**
100: * Returns url with proxy service ticket appended. Looks for static
101: * parameter upc_cas_service_uri and uses that for service. If not
102: * specified, uses the passed uri
103: *
104: * @param descriptor
105: * The original descriptor.
106: * @return descriptor with CAS proxy ticket parameter appended.
107: */
108: public String getDescriptor(String descriptor) {
109: if (log.isTraceEnabled()) {
110: log.trace("entering getDescriptor(" + descriptor + ")");
111: }
112: String proxyTicket = null;
113:
114: if (this .casSecurityContext != null) {
115: try {
116: // if no specified parameter for service, use target descriptor
117: String casUri = this .staticData
118: .getParameter("upc_cas_service_uri");
119:
120: if (casUri != null) {
121: proxyTicket = this .casSecurityContext
122: .getCasServiceToken(casUri);
123: } else {
124: proxyTicket = this .casSecurityContext
125: .getCasServiceToken(descriptor);
126: }
127:
128: } catch (CasProxyTicketAcquisitionException casex) {
129: log
130: .error(
131: "CasConnectionContext::getDescriptor() - Error retreiving proxy ticket.",
132: casex);
133: }
134: }
135:
136: if (proxyTicket != null) {
137: // append ticket parameter and value to query string
138: if (descriptor.indexOf("?") != -1) {
139: descriptor = descriptor + "&ticket=" + proxyTicket;
140: } else {
141: descriptor = descriptor + "?ticket=" + proxyTicket;
142: }
143: }
144:
145: if (log.isTraceEnabled()) {
146: log.trace("returning from getDescriptor() with ["
147: + descriptor + "]");
148: }
149: return descriptor;
150: }
151:
152: /**
153: * Get the "ticket={ticket}" parameter String given a ChannelRuntimeData
154: * containing a parameter declaring the service for which a proxy ticket
155: * is desired. If the ChannelRuntimeData presents the parameter
156: * "cw_xml", this method returns "ticket={ticket}" where {ticket} is a
157: * proxy ticket authenticating to the service specified by the cw_xml
158: * ChannelRuntimeData parameter. If the ChannelRuntimedata does not present
159: * the "cw_xml" parameter, this method returns "ticket=null".
160: * @param rd ChannelRuntimeData.
161: * @return "ticket={ticket}" where {ticket} is a proxy ticket or is "null".
162: */
163: public String getPostData(ChannelRuntimeData rd) {
164: /*
165: * The design of this method might be improved by moving responsibility
166: * for determining what URI is being accessed to the caller (the channel)
167: * and taking a String argument identifying the service for which a
168: * proxy ticket is desired, rather than making CasConnectionContext
169: * aware of and bound to a particular ChannelRuntimeData parameter.
170: */
171:
172: // get proxy service ticket for the service if needed
173: String proxyTicket = null;
174: if (this .casSecurityContext != null)
175: try {
176: String xmlUri = rd.getParameter("cw_xml");
177: if (xmlUri == null) {
178: xmlUri = this .staticData.getParameter("cw_xml");
179: }
180: proxyTicket = this .casSecurityContext
181: .getCasServiceToken(xmlUri);
182: } catch (CasProxyTicketAcquisitionException casex) {
183: log
184: .error(
185: "sendLocalData() - Error retreiving proxy ticket.",
186: casex);
187: }
188: return ("ticket=" + proxyTicket);
189: }
190:
191: public void sendLocalData(Object conParam, ChannelRuntimeData rd) {
192: // CAS does not have anything to do here. Post data is handled by the
193: // getPostData method instead of being sent separately in this method.
194: return;
195: }
196:
197: public String toString() {
198: StringBuffer sb = new StringBuffer();
199: sb.append(this .getClass().getName());
200: sb.append(" staticData:");
201: sb.append(this .staticData);
202: sb.append(" person:");
203: sb.append(this .person);
204: sb.append(" casSecurityContext:");
205: sb.append(this.casSecurityContext);
206: return sb.toString();
207: }
208: }
|