This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.auth.form-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-form.git
commit d5ecfb958c5cc603a89d7d3dd6421367fd2f4456 Author: Justin Edelson <[email protected]> AuthorDate: Wed Jun 23 21:30:55 2010 +0000 SLING-1564 - adding support for form inclusion as well as custom form pages via fragments git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/extensions/formauth@957356 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 6 ++ .../formauth/impl/AuthenticationFormServlet.java | 43 ++++++++++++- .../formauth/impl/FormAuthenticationHandler.java | 71 ++++++++++++++++++++-- .../OSGI-INF/metatype/metatype.properties | 16 +++-- 4 files changed, 124 insertions(+), 12 deletions(-) diff --git a/pom.xml b/pom.xml index 5202b4f..1c35467 100644 --- a/pom.xml +++ b/pom.xml @@ -117,6 +117,12 @@ <scope>provided</scope> </dependency> <dependency> + <groupId>org.apache.sling</groupId> + <artifactId>org.apache.sling.api</artifactId> + <version>2.0.9-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + <dependency> <groupId>org.osgi</groupId> <artifactId>org.osgi.core</artifactId> </dependency> diff --git a/src/main/java/org/apache/sling/formauth/impl/AuthenticationFormServlet.java b/src/main/java/org/apache/sling/formauth/impl/AuthenticationFormServlet.java index 463f2de..233f48c 100644 --- a/src/main/java/org/apache/sling/formauth/impl/AuthenticationFormServlet.java +++ b/src/main/java/org/apache/sling/formauth/impl/AuthenticationFormServlet.java @@ -58,6 +58,10 @@ public class AuthenticationFormServlet extends HttpServlet { @SuppressWarnings("unused") private static final String AUTH_REQUIREMENT = "-" + SERVLET_PATH; + private static final String DEFAULT_FORM_PATH = "login.html"; + + private static final String CUSTOM_FORM_PATH = "custom_login.html"; + /** * The raw form used by the {@link #getForm(HttpServletRequest)} method to * fill in with per-request data. This field is set by the @@ -82,7 +86,30 @@ public class AuthenticationFormServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { + handle(request, response); + } + + /** + * Prepares and returns the login form. The response is sent as an UTF-8 + * encoded <code>text/html</code> page with all known cache control headers + * set to prevent all caching. + * <p> + * This servlet is to be called to handle the request directly, that is it + * expected to not be included and for the response to not be committed yet + * because it first resets the response. + * + * @throws IOException if an error occurrs preparing or sending back the + * login form + * @throws IllegalStateException if the response has already been committed + * and thus response reset is not possible. + */ + @Override + protected void doPost(HttpServletRequest request, + HttpServletResponse response) throws IOException { + handle(request, response); + } + private void handle(HttpServletRequest request, HttpServletResponse response) throws IOException { // reset the response first response.reset(); @@ -143,6 +170,12 @@ public class AuthenticationFormServlet extends HttpServlet { * string if there is no specific reason */ private String getReason(final HttpServletRequest request) { + // return the resource attribute if set to a non-empty string + Object resObj = request.getAttribute(FormAuthenticationHandler.PAR_J_REASON); + if (resObj instanceof FormReason) { + return ((FormReason) resObj).toString(); + } + final String reason = request.getParameter(FormAuthenticationHandler.PAR_J_REASON); if (reason != null) { try { @@ -150,7 +183,7 @@ public class AuthenticationFormServlet extends HttpServlet { } catch (IllegalArgumentException iae) { // thrown if the reason is not an expected value, assume none } - + // no valid FormReason value, use raw value return reason; } @@ -169,7 +202,13 @@ public class AuthenticationFormServlet extends HttpServlet { if (rawForm == null) { InputStream ins = null; try { - ins = getClass().getResourceAsStream("login.html"); + // try a custom login page first. + ins = getClass().getResourceAsStream(CUSTOM_FORM_PATH); + if (ins == null) { + // try the standard login page + ins = getClass().getResourceAsStream(DEFAULT_FORM_PATH); + } + if (ins != null) { StringBuilder builder = new StringBuilder(); Reader r = new InputStreamReader(ins, "UTF-8"); diff --git a/src/main/java/org/apache/sling/formauth/impl/FormAuthenticationHandler.java b/src/main/java/org/apache/sling/formauth/impl/FormAuthenticationHandler.java index 9e78e89..1415c67 100644 --- a/src/main/java/org/apache/sling/formauth/impl/FormAuthenticationHandler.java +++ b/src/main/java/org/apache/sling/formauth/impl/FormAuthenticationHandler.java @@ -28,6 +28,8 @@ import java.util.Dictionary; import javax.jcr.Credentials; import javax.jcr.SimpleCredentials; +import javax.servlet.Servlet; +import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -35,6 +37,10 @@ import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; +import org.apache.sling.api.resource.LoginException; +import org.apache.sling.api.resource.Resource; +import org.apache.sling.api.resource.ResourceResolver; +import org.apache.sling.api.resource.ResourceResolverFactory; import org.apache.sling.commons.auth.Authenticator; import org.apache.sling.commons.auth.spi.AuthenticationFeedbackHandler; import org.apache.sling.commons.auth.spi.AuthenticationHandler; @@ -151,6 +157,21 @@ public class FormAuthenticationHandler implements AuthenticationHandler, private static final String DEFAULT_TOKEN_FILE = "cookie-tokens.bin"; /** + * Whether to redirect to the login form or simple do an include. + * + * @scr.property type="Boolean" valueRef="DEFAULT_INCLUDE_FORM" + */ + public static final String PAR_INCLUDE_FORM = "form.use.include"; + + /** + * The default include value. + * + * @see #PAR_INCLUDE_FORM + */ + private static final boolean DEFAULT_INCLUDE_FORM = false; + + + /** * The request method required for user name and password submission by the * form (value is "POST"). */ @@ -247,6 +268,20 @@ public class FormAuthenticationHandler implements AuthenticationHandler, private ServiceRegistration loginModule; /** + * If true, the handler will attempt to include the login form instead of + * doing a redirect. + */ + private boolean includeLoginForm; + + /** + * The resource resolver factory used to resolve the login form as a resource + * + * @scr.reference policy="dynamic" cardinality="0..1" + */ + private ResourceResolverFactory resourceResolverFactory; + + + /** * Extracts cookie/session based credentials from the request. Returns * <code>null</code> if the handler assumes HTTP Basic authentication would * be more appropriate, if no form fields are present in the request and if @@ -311,6 +346,35 @@ public class FormAuthenticationHandler implements AuthenticationHandler, return true; } + String resource = getLoginResource(request); + if (resource == null) { + resource = request.getContextPath() + request.getPathInfo(); + request.setAttribute(Authenticator.LOGIN_RESOURCE, resource); + } + + if (includeLoginForm && (resourceResolverFactory != null)) { + ResourceResolver resourceResolver = null; + try { + resourceResolver = resourceResolverFactory.getAdministrativeResourceResolver(null); + Resource loginFormResource = resourceResolver.resolve(loginForm); + Servlet loginFormServlet = loginFormResource.adaptTo(Servlet.class); + if (loginFormServlet != null) { + try { + loginFormServlet.service(request, response); + return true; + } catch (ServletException e) { + log.error("Failed to include the form: " + loginForm, e); + } + } + } catch (LoginException e) { + log.error("Unable to get a resource resolver to include for the login resource. Will redirect instead."); + } finally { + if (resourceResolver != null) { + resourceResolver.close(); + } + } + } + // prepare the login form redirection target final StringBuilder targetBuilder = new StringBuilder(); targetBuilder.append(request.getContextPath()); @@ -318,10 +382,6 @@ public class FormAuthenticationHandler implements AuthenticationHandler, // append originally requested resource (for redirect after login) char parSep = '?'; - String resource = getLoginResource(request); - if (resource == null) { - resource = request.getContextPath() + request.getPathInfo(); - } if (resource != null) { targetBuilder.append(parSep).append(Authenticator.LOGIN_RESOURCE); @@ -706,6 +766,9 @@ public class FormAuthenticationHandler implements AuthenticationHandler, log.info("Cannot register FormLoginModulePlugin. This is expected if Sling LoginModulePlugin services are not supported"); log.debug("dump", t); } + + this.includeLoginForm = OsgiUtil.toBoolean(properties.get(PAR_INCLUDE_FORM), DEFAULT_INCLUDE_FORM); + } protected void deactivate( diff --git a/src/main/resources/OSGI-INF/metatype/metatype.properties b/src/main/resources/OSGI-INF/metatype/metatype.properties index 3c2a922..2e5839e 100644 --- a/src/main/resources/OSGI-INF/metatype/metatype.properties +++ b/src/main/resources/OSGI-INF/metatype/metatype.properties @@ -31,7 +31,7 @@ path.description = Repository path for which this authentication handler \ should be used by Sling. If this is empty, the authentication handler will \ be disabled. -form.login.form.name = Login Form +form.login.form.name = Login Form form.login.form.description = The URL (without any context path prefix) to \ redirect the client to to present the login form. The default value is \ "/system/sling/form/login". @@ -41,22 +41,22 @@ form.auth.storage.description = The type of storage used to provide the \ authentication state. Valid values are cookie and session. The default value \ (cookie) also applies if any setting other than the supported values is \ configured. - + form.auth.name.name = Cookie/Attribute Name form.auth.name.description = The name of the Cookie or HTTP Session attribute \ - providing the authentication state. The default value is "sling.formauth". + providing the authentication state. The default value is "sling.formauth". -form.credentials.name.name = Credentials Attribute +form.credentials.name.name = Credentials Attribute form.credentials.name.description = The name of the SimpleCredentials \ attribute used to provide the authentication data to the LoginModulePlugin. \ The default value is "sling.formauth". -form.auth.timeout.name = Timeout +form.auth.timeout.name = Timeout form.auth.timeout.description = The number of minutes after which a login \ session times out. This value is used as the expiry time set in the \ authentication data. The default value is 30 minutes. If the value is set \ a value less than 1, the default value is used instead. - + form.token.file.name = Security Token File form.token.file.description = The name of the file used to persist the \ security tokens. The default value is cookie-tokens.bin. This property \ @@ -70,3 +70,7 @@ form.token.file.description = The name of the file used to persist the \ service.ranking.name = Ranking service.ranking.description = The relative ranking of this service. +form.use.include.name = Include Form +form.use.include.description = If true, this authentication handler will attempt \ + to include a Servlet resource at the login form path. If false, a redirect will \ + be used instead. -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
