001package com.randomnoun.common.security.impl; 002 003/* (c) 2013 randomnoun. All Rights Reserved. This work is licensed under a 004 * BSD Simplified License. (http://www.randomnoun.com/bsd-simplified.html) 005 */ 006 007import java.io.IOException; 008import java.util.*; 009 010import org.apache.log4j.Logger; 011import org.springframework.jdbc.core.*; 012 013import com.randomnoun.common.Text; 014import com.randomnoun.common.security.Permission; 015import com.randomnoun.common.security.SecurityAuthenticator; 016import com.randomnoun.common.security.User; 017import com.randomnoun.common.security.impl.SpringSecurityAuthenticatorImpl; 018 019// ok. the USERID column in the table is actually a string. 020// presumably the actual User.userId is sourced from some other column. 021 022// this implementation appears to favour querying on the USERID String, 023// so bear that in mind as well. It also doesn't populate the actual User.userId, 024// so don't use that at all. 025 026/** 027 * See SpringSecurityLoaderImpl. Maybe. 028 * 029 * 030 * @author knoxg 031 */ 032public class SpringSecurityAuthenticatorImpl 033 implements SecurityAuthenticator 034{ 035 036 /** Logger for this class */ 037 public static final Logger logger = Logger.getLogger(SpringSecurityAuthenticatorImpl.class); 038 039 /** Properties used in this loader */ 040 private Map<String, Object> properties = null; 041 042 public static String INIT_TABLENAME = "tableName"; 043 public static String INIT_USERNAME_COLUMN = "usernameColumn"; 044 public static String INIT_PASSWORD_COLUMN = "passwordColumn"; 045 046 /** Odd. */ 047 public static String INIT_JDBCTEMPLATE = "jdbcTemplate"; 048 049 String tableName; 050 String usernameColumn; 051 String passwordColumn; 052 053 /** Initialise this loader. 054 * 055 * @see com.randomnoun.common.security.SecurityLoader#initialise(java.util.Map) 056 */ 057 public void initialise(Map<String, Object> properties) 058 { 059 this.properties = properties; 060 if (properties.get(INIT_JDBCTEMPLATE)==null) { throw new NullPointerException("null INIT_JDBCTEMPLATE"); } 061 062 tableName = Text.strDefault((String) properties.get(INIT_TABLENAME), "users"); 063 usernameColumn = Text.strDefault((String) properties.get(INIT_USERNAME_COLUMN), "userId"); 064 passwordColumn = Text.strDefault((String) properties.get(INIT_PASSWORD_COLUMN), "password"); 065 } 066 067 /** Authenticates a user. 068 * 069 */ 070 public boolean authenticate(User user, String password) 071 { 072 // check that the password is not empty 073 if (password == null || password.equals("")) { 074 return false; 075 } 076 JdbcTemplate jt = (JdbcTemplate)properties.get("jdbcTemplate"); 077 String sql = 078 "SELECT " + passwordColumn + 079 " FROM " + tableName + 080 " WHERE " + usernameColumn + " = ?"; 081 List<Object> sqlParams = new ArrayList<Object>(2); 082 sqlParams.add(user.getUsername()); 083 boolean authenticated = false; 084 try { 085 // TODO hash this, then perform the comparison in a stored procedure, 086 // then move it all to LDAP or OpenID 087 String databasePassword = (String) jt.queryForObject(sql, sqlParams.toArray(), String.class); 088 authenticated = password.equals(databasePassword); 089 } catch (Exception ex) { 090 logger.error("Error authenticating user", ex); 091 authenticated = false; 092 } 093 return authenticated; 094 } 095 096 097 /** Resets the security context. 098 * 099 * <p>This security context holds no state, so this method does nothing. 100 */ 101 public void resetSecurityContext() { 102 // no action necessary 103 } 104 105 public void saveUserRolesAndPermissions(User user, List<String> roles, List<Permission> userPermissions) throws IOException 106 { 107 throw new UnsupportedOperationException("not implemented"); 108 } 109 110 public void saveRolePermissions(String role, List<Permission> rolePermissions) 111 throws IOException 112 { 113 throw new UnsupportedOperationException("not implemented"); 114 } 115 116} 117