Java tutorial
/* * Copyright (c) 2011-2012, Martijn Brinkers, Djigzo. * * This file is part of Djigzo email encryption. * * Djigzo is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License * version 3, 19 November 2007 as published by the Free Software * Foundation. * * Djigzo is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public * License along with Djigzo. If not, see <http://www.gnu.org/licenses/> * * Additional permission under GNU AGPL version 3 section 7 * * If you modify this Program, or any covered work, by linking or * combining it with saaj-api-1.3.jar, saaj-impl-1.3.jar, * wsdl4j-1.6.1.jar (or modified versions of these libraries), * containing parts covered by the terms of Common Development and * Distribution License (CDDL), Common Public License (CPL) the * licensors of this Program grant you additional permission to * convey the resulting work. */ package mitm.djigzo.web.pages.portal.secure; import java.net.URL; import javax.servlet.http.HttpSession; import mitm.application.djigzo.UserProperties; import mitm.application.djigzo.james.PortalInvitationValidator; import mitm.application.djigzo.james.PortalInvitationValidator.ValidatorException; import mitm.application.djigzo.ws.LoginWS; import mitm.application.djigzo.ws.PortalUserWS; import mitm.application.djigzo.ws.SystemManagerWS; import mitm.common.mail.EmailAddressUtils; import mitm.common.properties.HierarchicalPropertiesException; import mitm.common.ws.WebServiceCheckedException; import mitm.djigzo.web.common.security.PortalUserDetailsServiceExt; import mitm.djigzo.web.entities.UserManager; import mitm.djigzo.web.utils.PasswordCodec; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.tapestry5.Asset; import org.apache.tapestry5.ComponentResources; import org.apache.tapestry5.PersistenceConstants; import org.apache.tapestry5.annotations.BeginRender; import org.apache.tapestry5.annotations.Cached; import org.apache.tapestry5.annotations.Component; import org.apache.tapestry5.annotations.IncludeStylesheet; import org.apache.tapestry5.annotations.Path; import org.apache.tapestry5.annotations.Persist; import org.apache.tapestry5.annotations.Property; import org.apache.tapestry5.corelib.components.Form; import org.apache.tapestry5.corelib.components.PasswordField; import org.apache.tapestry5.ioc.Messages; import org.apache.tapestry5.ioc.annotations.Inject; import org.apache.tapestry5.ioc.annotations.Value; import org.apache.tapestry5.services.Request; import org.apache.tapestry5.services.RequestGlobals; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.Authentication; import org.springframework.security.AuthenticationException; import org.springframework.security.context.HttpSessionContextIntegrationFilter; import org.springframework.security.context.SecurityContext; import org.springframework.security.context.SecurityContextHolder; import org.springframework.security.providers.AbstractAuthenticationToken; import org.springframework.security.providers.ProviderManager; import org.springframework.security.providers.UsernamePasswordAuthenticationToken; import org.springframework.security.ui.AbstractProcessingFilter; import org.springframework.security.ui.WebAuthenticationDetails; import org.springframework.security.ui.savedrequest.SavedRequest; import org.springframework.security.userdetails.UserDetails; @IncludeStylesheet("context:styles/pages/portal/secure/signup.css") public class Signup { private final static Logger logger = LoggerFactory.getLogger(Signup.class); @SuppressWarnings("unused") @Inject @Path("context:images/logo.png") @Property private Asset logoAsset; @Inject private Request request; @Inject private ComponentResources resources; @Inject private Messages messages; @Inject private SystemManagerWS systemManagerWS; @Inject private UserManager userManager; @Inject private PasswordCodec passwordCodec; @Inject private PortalUserWS portalUserWS; @Inject private PortalUserDetailsServiceExt userDetailsService; @Inject private LoginWS loginWS; @Inject private ProviderManager authenticationManager; @Inject private RequestGlobals requestGlobals; /* * The new password for the user */ private String newPassword; /* * Again the new password (should be the same as newPassword) */ private String repeatNewPassword; /* * True if and error has occurred */ @Persist(PersistenceConstants.FLASH) private boolean error; /* * Error message if an error has occurred */ @Persist(PersistenceConstants.FLASH) private String errorMessage; @Component(id = "newPassword", parameters = { "value = newPassword", "validate=required" }) private PasswordField newPasswordField; @SuppressWarnings("unused") @Component(id = "repeatNewPassword", parameters = { "value = repeatNewPassword", "validate=required" }) private PasswordField repeatNewPasswordField; @Component private Form form; /* * The email address request parameter */ private String email; /* * The timestamp request parameter */ private long timestamp; /* * The mac request parameter */ private String mac; /* * The number of milliseconds a link is valid */ @Inject @Value("${portal.selectpassword.validity}") private long validity; @Cached private UserProperties getUserProperties() throws WebServiceCheckedException { return userManager.getUser(email, true).getPreferences().getProperties(); } @BeginRender public void beginRender() { /* * Make sure userDetailsService has access to the required serviced */ userDetailsService.setPasswordCodec(passwordCodec); userDetailsService.setLoginWS(loginWS); } protected Object onActivate() { if (!isBackendRunning()) { return null; } try { if (email == null) { email = EmailAddressUtils.canonicalizeAndValidate(request.getParameter("email"), true); } if (timestamp == 0) { timestamp = NumberUtils.toLong(request.getParameter("ts"), 0); } if (mac == null) { mac = StringUtils.trimToNull(request.getParameter("mac")); } if (email == null) { throw new ValidatorException("email is not set"); } if (timestamp == 0) { throw new ValidatorException("timestamp is not set"); } if (mac == null) { throw new ValidatorException("mac is not set"); } if ((System.currentTimeMillis() - timestamp) > validity) { throw new ValidatorException(messages.get("sign-up-expired")); } if (StringUtils.isNotEmpty(getUserProperties().getPortalProperties().getPassword())) { /* * A password was already set. Redirect to login page (this is also used to redirect to the * login after the user has selected a portal password) */ return resources.createPageLink(Login.class, false, email); } } catch (Exception e) { errorMessage = e.getMessage(); error = true; } return null; } private void validateParameters() throws ValidatorException { try { if ((System.currentTimeMillis() - timestamp) > validity) { throw new ValidatorException(messages.get("sign-up-expired")); } UserProperties userProperties = getUserProperties(); /* * Validate the mac */ PortalInvitationValidator validator = new PortalInvitationValidator(); validator.setEmail(email); validator.setTimestamp(timestamp); String check = validator.calulateMAC(userProperties.getServerSecret()); if (!StringUtils.equals(mac, check)) { throw new ValidatorException("The checksum is not correct"); } if (StringUtils.isNotEmpty(userProperties.getPortalProperties().getPassword())) { /* * A password was already set. */ throw new ValidatorException("Password was already set"); } } catch (WebServiceCheckedException e) { throw new ValidatorException(e); } catch (HierarchicalPropertiesException e) { throw new ValidatorException(e); } } protected void onActivate(String email, long timestamp, String mac) { this.email = StringUtils.trimToNull(email); this.timestamp = timestamp; this.mac = StringUtils.trimToNull(mac); } public Object[] onPassivate() { return new Object[] { email, timestamp, mac }; } public void onValidateForm() { try { if (StringUtils.isEmpty(newPassword)) { return; } if (StringUtils.isEmpty(repeatNewPassword)) { return; } if (!StringUtils.equals(newPassword, repeatNewPassword)) { form.recordError(newPasswordField, messages.get("passwords-not-equal")); return; } validateParameters(); } catch (Exception e) { form.recordError("There was a problem. Message: " + e.getMessage()); logger.error("Error validating form", e); } } /* * Retrieves that target URL which was saved by Spring when being redirected to the signup page */ private String getSavedTarget() { HttpSession session = requestGlobals.getHTTPServletRequest().getSession(false); if (session == null) { return null; } /* * Get the saved request from the HTTP session */ SavedRequest savedRequest = (SavedRequest) session .getAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY); String target = null; if (savedRequest != null) { target = savedRequest.getFullRequestUrl(); /* * Clear the saved request since we have handled it */ session.removeAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY); } return target; } public Object onSuccess() { Object result = null; try { portalUserWS.setEncodedPassword(email, passwordCodec.encodePassword(newPassword)); authenticate(email, newPassword); /* * get the saved request from Spring (if any) */ String target = getSavedTarget(); if (StringUtils.isNotEmpty(target)) { logger.debug("redirecting to {}", target); result = new URL(target); } } catch (Exception e) { error = true; errorMessage = e.getMessage(); logger.error("Error setting password", e); } return result; } /** * Programatically authenticate the user */ public void authenticate(String username, String password) { try { UserDetails details = userDetailsService.loadUserByUsername(username); UsernamePasswordAuthenticationToken usernameAndPassword = new UsernamePasswordAuthenticationToken( username, password, details.getAuthorities()); /* * Add details about the authentication (IP address etc.) */ ((AbstractAuthenticationToken) usernameAndPassword) .setDetails(new WebAuthenticationDetails(requestGlobals.getHTTPServletRequest())); /* * Authenticate, to be 100% certain that username/password is correct */ Authentication authentication = authenticationManager.doAuthentication(usernameAndPassword); SecurityContext securityContext = SecurityContextHolder.getContext(); securityContext.setAuthentication(authentication); /* * The SecurityContext must be placed in the HTTP session otherwise Spring will not use it */ requestGlobals.getHTTPServletRequest().getSession(true) .setAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY, securityContext); } catch (AuthenticationException e) { SecurityContextHolder.getContext().setAuthentication(null); logger.error("Login failed after registration.", e); throw e; } } public String getEmail() { return email; } public String getNewPassword() { return newPassword; } public void setNewPassword(String newPassword) { this.newPassword = newPassword; } public String getRepeatNewPassword() { return repeatNewPassword; } public void setRepeatNewPassword(String repeatNewPassword) { this.repeatNewPassword = repeatNewPassword; } public boolean isError() { return error; } public String getErrorMessage() { return errorMessage; } @Cached public boolean isBackendRunning() { boolean running; try { running = systemManagerWS.isRunning(); } catch (Exception e) { logger.error("Error in isBackendRunning. Backend is propably not running.", e); running = false; } return running; } }