1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.acegisecurity.ui.webapp;
16
17 import org.acegisecurity.AuthenticationException;
18 import org.acegisecurity.intercept.web.AuthenticationEntryPoint;
19 import org.acegisecurity.util.PortMapper;
20 import org.acegisecurity.util.PortMapperImpl;
21 import org.acegisecurity.util.PortResolver;
22 import org.acegisecurity.util.PortResolverImpl;
23
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26
27 import org.springframework.beans.factory.InitializingBean;
28
29 import org.springframework.util.Assert;
30
31 import java.io.IOException;
32
33 import javax.servlet.ServletException;
34 import javax.servlet.ServletRequest;
35 import javax.servlet.ServletResponse;
36 import javax.servlet.http.HttpServletRequest;
37 import javax.servlet.http.HttpServletResponse;
38
39
40 /***
41 * <p>
42 * Used by the <code>SecurityEnforcementFilter</code> to commence
43 * authentication via the {@link AuthenticationProcessingFilter}. This object
44 * holds the location of the login form, relative to the web app context path,
45 * and is used to commence a redirect to that form.
46 * </p>
47 *
48 * <p>
49 * By setting the <em>forceHttps</em> property to true, you may configure the
50 * class to force the protocol used for the login form to be
51 * <code>HTTPS</code>, even if the original intercepted request for a resource
52 * used the <code>HTTP</code> protocol. When this happens, after a successful
53 * login (via HTTPS), the original resource will still be accessed as HTTP,
54 * via the original request URL. For the forced HTTPS feature to work, the
55 * {@link PortMapper} is consulted to determine the HTTP:HTTPS pairs.
56 * </p>
57 *
58 * @author Ben Alex
59 * @author colin sampaleanu
60 * @author Omri Spector
61 * @version $Id: AuthenticationProcessingFilterEntryPoint.java,v 1.11 2005/11/17 00:55:50 benalex Exp $
62 */
63 public class AuthenticationProcessingFilterEntryPoint
64 implements AuthenticationEntryPoint, InitializingBean {
65 private static final Log logger = LogFactory.getLog(AuthenticationProcessingFilterEntryPoint.class);
66 private PortMapper portMapper = new PortMapperImpl();
67 private PortResolver portResolver = new PortResolverImpl();
68 private String loginFormUrl;
69 private boolean forceHttps = false;
70
71 /***
72 * Set to true to force login form access to be via https. If this value is
73 * ture (the default is false), and the incoming request for the protected
74 * resource which triggered the interceptor was not already
75 * <code>https</code>, then
76 *
77 * @param forceHttps
78 */
79 public void setForceHttps(boolean forceHttps) {
80 this.forceHttps = forceHttps;
81 }
82
83 public boolean getForceHttps() {
84 return forceHttps;
85 }
86
87 /***
88 * The URL where the <code>AuthenticationProcessingFilter</code> login page
89 * can be found. Should be relative to the web-app context path, and
90 * include a leading <code>/</code>
91 *
92 * @param loginFormUrl
93 */
94 public void setLoginFormUrl(String loginFormUrl) {
95 this.loginFormUrl = loginFormUrl;
96 }
97
98 public String getLoginFormUrl() {
99 return loginFormUrl;
100 }
101
102 public void setPortMapper(PortMapper portMapper) {
103 this.portMapper = portMapper;
104 }
105
106 public PortMapper getPortMapper() {
107 return portMapper;
108 }
109
110 public void setPortResolver(PortResolver portResolver) {
111 this.portResolver = portResolver;
112 }
113
114 public PortResolver getPortResolver() {
115 return portResolver;
116 }
117
118 public void afterPropertiesSet() throws Exception {
119 Assert.hasLength(loginFormUrl, "loginFormUrl must be specified");
120 Assert.notNull(portMapper, "portMapper must be specified");
121 Assert.notNull(portResolver, "portResolver must be specified");
122 }
123
124 public void commence(ServletRequest request, ServletResponse response,
125 AuthenticationException authException)
126 throws IOException, ServletException {
127 HttpServletRequest req = (HttpServletRequest) request;
128 String scheme = request.getScheme();
129 String serverName = request.getServerName();
130 int serverPort = portResolver.getServerPort(request);
131 String contextPath = req.getContextPath();
132
133 boolean inHttp = "http".equals(scheme.toLowerCase());
134 boolean inHttps = "https".equals(scheme.toLowerCase());
135
136 boolean includePort = ((inHttp && (serverPort == 80)) ||
137 (inHttps && (serverPort == 443)));
138
139 if ("http".equals(scheme.toLowerCase()) && (serverPort == 80)) {
140 includePort = false;
141 }
142
143 if ("https".equals(scheme.toLowerCase()) && (serverPort == 443)) {
144 includePort = false;
145 }
146
147 String redirectUrl = contextPath + loginFormUrl;
148
149 if (forceHttps && inHttp) {
150 Integer httpPort = new Integer(portResolver.getServerPort(request));
151 Integer httpsPort = (Integer) portMapper.lookupHttpsPort(httpPort);
152
153 if (httpsPort != null) {
154 if (httpsPort.intValue() == 443) {
155 includePort = false;
156 } else {
157 includePort = true;
158 }
159
160 redirectUrl = "https://" + serverName +
161 ((includePort) ? (":" + httpsPort) : "") + contextPath +
162 loginFormUrl;
163 }
164 }
165
166 if (logger.isDebugEnabled()) {
167 logger.debug("Redirecting to: " + redirectUrl);
168 }
169
170 ((HttpServletResponse) response).sendRedirect(((HttpServletResponse) response).encodeRedirectURL(
171 redirectUrl));
172 }
173 }