1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.security;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.sql.Connection;
24 import java.sql.DriverManager;
25 import java.sql.PreparedStatement;
26 import java.sql.ResultSet;
27 import java.sql.SQLException;
28 import java.util.ArrayList;
29 import java.util.List;
30 import java.util.Properties;
31
32 import javax.servlet.ServletRequest;
33
34 import org.eclipse.jetty.server.UserIdentity;
35 import org.eclipse.jetty.util.Loader;
36 import org.eclipse.jetty.util.log.Log;
37 import org.eclipse.jetty.util.log.Logger;
38 import org.eclipse.jetty.util.resource.Resource;
39 import org.eclipse.jetty.util.security.Credential;
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 public class JDBCLoginService extends MappedLoginService
56 {
57 private static final Logger LOG = Log.getLogger(JDBCLoginService.class);
58
59 protected String _config;
60 protected String _jdbcDriver;
61 protected String _url;
62 protected String _userName;
63 protected String _password;
64 protected String _userTableKey;
65 protected String _userTablePasswordField;
66 protected String _roleTableRoleField;
67 protected int _cacheTime;
68 protected long _lastHashPurge;
69 protected Connection _con;
70 protected String _userSql;
71 protected String _roleSql;
72
73
74
75
76
77 public class JDBCKnownUser extends KnownUser
78 {
79 int _userKey;
80
81 public JDBCKnownUser(String name, Credential credential, int key)
82 {
83 super(name, credential);
84 _userKey = key;
85 }
86
87
88 public int getUserKey ()
89 {
90 return _userKey;
91 }
92 }
93
94
95 public JDBCLoginService()
96 throws IOException
97 {
98 }
99
100
101 public JDBCLoginService(String name)
102 throws IOException
103 {
104 setName(name);
105 }
106
107
108 public JDBCLoginService(String name, String config)
109 throws IOException
110 {
111 setName(name);
112 setConfig(config);
113 }
114
115
116 public JDBCLoginService(String name, IdentityService identityService, String config)
117 throws IOException
118 {
119 setName(name);
120 setIdentityService(identityService);
121 setConfig(config);
122 }
123
124
125
126
127
128
129 @Override
130 protected void doStart() throws Exception
131 {
132 Properties properties = new Properties();
133 Resource resource = Resource.newResource(_config);
134 try (InputStream in = resource.getInputStream())
135 {
136 properties.load(in);
137 }
138 _jdbcDriver = properties.getProperty("jdbcdriver");
139 _url = properties.getProperty("url");
140 _userName = properties.getProperty("username");
141 _password = properties.getProperty("password");
142 String _userTable = properties.getProperty("usertable");
143 _userTableKey = properties.getProperty("usertablekey");
144 String _userTableUserField = properties.getProperty("usertableuserfield");
145 _userTablePasswordField = properties.getProperty("usertablepasswordfield");
146 String _roleTable = properties.getProperty("roletable");
147 String _roleTableKey = properties.getProperty("roletablekey");
148 _roleTableRoleField = properties.getProperty("roletablerolefield");
149 String _userRoleTable = properties.getProperty("userroletable");
150 String _userRoleTableUserKey = properties.getProperty("userroletableuserkey");
151 String _userRoleTableRoleKey = properties.getProperty("userroletablerolekey");
152 _cacheTime = new Integer(properties.getProperty("cachetime"));
153
154 if (_jdbcDriver == null || _jdbcDriver.equals("")
155 || _url == null
156 || _url.equals("")
157 || _userName == null
158 || _userName.equals("")
159 || _password == null
160 || _cacheTime < 0)
161 {
162 LOG.warn("UserRealm " + getName() + " has not been properly configured");
163 }
164 _cacheTime *= 1000;
165 _lastHashPurge = 0;
166 _userSql = "select " + _userTableKey + "," + _userTablePasswordField + " from " + _userTable + " where " + _userTableUserField + " = ?";
167 _roleSql = "select r." + _roleTableRoleField
168 + " from "
169 + _roleTable
170 + " r, "
171 + _userRoleTable
172 + " u where u."
173 + _userRoleTableUserKey
174 + " = ?"
175 + " and r."
176 + _roleTableKey
177 + " = u."
178 + _userRoleTableRoleKey;
179
180 Loader.loadClass(this.getClass(), _jdbcDriver).newInstance();
181 super.doStart();
182 }
183
184
185
186 public String getConfig()
187 {
188 return _config;
189 }
190
191
192
193
194
195
196
197 public void setConfig(String config)
198 {
199 if (isRunning())
200 throw new IllegalStateException("Running");
201 _config=config;
202 }
203
204
205
206
207
208 public void connectDatabase()
209 {
210 try
211 {
212 Class.forName(_jdbcDriver);
213 _con = DriverManager.getConnection(_url, _userName, _password);
214 }
215 catch (SQLException e)
216 {
217 LOG.warn("UserRealm " + getName() + " could not connect to database; will try later", e);
218 }
219 catch (ClassNotFoundException e)
220 {
221 LOG.warn("UserRealm " + getName() + " could not connect to database; will try later", e);
222 }
223 }
224
225
226 @Override
227 public UserIdentity login(String username, Object credentials, ServletRequest request)
228 {
229 long now = System.currentTimeMillis();
230 if (now - _lastHashPurge > _cacheTime || _cacheTime == 0)
231 {
232 _users.clear();
233 _lastHashPurge = now;
234 closeConnection();
235 }
236
237 return super.login(username,credentials, request);
238 }
239
240
241 @Override
242 protected void loadUsers()
243 {
244 }
245
246
247 @Deprecated
248 protected UserIdentity loadUser(String username)
249 {
250 try
251 {
252 if (null == _con)
253 connectDatabase();
254
255 if (null == _con)
256 throw new SQLException("Can't connect to database");
257
258 try (PreparedStatement stat1 = _con.prepareStatement(_userSql))
259 {
260 stat1.setObject(1, username);
261 try (ResultSet rs1 = stat1.executeQuery())
262 {
263 if (rs1.next())
264 {
265 int key = rs1.getInt(_userTableKey);
266 String credentials = rs1.getString(_userTablePasswordField);
267
268
269 List<String> roles = new ArrayList<String>();
270
271 try (PreparedStatement stat2 = _con.prepareStatement(_roleSql))
272 {
273 stat2.setInt(1, key);
274 try (ResultSet rs2 = stat2.executeQuery())
275 {
276 while (rs2.next())
277 roles.add(rs2.getString(_roleTableRoleField));
278 }
279 }
280 return putUser(username, Credential.getCredential(credentials), roles.toArray(new String[roles.size()]));
281 }
282 }
283 }
284 }
285 catch (SQLException e)
286 {
287 LOG.warn("UserRealm " + getName() + " could not load user information from database", e);
288 closeConnection();
289 }
290 return null;
291 }
292
293
294
295
296
297 public KnownUser loadUserInfo (String username)
298 {
299 try
300 {
301 if (null == _con)
302 connectDatabase();
303
304 if (null == _con)
305 throw new SQLException("Can't connect to database");
306
307 try (PreparedStatement stat1 = _con.prepareStatement(_userSql))
308 {
309 stat1.setObject(1, username);
310 try (ResultSet rs1 = stat1.executeQuery())
311 {
312 if (rs1.next())
313 {
314 int key = rs1.getInt(_userTableKey);
315 String credentials = rs1.getString(_userTablePasswordField);
316
317 return new JDBCKnownUser (username, Credential.getCredential(credentials), key);
318 }
319 }
320 }
321 }
322 catch (SQLException e)
323 {
324 LOG.warn("UserRealm " + getName() + " could not load user information from database", e);
325 closeConnection();
326 }
327
328 return null;
329 }
330
331
332
333
334
335
336 public String[] loadRoleInfo (KnownUser user)
337 {
338 JDBCKnownUser jdbcUser = (JDBCKnownUser)user;
339
340 try
341 {
342 if (null == _con)
343 connectDatabase();
344
345 if (null == _con)
346 throw new SQLException("Can't connect to database");
347
348
349 List<String> roles = new ArrayList<String>();
350
351 try (PreparedStatement stat2 = _con.prepareStatement(_roleSql))
352 {
353 stat2.setInt(1, jdbcUser.getUserKey());
354 try (ResultSet rs2 = stat2.executeQuery())
355 {
356 while (rs2.next())
357 roles.add(rs2.getString(_roleTableRoleField));
358 return roles.toArray(new String[roles.size()]);
359 }
360 }
361 }
362 catch (SQLException e)
363 {
364 LOG.warn("UserRealm " + getName() + " could not load user information from database", e);
365 closeConnection();
366 }
367
368 return null;
369 }
370
371
372
373
374
375 private void closeConnection ()
376 {
377 if (_con != null)
378 {
379 if (LOG.isDebugEnabled()) LOG.debug("Closing db connection for JDBCUserRealm");
380 try { _con.close(); }catch (Exception e) {LOG.ignore(e);}
381 }
382 _con = null;
383 }
384 }