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, true, true, true,
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 }
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>