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 org.eclipse.jetty.server.UserIdentity;
33 import org.eclipse.jetty.util.Loader;
34 import org.eclipse.jetty.util.log.Log;
35 import org.eclipse.jetty.util.log.Logger;
36 import org.eclipse.jetty.util.resource.Resource;
37 import org.eclipse.jetty.util.security.Credential;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 public class JDBCLoginService extends MappedLoginService
62 {
63 private static final Logger LOG = Log.getLogger(JDBCLoginService.class);
64
65 protected String _config;
66 protected String _jdbcDriver;
67 protected String _url;
68 protected String _userName;
69 protected String _password;
70 protected String _userTableKey;
71 protected String _userTablePasswordField;
72 protected String _roleTableRoleField;
73 protected int _cacheTime;
74 protected long _lastHashPurge;
75 protected Connection _con;
76 protected String _userSql;
77 protected String _roleSql;
78
79
80
81 public JDBCLoginService()
82 throws IOException
83 {
84 }
85
86
87 public JDBCLoginService(String name)
88 throws IOException
89 {
90 setName(name);
91 }
92
93
94 public JDBCLoginService(String name, String config)
95 throws IOException
96 {
97 setName(name);
98 setConfig(config);
99 }
100
101
102 public JDBCLoginService(String name, IdentityService identityService, String config)
103 throws IOException
104 {
105 setName(name);
106 setIdentityService(identityService);
107 setConfig(config);
108 }
109
110
111
112
113
114
115 @Override
116 protected void doStart() throws Exception
117 {
118 Properties properties = new Properties();
119 Resource resource = Resource.newResource(_config);
120 try (InputStream in = resource.getInputStream())
121 {
122 properties.load(in);
123 }
124 _jdbcDriver = properties.getProperty("jdbcdriver");
125 _url = properties.getProperty("url");
126 _userName = properties.getProperty("username");
127 _password = properties.getProperty("password");
128 String _userTable = properties.getProperty("usertable");
129 _userTableKey = properties.getProperty("usertablekey");
130 String _userTableUserField = properties.getProperty("usertableuserfield");
131 _userTablePasswordField = properties.getProperty("usertablepasswordfield");
132 String _roleTable = properties.getProperty("roletable");
133 String _roleTableKey = properties.getProperty("roletablekey");
134 _roleTableRoleField = properties.getProperty("roletablerolefield");
135 String _userRoleTable = properties.getProperty("userroletable");
136 String _userRoleTableUserKey = properties.getProperty("userroletableuserkey");
137 String _userRoleTableRoleKey = properties.getProperty("userroletablerolekey");
138 _cacheTime = new Integer(properties.getProperty("cachetime"));
139
140 if (_jdbcDriver == null || _jdbcDriver.equals("")
141 || _url == null
142 || _url.equals("")
143 || _userName == null
144 || _userName.equals("")
145 || _password == null
146 || _cacheTime < 0)
147 {
148 LOG.warn("UserRealm " + getName() + " has not been properly configured");
149 }
150 _cacheTime *= 1000;
151 _lastHashPurge = 0;
152 _userSql = "select " + _userTableKey + "," + _userTablePasswordField + " from " + _userTable + " where " + _userTableUserField + " = ?";
153 _roleSql = "select r." + _roleTableRoleField
154 + " from "
155 + _roleTable
156 + " r, "
157 + _userRoleTable
158 + " u where u."
159 + _userRoleTableUserKey
160 + " = ?"
161 + " and r."
162 + _roleTableKey
163 + " = u."
164 + _userRoleTableRoleKey;
165
166 Loader.loadClass(this.getClass(), _jdbcDriver).newInstance();
167 super.doStart();
168 }
169
170
171
172 public String getConfig()
173 {
174 return _config;
175 }
176
177
178
179
180
181
182
183 public void setConfig(String config)
184 {
185 if (isRunning())
186 throw new IllegalStateException("Running");
187 _config=config;
188 }
189
190
191
192
193
194 public void connectDatabase()
195 {
196 try
197 {
198 Class.forName(_jdbcDriver);
199 _con = DriverManager.getConnection(_url, _userName, _password);
200 }
201 catch (SQLException e)
202 {
203 LOG.warn("UserRealm " + getName() + " could not connect to database; will try later", e);
204 }
205 catch (ClassNotFoundException e)
206 {
207 LOG.warn("UserRealm " + getName() + " could not connect to database; will try later", e);
208 }
209 }
210
211
212 @Override
213 public UserIdentity login(String username, Object credentials)
214 {
215 long now = System.currentTimeMillis();
216 if (now - _lastHashPurge > _cacheTime || _cacheTime == 0)
217 {
218 _users.clear();
219 _lastHashPurge = now;
220 closeConnection();
221 }
222
223 return super.login(username,credentials);
224 }
225
226
227 @Override
228 protected void loadUsers()
229 {
230 }
231
232
233 @Override
234 protected UserIdentity loadUser(String username)
235 {
236 try
237 {
238 if (null == _con)
239 connectDatabase();
240
241 if (null == _con)
242 throw new SQLException("Can't connect to database");
243
244 try (PreparedStatement stat1 = _con.prepareStatement(_userSql))
245 {
246 stat1.setObject(1, username);
247 try (ResultSet rs1 = stat1.executeQuery())
248 {
249 if (rs1.next())
250 {
251 int key = rs1.getInt(_userTableKey);
252 String credentials = rs1.getString(_userTablePasswordField);
253 List<String> roles = new ArrayList<String>();
254
255 try (PreparedStatement stat2 = _con.prepareStatement(_roleSql))
256 {
257 stat2.setInt(1, key);
258 try (ResultSet rs2 = stat2.executeQuery())
259 {
260 while (rs2.next())
261 roles.add(rs2.getString(_roleTableRoleField));
262 }
263 }
264 return putUser(username, Credential.getCredential(credentials),roles.toArray(new String[roles.size()]));
265 }
266 }
267 }
268 }
269 catch (SQLException e)
270 {
271 LOG.warn("UserRealm " + getName() + " could not load user information from database", e);
272 closeConnection();
273 }
274 return null;
275 }
276
277
278
279
280 private void closeConnection ()
281 {
282 if (_con != null)
283 {
284 if (LOG.isDebugEnabled()) LOG.debug("Closing db connection for JDBCUserRealm");
285 try { _con.close(); }catch (Exception e) {LOG.ignore(e);}
286 }
287 _con = null;
288 }
289
290 }