001 package org.springframework.richclient.security; 002 003 import java.io.Serializable; 004 005 import org.apache.commons.logging.Log; 006 import org.apache.commons.logging.LogFactory; 007 import org.springframework.context.ApplicationContext; 008 import org.springframework.rules.constraint.Constraint; 009 import org.springframework.richclient.application.Application; 010 import org.springframework.rules.PropertyConstraintProvider; 011 import org.springframework.rules.Rules; 012 import org.springframework.rules.constraint.property.PropertyConstraint; 013 import org.springframework.security.Authentication; 014 import org.springframework.security.AuthenticationManager; 015 import org.springframework.security.SpringSecurityException; 016 import org.springframework.security.context.SecurityContextHolder; 017 import org.springframework.security.providers.UsernamePasswordAuthenticationToken; 018 019 /** 020 * This class provides a bean suitable for use in a login form, providing properties for 021 * storing the user name and password. It also provides 022 * event firing for application security lifecycle. {@link LoginCommand} uses this 023 * object as its form object to collect the user name and password to use in an 024 * authentication request. 025 * <p> 026 * The actual authentication request is handled here, in the {@link #login()} method. 027 * 028 * <P> 029 * Temporarily stores the username and password provided by the user. 030 * 031 * @deprecated by the creation of new {@link ApplicationSecurityManager} 032 * 033 * @author Ben Alex 034 * @see ClientSecurityEvent 035 * @see LoginCommand 036 * @see LogoutCommand 037 */ 038 public class SessionDetails implements Serializable, PropertyConstraintProvider { 039 public static final String PROPERTY_USERNAME = "username"; 040 041 public static final String PROPERTY_PASSWORD = "password"; 042 043 private static final Log logger = LogFactory.getLog( SessionDetails.class ); 044 045 private transient AuthenticationManager authenticationManager; 046 047 private String username; 048 049 private String password; 050 051 private Rules validationRules; 052 053 public SessionDetails() { 054 // Retrieve any existing login information from the 055 // ContextHolder 056 if (SecurityContextHolder.getContext().getAuthentication() != null) { 057 setUsername(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString()); 058 setPassword(SecurityContextHolder.getContext().getAuthentication().getCredentials().toString()); 059 } 060 initRules(); 061 } 062 063 protected void initRules() { 064 this.validationRules = new Rules(getClass()) { 065 protected void initRules() { 066 add(PROPERTY_USERNAME, all(new Constraint[] { required(), maxLength(getUsernameMaxLength()) })); 067 add(PROPERTY_PASSWORD, all(new Constraint[] { required(), minLength(getPasswordMinLength()) })); 068 } 069 070 protected int getUsernameMaxLength() { 071 return 8; 072 } 073 074 protected int getPasswordMinLength() { 075 return 2; 076 } 077 078 }; 079 } 080 081 public PropertyConstraint getPropertyConstraint(String propertyName) { 082 return validationRules.getPropertyConstraint(propertyName); 083 } 084 085 public String getUsername() { 086 return username; 087 } 088 089 public void setUsername(String username) { 090 this.username = username; 091 } 092 093 public String getPassword() { 094 return password; 095 } 096 097 public void setPassword(String password) { 098 this.password = password; 099 } 100 101 public void setAuthenticationManager(AuthenticationManager manager) { 102 this.authenticationManager = manager; 103 } 104 105 public void login() throws SpringSecurityException { 106 final ApplicationContext appCtx = Application.instance().getApplicationContext(); 107 108 // Attempt login 109 UsernamePasswordAuthenticationToken request = new UsernamePasswordAuthenticationToken(getUsername(), 110 getPassword()); 111 112 Authentication result = null; 113 114 try { 115 result = authenticationManager.authenticate(request); 116 } catch( SpringSecurityException e ) { 117 logger.warn( "authentication failed", e); 118 119 // Fire application event to advise of failed login 120 appCtx.publishEvent( new AuthenticationFailedEvent(request, e)); 121 122 // And rethrow the exception to prevent the dialog from closing 123 throw e; 124 } 125 126 // Handle success or failure of the authentication attempt 127 if( logger.isDebugEnabled()) { 128 logger.debug("successful login - update context holder and fire event"); 129 } 130 131 // Commit the successful Authentication object to the secure 132 // ContextHolder 133 SecurityContextHolder.getContext().setAuthentication(result); 134 135 // Fire application event to advise of new login 136 appCtx.publishEvent(new LoginEvent(result)); 137 } 138 139 public static Authentication logout() { 140 Authentication existing = SecurityContextHolder.getContext().getAuthentication(); 141 142 // Make the Authentication object null if a SecureContext exists 143 SecurityContextHolder.getContext().setAuthentication(null); 144 145 // Create a non-null Authentication object if required (to meet 146 // ApplicationEvent contract) 147 if (existing == null) { 148 existing = ClientSecurityEvent.NO_AUTHENTICATION; 149 } 150 151 // Fire application event to advise of logout 152 ApplicationContext appCtx = Application.instance().getApplicationContext(); 153 appCtx.publishEvent(new LogoutEvent(existing)); 154 155 return existing; 156 } 157 158 }