001: /* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
002: *
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: *
007: * http://www.apache.org/licenses/LICENSE-2.0
008: *
009: * Unless required by applicable law or agreed to in writing, software
010: * distributed under the License is distributed on an "AS IS" BASIS,
011: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: * See the License for the specific language governing permissions and
013: * limitations under the License.
014: */
015:
016: package org.acegisecurity.securechannel;
017:
018: import org.acegisecurity.ConfigAttribute;
019: import org.acegisecurity.ConfigAttributeDefinition;
020:
021: import org.acegisecurity.intercept.web.FilterInvocation;
022: import org.acegisecurity.intercept.web.FilterInvocationDefinitionSource;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: import org.springframework.beans.factory.InitializingBean;
028:
029: import org.springframework.util.Assert;
030:
031: import java.io.IOException;
032:
033: import java.util.HashSet;
034: import java.util.Iterator;
035: import java.util.Set;
036:
037: import javax.servlet.Filter;
038: import javax.servlet.FilterChain;
039: import javax.servlet.FilterConfig;
040: import javax.servlet.ServletException;
041: import javax.servlet.ServletRequest;
042: import javax.servlet.ServletResponse;
043: import javax.servlet.http.HttpServletRequest;
044: import javax.servlet.http.HttpServletResponse;
045:
046: /**
047: * Ensures a web request is delivered over the required channel.<p>Internally uses a {@link FilterInvocation} to
048: * represent the request, so that the <code>FilterInvocation</code>-related property editors and lookup classes can be
049: * used.</p>
050: * <P>Delegates the actual channel security decisions and necessary actions to the configured {@link
051: * ChannelDecisionManager}. If a response is committed by the <code>ChannelDecisionManager</code>, the filter chain
052: * will not proceed.</p>
053: * <P><B>Do not use this class directly.</B> Instead configure <code>web.xml</code> to use the {@link
054: * org.acegisecurity.util.FilterToBeanProxy}.</p>
055: *
056: * @author Ben Alex
057: * @version $Id: ChannelProcessingFilter.java 1784 2007-02-24 21:00:24Z luke_t $
058: */
059: public class ChannelProcessingFilter implements InitializingBean,
060: Filter {
061: //~ Static fields/initializers =====================================================================================
062:
063: private static final Log logger = LogFactory
064: .getLog(ChannelProcessingFilter.class);
065:
066: //~ Instance fields ================================================================================================
067:
068: private ChannelDecisionManager channelDecisionManager;
069: private FilterInvocationDefinitionSource filterInvocationDefinitionSource;
070:
071: //~ Methods ========================================================================================================
072:
073: public void afterPropertiesSet() throws Exception {
074: Assert.notNull(filterInvocationDefinitionSource,
075: "filterInvocationDefinitionSource must be specified");
076: Assert.notNull(channelDecisionManager,
077: "channelDecisionManager must be specified");
078:
079: Iterator iter = this .filterInvocationDefinitionSource
080: .getConfigAttributeDefinitions();
081:
082: if (iter == null) {
083: if (logger.isWarnEnabled()) {
084: logger
085: .warn("Could not validate configuration attributes as the FilterInvocationDefinitionSource did "
086: + "not return a ConfigAttributeDefinition Iterator");
087: }
088:
089: return;
090: }
091:
092: Set set = new HashSet();
093:
094: while (iter.hasNext()) {
095: ConfigAttributeDefinition def = (ConfigAttributeDefinition) iter
096: .next();
097: Iterator attributes = def.getConfigAttributes();
098:
099: while (attributes.hasNext()) {
100: ConfigAttribute attr = (ConfigAttribute) attributes
101: .next();
102:
103: if (!this .channelDecisionManager.supports(attr)) {
104: set.add(attr);
105: }
106: }
107: }
108:
109: if (set.size() == 0) {
110: if (logger.isInfoEnabled()) {
111: logger.info("Validated configuration attributes");
112: }
113: } else {
114: throw new IllegalArgumentException(
115: "Unsupported configuration attributes: "
116: + set.toString());
117: }
118: }
119:
120: public void destroy() {
121: }
122:
123: public void doFilter(ServletRequest request,
124: ServletResponse response, FilterChain chain)
125: throws IOException, ServletException {
126: if (!(request instanceof HttpServletRequest)) {
127: throw new ServletException("HttpServletRequest required");
128: }
129:
130: if (!(response instanceof HttpServletResponse)) {
131: throw new ServletException("HttpServletResponse required");
132: }
133:
134: FilterInvocation fi = new FilterInvocation(request, response,
135: chain);
136: ConfigAttributeDefinition attr = this .filterInvocationDefinitionSource
137: .getAttributes(fi);
138:
139: if (attr != null) {
140: if (logger.isDebugEnabled()) {
141: logger.debug("Request: " + fi.toString()
142: + "; ConfigAttributes: " + attr.toString());
143: }
144:
145: channelDecisionManager.decide(fi, attr);
146:
147: if (fi.getResponse().isCommitted()) {
148: return;
149: }
150: }
151:
152: chain.doFilter(request, response);
153: }
154:
155: public ChannelDecisionManager getChannelDecisionManager() {
156: return channelDecisionManager;
157: }
158:
159: public FilterInvocationDefinitionSource getFilterInvocationDefinitionSource() {
160: return filterInvocationDefinitionSource;
161: }
162:
163: public void init(FilterConfig filterConfig) throws ServletException {
164: }
165:
166: public void setChannelDecisionManager(
167: ChannelDecisionManager channelDecisionManager) {
168: this .channelDecisionManager = channelDecisionManager;
169: }
170:
171: public void setFilterInvocationDefinitionSource(
172: FilterInvocationDefinitionSource filterInvocationDefinitionSource) {
173: this.filterInvocationDefinitionSource = filterInvocationDefinitionSource;
174: }
175: }
|