~james-page/ubuntu/oneiric/jenkins-winstone/827651

« back to all changes in this revision

Viewing changes to src/java/winstone/auth/FormAuthenticationHandler.java

  • Committer: Bazaar Package Importer
  • Author(s): James Page
  • Date: 2011-06-29 12:16:17 UTC
  • Revision ID: james.westby@ubuntu.com-20110629121617-vd3ha6lp4nqvxkbr
Tags: upstream-0.9.10-jenkins-25+dfsg
ImportĀ upstreamĀ versionĀ 0.9.10-jenkins-25+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
 
3
 * Distributed under the terms of either:
 
4
 * - the common development and distribution license (CDDL), v1.0; or
 
5
 * - the GNU Lesser General Public License, v2.1 or later
 
6
 */
 
7
package winstone.auth;
 
8
 
 
9
import java.io.IOException;
 
10
import java.util.List;
 
11
import java.util.Set;
 
12
 
 
13
import javax.servlet.ServletException;
 
14
import javax.servlet.ServletRequest;
 
15
import javax.servlet.ServletResponse;
 
16
import javax.servlet.http.HttpServletRequest;
 
17
import javax.servlet.http.HttpServletRequestWrapper;
 
18
import javax.servlet.http.HttpServletResponse;
 
19
import javax.servlet.http.HttpSession;
 
20
 
 
21
import org.w3c.dom.Node;
 
22
 
 
23
import winstone.AuthenticationPrincipal;
 
24
import winstone.AuthenticationRealm;
 
25
import winstone.Logger;
 
26
import winstone.WebAppConfiguration;
 
27
import winstone.WinstoneRequest;
 
28
 
 
29
/**
 
30
 * Handles FORM based authentication configurations. Fairly simple ... it just
 
31
 * redirects any unauthorized requests to the login page, and any bad logins to
 
32
 * the error page. The auth values are stored in the session in a special slot.
 
33
 * 
 
34
 * @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
 
35
 * @version $Id: FormAuthenticationHandler.java,v 1.7 2006/12/13 14:07:43 rickknowles Exp $
 
36
 */
 
37
public class FormAuthenticationHandler extends BaseAuthenticationHandler {
 
38
    private static final String ELEM_FORM_LOGIN_CONFIG = "form-login-config";
 
39
    private static final String ELEM_FORM_LOGIN_PAGE = "form-login-page";
 
40
    private static final String ELEM_FORM_ERROR_PAGE = "form-error-page";
 
41
    private static final String FORM_ACTION = "j_security_check";
 
42
    private static final String FORM_USER = "j_username";
 
43
    private static final String FORM_PASS = "j_password";
 
44
    private static final String AUTHENTICATED_USER = "winstone.auth.FormAuthenticationHandler.AUTHENTICATED_USER";
 
45
    private static final String CACHED_REQUEST = "winstone.auth.FormAuthenticationHandler.CACHED_REQUEST";
 
46
    
 
47
    private String loginPage;
 
48
    private String errorPage;
 
49
 
 
50
    /**
 
51
     * Constructor for the FORM authenticator
 
52
     * 
 
53
     * @param realm
 
54
     *            The realm against which we are authenticating
 
55
     * @param constraints
 
56
     *            The array of security constraints that might apply
 
57
     * @param resources
 
58
     *            The list of resource strings for messages
 
59
     * @param realmName
 
60
     *            The name of the realm this handler claims
 
61
     */
 
62
    public FormAuthenticationHandler(Node loginConfigNode,
 
63
            List constraintNodes, Set rolesAllowed,
 
64
            AuthenticationRealm realm) {
 
65
        super(loginConfigNode, constraintNodes, rolesAllowed, realm);
 
66
 
 
67
        for (int n = 0; n < loginConfigNode.getChildNodes().getLength(); n++) {
 
68
            Node loginElm = loginConfigNode.getChildNodes().item(n);
 
69
            if (loginElm.getNodeName().equals(ELEM_FORM_LOGIN_CONFIG)) {
 
70
                for (int k = 0; k < loginElm.getChildNodes().getLength(); k++) {
 
71
                    Node formElm = loginElm.getChildNodes().item(k);
 
72
                    if (formElm.getNodeType() != Node.ELEMENT_NODE)
 
73
                        continue;
 
74
                    else if (formElm.getNodeName().equals(ELEM_FORM_LOGIN_PAGE))
 
75
                        loginPage = WebAppConfiguration.getTextFromNode(formElm);
 
76
                    else if (formElm.getNodeName().equals(ELEM_FORM_ERROR_PAGE))
 
77
                        errorPage = WebAppConfiguration.getTextFromNode(formElm);
 
78
                }
 
79
            }
 
80
        }
 
81
        Logger.log(Logger.DEBUG, AUTH_RESOURCES,
 
82
                "FormAuthenticationHandler.Initialised", realmName);
 
83
    }
 
84
 
 
85
    /**
 
86
     * Evaluates any authentication constraints, intercepting if auth is
 
87
     * required. The relevant authentication handler subclass's logic is used to
 
88
     * actually authenticate.
 
89
     * 
 
90
     * @return A boolean indicating whether to continue after this request
 
91
     */
 
92
    public boolean processAuthentication(ServletRequest request,
 
93
            ServletResponse response, String pathRequested) throws IOException,
 
94
            ServletException {
 
95
        if (pathRequested.equals(this.loginPage)
 
96
                || pathRequested.equals(this.errorPage)) {
 
97
            return true;
 
98
        } else {
 
99
            return super.processAuthentication(request, response, pathRequested);
 
100
        }
 
101
    }
 
102
 
 
103
    /**
 
104
     * Call this once we know that we need to authenticate
 
105
     */
 
106
    protected void requestAuthentication(HttpServletRequest request,
 
107
            HttpServletResponse response, String pathRequested)
 
108
            throws ServletException, IOException {
 
109
        // Save the critical details of the request into the session map
 
110
        ServletRequest unwrapped = request;
 
111
        while (unwrapped instanceof HttpServletRequestWrapper) {
 
112
            unwrapped = ((HttpServletRequestWrapper) unwrapped).getRequest();
 
113
        }
 
114
        HttpSession session = request.getSession(true);
 
115
        session.setAttribute(CACHED_REQUEST, new RetryRequestParams(unwrapped));
 
116
 
 
117
        // Forward on to the login page
 
118
        Logger.log(Logger.FULL_DEBUG, AUTH_RESOURCES,
 
119
                "FormAuthenticationHandler.GoToLoginPage");
 
120
        javax.servlet.RequestDispatcher rdLogin = request
 
121
                .getRequestDispatcher(this.loginPage);
 
122
        setNoCache(response);
 
123
        rdLogin.forward(request, response);
 
124
    }
 
125
 
 
126
    /**
 
127
     * Check the response - is it a response to the login page ?
 
128
     * 
 
129
     * @return A boolean indicating whether to continue with the request or not
 
130
     */
 
131
    protected boolean validatePossibleAuthenticationResponse(
 
132
            HttpServletRequest request, HttpServletResponse response,
 
133
            String pathRequested) throws ServletException, IOException {
 
134
        // Check if this is a j_security_check uri
 
135
        if (pathRequested.endsWith(FORM_ACTION)) {
 
136
            String username = request.getParameter(FORM_USER);
 
137
            String password = request.getParameter(FORM_PASS);
 
138
 
 
139
            // Send to error page if invalid
 
140
            AuthenticationPrincipal principal = this.realm
 
141
                    .authenticateByUsernamePassword(username, password);
 
142
            if (principal == null) {
 
143
                javax.servlet.RequestDispatcher rdError = request
 
144
                        .getRequestDispatcher(this.errorPage);
 
145
                rdError.forward(request, response);
 
146
            }
 
147
 
 
148
            // Send to stashed request
 
149
            else {
 
150
                // Iterate back as far as we can
 
151
                ServletRequest wrapperCheck = request;
 
152
                while (wrapperCheck instanceof HttpServletRequestWrapper) {
 
153
                    wrapperCheck = ((HttpServletRequestWrapper) wrapperCheck).getRequest();
 
154
                }
 
155
                
 
156
                // Get the stashed request
 
157
                WinstoneRequest actualRequest = null;
 
158
                if (wrapperCheck instanceof WinstoneRequest) {
 
159
                    actualRequest = (WinstoneRequest) wrapperCheck;
 
160
                    actualRequest.setRemoteUser(principal);
 
161
                } else {
 
162
                    Logger.log(Logger.WARNING, AUTH_RESOURCES,
 
163
                            "FormAuthenticationHandler.CantSetUser",
 
164
                            wrapperCheck.getClass().getName());
 
165
                }
 
166
                HttpSession session = request.getSession(true);
 
167
                String previousLocation = this.loginPage;
 
168
                RetryRequestParams cachedRequest = (RetryRequestParams) 
 
169
                        session.getAttribute(CACHED_REQUEST);
 
170
                if ((cachedRequest != null) && (actualRequest != null)) {
 
171
                    // Repopulate this request from the params we saved
 
172
                    request = new RetryRequestWrapper(request, cachedRequest);
 
173
                    previousLocation = 
 
174
                        (request.getServletPath() == null ? "" : request.getServletPath()) + 
 
175
                        (request.getPathInfo() == null ? "" : request.getPathInfo());
 
176
                } else {
 
177
                    Logger.log(Logger.DEBUG, AUTH_RESOURCES,
 
178
                            "FormAuthenticationHandler.NoCachedRequest");
 
179
                }
 
180
                
 
181
                // do role check, since we don't know that this user has permission
 
182
                if (doRoleCheck(request, response, previousLocation)) {
 
183
                    principal.setAuthType(HttpServletRequest.FORM_AUTH);
 
184
                    session.setAttribute(AUTHENTICATED_USER, principal);
 
185
                    javax.servlet.RequestDispatcher rdPrevious = request
 
186
                            .getRequestDispatcher(previousLocation);
 
187
                    rdPrevious.forward(request, response);
 
188
                } else {
 
189
                    javax.servlet.RequestDispatcher rdError = request
 
190
                            .getRequestDispatcher(this.errorPage);
 
191
                    rdError.forward(request, response);
 
192
                }
 
193
            }
 
194
            return false;
 
195
        }
 
196
        // If it's not a login, get the session, and look up the auth user variable
 
197
        else {
 
198
            WinstoneRequest actualRequest = null;
 
199
            if (request instanceof WinstoneRequest) {
 
200
                actualRequest = (WinstoneRequest) request;
 
201
            } else if (request instanceof HttpServletRequestWrapper) { 
 
202
                HttpServletRequestWrapper wrapper = (HttpServletRequestWrapper) request;
 
203
                if (wrapper.getRequest() instanceof WinstoneRequest) {
 
204
                    actualRequest = (WinstoneRequest) wrapper.getRequest();
 
205
                } else {
 
206
                    Logger.log(Logger.WARNING, AUTH_RESOURCES,
 
207
                            "FormAuthenticationHandler.CantSetUser", wrapper
 
208
                                    .getRequest().getClass().getName());
 
209
                }
 
210
            } else {
 
211
                Logger.log(Logger.WARNING, AUTH_RESOURCES,
 
212
                        "FormAuthenticationHandler.CantSetUser", request
 
213
                                .getClass().getName());
 
214
            }
 
215
 
 
216
            HttpSession session = actualRequest.getSession(false);
 
217
            if (session != null) {
 
218
                AuthenticationPrincipal authenticatedUser = (AuthenticationPrincipal) 
 
219
                        session.getAttribute(AUTHENTICATED_USER); 
 
220
                if (authenticatedUser != null) {
 
221
                    actualRequest.setRemoteUser(authenticatedUser);
 
222
                    Logger.log(Logger.FULL_DEBUG, AUTH_RESOURCES,
 
223
                            "FormAuthenticationHandler.GotUserFromSession");
 
224
                }
 
225
            }
 
226
            return true;
 
227
        }
 
228
    }
 
229
}