001: /* ***** BEGIN LICENSE BLOCK *****
002: * Version: MPL 1.1
003: * The contents of this file are subject to the Mozilla Public License Version
004: * 1.1 (the "License"); you may not use this file except in compliance with
005: * the License. You may obtain a copy of the License at
006: * http://www.mozilla.org/MPL/
007: *
008: * Software distributed under the License is distributed on an "AS IS" basis,
009: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
010: * for the specific language governing rights and limitations under the
011: * License.
012: *
013: * The Original Code is Riot.
014: *
015: * The Initial Developer of the Original Code is
016: * Neteye GmbH.
017: * Portions created by the Initial Developer are Copyright (C) 2007
018: * the Initial Developer. All Rights Reserved.
019: *
020: * Contributor(s):
021: * Felix Gnass [fgnass at neteye dot de]
022: *
023: * ***** END LICENSE BLOCK ***** */
024: package org.riotfamily.riot.hibernate.security;
025:
026: import org.hibernate.Criteria;
027: import org.hibernate.criterion.Restrictions;
028: import org.riotfamily.common.beans.PropertyUtils;
029: import org.riotfamily.common.util.HashUtils;
030: import org.riotfamily.riot.hibernate.dao.HqlDao;
031: import org.riotfamily.riot.list.support.ListParamsImpl;
032: import org.riotfamily.riot.security.auth.RiotUser;
033: import org.riotfamily.riot.security.auth.RiotUserDao;
034: import org.springframework.beans.factory.InitializingBean;
035: import org.springframework.util.Assert;
036:
037: /**
038: * RiotUserDao that performs look-ups vie Hibernate.
039: *
040: * @author Felix Gnass [fgnass at neteye dot de]
041: * @since 6.5
042: */
043: public class HibernateUserDao extends HqlDao implements RiotUserDao,
044: InitializingBean {
045:
046: public static final String DEFAULT_USERNAME = "admin";
047:
048: public static final String DEFAULT_PASSWORD = "admin";
049:
050: private String usernameProperty = "id";
051:
052: private String passwordProperty = "password";
053:
054: private String newPasswordProperty = "newPassword";
055:
056: private boolean hashPasswords = true;
057:
058: private RiotUser initialUser;
059:
060: /**
061: * Sets the user class.
062: * @throws IllegalArgumentException if the given class does not implement
063: * the {@link RiotUser} interface.
064: */
065: public void setEntityClass(Class entityClass) {
066: Assert.isAssignable(RiotUser.class, entityClass);
067: super .setEntityClass(entityClass);
068: }
069:
070: /**
071: * Sets the name of the property that holds the username. This property is
072: * used by {@link #findUserByCredentials(String, String)} to look up
073: * a user upon login.
074: */
075: public void setUsernameProperty(String usernameProperty) {
076: Assert.notNull(usernameProperty);
077: this .usernameProperty = usernameProperty;
078: }
079:
080: /**
081: * Sets the name of the property that holds the (possibly hashed) password.
082: * This property is used by {@link #findUserByCredentials(String, String)}
083: * to look up a user upon login.
084: */
085: public void setPasswordProperty(String passwordProperty) {
086: Assert.notNull(passwordProperty);
087: this .passwordProperty = passwordProperty;
088: }
089:
090: /**
091: * Sets whether MD5 hashes should be used instead of plain text passwords.
092: */
093: public void setHashPasswords(boolean hashPasswords) {
094: this .hashPasswords = hashPasswords;
095: }
096:
097: /**
098: * Sets the name of the (transient) property that holds the new plain text
099: * password. When {@link #setHashPasswords(boolean) hashed passwords} are
100: * used, this property is checked upon updates. If the property contains a
101: * non null value, this value is used to create a new password hash.
102: */
103: public void setNewPasswordProperty(String newPasswordProperty) {
104: this .newPasswordProperty = newPasswordProperty;
105: }
106:
107: /**
108: * Sets the initial user object that is persisted when no other user exists.
109: * If set to <code>null</code> (default), a new instance of the
110: * {@link #setEntityClass(Class) entity class} is created via reflection.
111: */
112: public void setInitialUser(RiotUser initialUser) {
113: this .initialUser = initialUser;
114: }
115:
116: public void afterPropertiesSet() throws Exception {
117: if (initialUser != null) {
118: Assert.isInstanceOf(getEntityClass(), initialUser);
119: } else {
120: initialUser = (RiotUser) getEntityClass().newInstance();
121: PropertyUtils.setProperty(initialUser, usernameProperty,
122: DEFAULT_USERNAME);
123:
124: String password = hashPasswords ? HashUtils
125: .md5(DEFAULT_PASSWORD) : DEFAULT_PASSWORD;
126:
127: PropertyUtils.setProperty(initialUser, passwordProperty,
128: password);
129: }
130: }
131:
132: public RiotUser findUserByCredentials(String username,
133: String password) {
134: if (hashPasswords) {
135: password = HashUtils.md5(password);
136: }
137: Criteria c = createCriteria(getEntityClass()).add(
138: Restrictions.eq(usernameProperty, username)).add(
139: Restrictions.eq(passwordProperty, password));
140:
141: RiotUser user = (RiotUser) c.uniqueResult();
142: if (user == null && !anyUserExists()) {
143: save(initialUser, null);
144: String initialUsername = PropertyUtils.getPropertyAsString(
145: initialUser, usernameProperty);
146: String initialPassword = PropertyUtils.getPropertyAsString(
147: initialUser, passwordProperty);
148: if (initialUsername.equals(username)
149: && initialPassword.equals(password)) {
150:
151: return initialUser;
152: }
153: }
154: return user;
155: }
156:
157: protected boolean anyUserExists() {
158: return getListSize(null, new ListParamsImpl()) > 0;
159: }
160:
161: protected void hashNewPassword(Object user) {
162: if (hashPasswords) {
163: String newPassword = PropertyUtils.getPropertyAsString(
164: user, newPasswordProperty);
165: if (newPassword != null) {
166: String hash = HashUtils.md5(newPassword);
167: PropertyUtils.setProperty(user, passwordProperty, hash);
168: PropertyUtils.setProperty(user, newPasswordProperty,
169: null);
170: }
171: }
172: }
173:
174: public void save(Object entity, Object parent) {
175: hashNewPassword(entity);
176: super .save(entity, parent);
177: }
178:
179: public void update(Object entity) {
180: hashNewPassword(entity);
181: super.update(entity);
182: }
183:
184: }
|