All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.acegisecurity.userdetails.jdbc.JdbcDaoImpl Maven / Gradle / Ivy

There is a newer version: 1.0.7
Show newest version
/* Copyright 2004, 2005 Acegi Technology Pty Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.acegisecurity.userdetails.jdbc;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.List;

import javax.sql.DataSource;

import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.userdetails.User;
import org.acegisecurity.userdetails.UserDetails;
import org.acegisecurity.userdetails.UserDetailsService;
import org.acegisecurity.userdetails.UsernameNotFoundException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContextException;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
import org.springframework.jdbc.object.MappingSqlQuery;


/**
 * 

* Retrieves user details (username, password, enabled flag, and authorities) * from a JDBC location. *

* *

* A default database structure is assumed, (see {@link * #DEF_USERS_BY_USERNAME_QUERY} and {@link * #DEF_AUTHORITIES_BY_USERNAME_QUERY}, which most users of this class will * need to override, if using an existing scheme. This may be done by setting * the default query strings used. If this does not provide enough * flexibility, another strategy would be to subclass this class and override * the {@link MappingSqlQuery} instances used, via the {@link * #initMappingSqlQueries()} extension point. *

* *

* In order to minimise backward compatibility issues, this DAO does not * recognise the expiration of user accounts or the expiration of user * credentials. However, it does recognise and honour the user * enabled/disabled column. *

* * @author Ben Alex * @author colin sampaleanu * @version $Id: JdbcDaoImpl.java,v 1.17 2005/12/04 10:48:33 benalex Exp $ */ public class JdbcDaoImpl extends JdbcDaoSupport implements UserDetailsService { //~ Static fields/initializers ============================================= public static final String DEF_USERS_BY_USERNAME_QUERY = "SELECT username,password,enabled FROM users WHERE username = ?"; public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY = "SELECT username,authority FROM authorities WHERE username = ?"; private static final Log logger = LogFactory.getLog(JdbcDaoImpl.class); //~ Instance fields ======================================================== protected MappingSqlQuery authoritiesByUsernameMapping; protected MappingSqlQuery usersByUsernameMapping; private String authoritiesByUsernameQuery; private String rolePrefix = ""; private String usersByUsernameQuery; private boolean usernameBasedPrimaryKey = true; //~ Constructors =========================================================== public JdbcDaoImpl() { usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY; authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY; } //~ Methods ================================================================ /** * Allows the default query string used to retrieve authorities based on * username to be overriden, if default table or column names need to be * changed. The default query is {@link * #DEF_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query, ensure * that all returned columns are mapped back to the same column names as * in the default query. * * @param queryString The query string to set */ public void setAuthoritiesByUsernameQuery(String queryString) { authoritiesByUsernameQuery = queryString; } public String getAuthoritiesByUsernameQuery() { return authoritiesByUsernameQuery; } /** * Allows a default role prefix to be specified. If this is set to a * non-empty value, then it is automatically prepended to any roles read * in from the db. This may for example be used to add the * ROLE_ prefix expected to exist in role names (by default) * by some other Acegi Security framework classes, in the case that the * prefix is not already present in the db. * * @param rolePrefix the new prefix */ public void setRolePrefix(String rolePrefix) { this.rolePrefix = rolePrefix; } public String getRolePrefix() { return rolePrefix; } /** * If true (the default), indicates the {@link * #getUsersByUsernameMapping()} returns a username in response to a * query. If false, indicates that a primary key is used * instead. If set to true, the class will use the * database-derived username in the returned UserDetails. If * false, the class will use the {@link * #loadUserByUsername(String)} derived username in the returned * UserDetails. * * @param usernameBasedPrimaryKey true if the mapping queries * return the username String, or false * if the mapping returns a database primary key. */ public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) { this.usernameBasedPrimaryKey = usernameBasedPrimaryKey; } public boolean isUsernameBasedPrimaryKey() { return usernameBasedPrimaryKey; } /** * Allows the default query string used to retrieve users based on username * to be overriden, if default table or column names need to be changed. * The default query is {@link #DEF_USERS_BY_USERNAME_QUERY}; when * modifying this query, ensure that all returned columns are mapped back * to the same column names as in the default query. If the 'enabled' * column does not exist in the source db, a permanent true value for this * column may be returned by using a query similar to
*
     * "SELECT username,password,'true' as enabled FROM users WHERE username = ?"
     * 
* * @param usersByUsernameQueryString The query string to set */ public void setUsersByUsernameQuery(String usersByUsernameQueryString) { this.usersByUsernameQuery = usersByUsernameQueryString; } public String getUsersByUsernameQuery() { return usersByUsernameQuery; } public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { List users = usersByUsernameMapping.execute(username); if (users.size() == 0) { throw new UsernameNotFoundException("User not found"); } UserDetails user = (UserDetails) users.get(0); // contains no GrantedAuthority[] List dbAuths = authoritiesByUsernameMapping.execute(user.getUsername()); if (dbAuths.size() == 0) { throw new UsernameNotFoundException("User has no GrantedAuthority"); } GrantedAuthority[] arrayAuths = {}; addCustomAuthorities(user.getUsername(), dbAuths); arrayAuths = (GrantedAuthority[]) dbAuths.toArray(arrayAuths); String returnUsername = user.getUsername(); if (!usernameBasedPrimaryKey) { returnUsername = username; } return new User(returnUsername, user.getPassword(), user.isEnabled(), true, true, true, arrayAuths); } /** * Allows subclasses to add their own granted authorities to the list to be * returned in the User. * * @param username the username, for use by finder methods * @param authorities the current granted authorities, as populated from * the authoritiesByUsername mapping */ protected void addCustomAuthorities(String username, List authorities) {} protected void initDao() throws ApplicationContextException { initMappingSqlQueries(); } /** * Extension point to allow other MappingSqlQuery objects to be substituted * in a subclass */ protected void initMappingSqlQueries() { this.usersByUsernameMapping = new UsersByUsernameMapping(getDataSource()); this.authoritiesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource()); } //~ Inner Classes ========================================================== /** * Query object to look up a user's authorities. */ protected class AuthoritiesByUsernameMapping extends MappingSqlQuery { protected AuthoritiesByUsernameMapping(DataSource ds) { super(ds, authoritiesByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String roleName = rolePrefix + rs.getString(2); GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName); return authority; } } /** * Query object to look up a user. */ protected class UsersByUsernameMapping extends MappingSqlQuery { protected UsersByUsernameMapping(DataSource ds) { super(ds, usersByUsernameQuery); declareParameter(new SqlParameter(Types.VARCHAR)); compile(); } protected Object mapRow(ResultSet rs, int rownum) throws SQLException { String username = rs.getString(1); String password = rs.getString(2); boolean enabled = rs.getBoolean(3); UserDetails user = new User(username, password, enabled, true, true, true, new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")}); return user; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy