AcegiJdbcDaoImpl.java
  1 package org.security.acegi;
  2 
  3 import java.sql.ResultSet;
  4 
  5 import java.sql.SQLException;
  6 
  7 import java.sql.Types;
  8 
  9 import java.util.List;
 10 
 11 import javax.sql.DataSource;
 12 
 13 import org.acegisecurity.GrantedAuthority;
 14 
 15 import org.acegisecurity.GrantedAuthorityImpl;
 16 
 17 import org.acegisecurity.userdetails.UsernameNotFoundException;
 18 
 19 import org.acegisecurity.userdetails.jdbc.JdbcDaoImpl;
 20 
 21 import org.security.IUserDetails;
 22 
 23 import org.security.UserDetailsImpl;
 24 
 25 import org.springframework.dao.DataAccessException;
 26 
 27 import org.springframework.jdbc.core.SqlParameter;
 28 
 29 import org.springframework.jdbc.object.MappingSqlQuery;
 30 
 31 /**
 32  * The class AcegiJdbcDaoImpl provides the method to
     *  get IUserDetail information from db which contains userId,
     * companyId and UserDetail information.
 33  * 
 34  * @author wade
 35  *
 36  */
 37 public class AcegiJdbcDaoImpl extends JdbcDaoImpl {
 38 
 39 public static final String DEF_USERS_BY_USERNAME_QUERY =
 40 
 41 "SELECT u.user_id, u.company_id, email, password, enabled                         "+"from role r, user_role ur, user u where r.role_id = ur.role_id "+"and ur.user_id = u.user_id and email = ? limit 1";
 42 
 43 public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY =
 44 
 45 "SELECT username,authority FROM authorities WHERE username = ?";
 46 
 47 protected MappingSqlQuery rolesByUsernameMapping;
 48 
 49 protected MappingSqlQuery usersByNameMapping;
 50 
 51 private String authoritiesByUsernameQuery;
 52 
 53 private String rolePrefix = "";
 54 
 55 private String usersByUsernameQuery;
 56 
 57 private boolean usernameBasedPrimaryKey = true;
 58 
 59 public AcegiJdbcDaoImpl(){
 60 
 61 usersByUsernameQuery = DEF_USERS_BY_USERNAME_QUERY;
 62 
 63 authoritiesByUsernameQuery = DEF_AUTHORITIES_BY_USERNAME_QUERY;
 64 
 65 }
 66 
 67 public String getAuthoritiesByUsernameQuery() {
 68 
 69 return authoritiesByUsernameQuery;
 70 
 71 }
 72 
 73 public String getRolePrefix() {
 74 
 75 return rolePrefix;
 76 
 77 }
 78 
 79 public String getUsersByUsernameQuery() {
 80 
 81 return usersByUsernameQuery;
 82 
 83 }
 84 
 85 protected void initMappingSqlQueries() {
 86 
 87 this.usersByNameMapping = new UsersByUsernameMapping(getDataSource());
 88 
 89 this.rolesByUsernameMapping = new AuthoritiesByUsernameMapping(getDataSource());
 90 
 91 }
 92 
 93 /**
 94      * Allows the default query string used to retrieve authorities based on
         *      username to be overriden, if
 95      * default table or column names need to be changed. The default query is {@link
 96      * #DEF_AUTHORITIES_BY_USERNAME_QUERY}; when modifying this query,
         *      ensure that all returned columns are mapped
 97      * back to the same column names as in the default query.
 98      *
 99      * @param queryString The query string to set
100      */
101 public void setAuthoritiesByUsernameQuery(String queryString) {
102 
103 authoritiesByUsernameQuery = queryString;
104 
105 }
106 
107 /**
108      * Allows a default role prefix to be specified. If this is set to a non-empty value,
         then it is
109      * automatically prepended to any roles read in from the db. This may for example be used to add the
110      * <code>ROLE_</code> prefix expected to exist in role names (by default) by some other Acegi Security framework
111      * classes, in the case that the prefix is not already present in the db.
112      *
113      * @param rolePrefix the new prefix
114      */
115 public void setRolePrefix(String rolePrefix) {
116 
117 this.rolePrefix = rolePrefix;
118 
119 }
120 
121 /**
122      * If <code>true</code> (the default), indicates the {@link #getUsersByUsernameQuery()} returns a username
123      * in response to a query. If <code>false</code>, indicates that a primary key is used instead. If set to
124      * <code>true</code>, the class will use the database-derived username in the returned <code>UserDetailsImpl</code>.
125      * If <code>false</code>, the class will use the {@link #loadUserByUsername(String)} derived username in the
126      * returned <code>UserDetailsImpl</code>.
127      *
128      * @param usernameBasedPrimaryKey <code>true</code> if the mapping queries return the username <code>String</code>,
129      *        or <code>false</code> if the mapping returns a database primary key.
130      */
131 public void setUsernameBasedPrimaryKey(boolean usernameBasedPrimaryKey) {
132 
133 this.usernameBasedPrimaryKey = usernameBasedPrimaryKey;
134 
135 }
136 
137 /**
138      * Allows the default query string used to retrieve users based on username to be overriden, if default
139      * table or column names need to be changed. The default query is {@link #DEF_USERS_BY_USERNAME_QUERY}; when
140      * modifying this query, ensure that all returned columns are mapped back to the same column names as in the
141      * default query. If the 'enabled' column does not exist in the source db, a permanent true value for this column
142      * may be returned by using a query similar to <br><pre>
143      * "SELECT username,password,'true' as enabled FROM users WHERE username = ?"</pre>
144      *
145      * @param usersByUsernameQueryString The query string to set
146      */
147 public void setUsersByUsernameQuery(String usersByUsernameQueryString) {
148 
149 this.usersByUsernameQuery = usersByUsernameQueryString;
150 
151 }
152 
153 public IUserDetails loadUserByUsername(String username)
154 
155 throws UsernameNotFoundException, DataAccessException {
156 
157 List users = usersByNameMapping.execute(username);
158 
159 if (users.size() == 0) {
160 
161 throw new UsernameNotFoundException("User not found");
162 
163 }
164 
165 IUserDetails user = (IUserDetails) users.get(0); // contains no GrantedAuthority[]
166 List dbAuths = rolesByUsernameMapping.execute(user.getUsername());
167 addCustomAuthorities(user.getUsername(), dbAuths);
168 if (dbAuths.size() == 0) {
169 
170 throw new UsernameNotFoundException("User has no GrantedAuthority");
171 
172 }
173 
174 GrantedAuthority[] arrayAuths = (GrantedAuthority[]) dbAuths.toArray(new GrantedAuthority[dbAuths.size()]);
175 
176 user.setAuthorities(arrayAuths);
177 
178 if (!usernameBasedPrimaryKey) {
179 
180 user.setUsername(username);
181 
182 }
183 
184 return user;
185 
186 }
187 
188 /**
189      * Query object to look up a user's authorities.
190      */
191 protected class AuthoritiesByUsernameMapping extends MappingSqlQuery {
192 
193 protected AuthoritiesByUsernameMapping(DataSource ds) {
194 
195 super(ds, authoritiesByUsernameQuery);
196 
197 declareParameter(new SqlParameter(Types.VARCHAR));
198 
199 compile();
200 
201 }
202 
203 protected Object mapRow(ResultSet rs, int rownum)
204 
205 throws SQLException {
206 
207 String roleName = rolePrefix + rs.getString(2);
208 
209 GrantedAuthorityImpl authority = new GrantedAuthorityImpl(roleName);
210 
211 return authority;
212 
213 }
214 
215 }
216 
217 /**
218      * Query object to look up a user.
219      */
220 protected class UsersByUsernameMapping extends MappingSqlQuery {
221 
222 protected UsersByUsernameMapping(DataSource ds) {
223 
224 super(ds, usersByUsernameQuery);
225 
226 declareParameter(new SqlParameter(Types.VARCHAR));
227 
228 compile();
229 
230 }
231 
232 protected Object mapRow(ResultSet rs, int rownum)
233 
234 throws SQLException {
235 
236 int user_id = rs.getInt(1);
237 
238 int company_id = rs.getInt(2);
239 
240 String username = rs.getString(3);
241 
242 String password = rs.getString(4);
243 
244 boolean enabled = rs.getBoolean(5);
245 
246 IUserDetails user = new UserDetailsImpl(username, password, enabled, truetruetrue,
247 
248 new GrantedAuthority[] {new GrantedAuthorityImpl("HOLDER")});
249 
250 user.setUserId(user_id);
251 
252 user.setCompanyId(company_id);
253 
254 return user;
255 
256 }
257 
258 }
259 
260 }

修改spring配置, 使用我们新建立的类:
 1 <bean id="userDetailsService"
 2 class="org.security.acegi.AcegiJdbcDaoImpl">
 3 <property name="dataSource">
 4 <ref bean="dataSource" />
 5 </property>
 6 <property name="usersByUsernameQuery">
 7 <value>
 8 SELECT u.user_id, u.company_id, email, password, enabled
 9 from role r, user_role ur, user u where r.role_id = ur.role_id and ur.user_id = u.user_id
10 and email = ?
11 limit 1
12 </value>
13 </property>
14 <property name="authoritiesByUsernameQuery">
15 <value>
16 SELECT u.email, r.role_name FROM user_role ur, user u, role r WHERE
17 ur.user_id = u.user_id and ur.role_id = r.role_id and u.email = ?
18 </value>
19 </property>
20 </bean>

好了, 如果再有用户登录,就会调用我们的loadUserByUsername, 从数据库中读取用户数据了, 那用户的权限都有什么呢? 一个用户又对应着哪些ROLE呢? 下面先讲一下ACEGI 例子中的权限设置