1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.mortbay.jetty.security;
17
18 import java.io.IOException;
19 import java.security.Principal;
20 import java.sql.Connection;
21 import java.sql.DriverManager;
22 import java.sql.PreparedStatement;
23 import java.sql.ResultSet;
24 import java.sql.SQLException;
25 import java.util.Properties;
26
27 import org.mortbay.jetty.Request;
28 import org.mortbay.log.Log;
29 import org.mortbay.resource.Resource;
30 import org.mortbay.util.Loader;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 public class JDBCUserRealm extends HashUserRealm implements UserRealm
57 {
58
59 private String _jdbcDriver;
60 private String _url;
61 private String _userName;
62 private String _password;
63 private String _userTable;
64 private String _userTableKey;
65 private String _userTableUserField;
66 private String _userTablePasswordField;
67 private String _roleTable;
68 private String _roleTableKey;
69 private String _roleTableRoleField;
70 private String _userRoleTable;
71 private String _userRoleTableUserKey;
72 private String _userRoleTableRoleKey;
73 private int _cacheTime;
74
75 private long _lastHashPurge;
76 private Connection _con;
77 private String _userSql;
78 private String _roleSql;
79
80
81
82
83 public JDBCUserRealm()
84 {
85 super();
86 }
87
88
89
90
91
92 public JDBCUserRealm(String name)
93 {
94 super(name);
95 }
96
97
98
99
100
101
102
103
104 public JDBCUserRealm(String name, String config)
105 throws IOException,
106 ClassNotFoundException,
107 InstantiationException,
108 IllegalAccessException
109 {
110 super(name);
111 setConfig(config);
112 Loader.loadClass(this.getClass(),_jdbcDriver).newInstance();
113 }
114
115
116
117
118
119
120 protected void loadConfig()
121 throws IOException
122 {
123 Properties properties = new Properties();
124
125 properties.load(getConfigResource().getInputStream());
126
127 _jdbcDriver = properties.getProperty("jdbcdriver");
128 _url = properties.getProperty("url");
129 _userName = properties.getProperty("username");
130 _password = properties.getProperty("password");
131 _userTable = properties.getProperty("usertable");
132 _userTableKey = properties.getProperty("usertablekey");
133 _userTableUserField = properties.getProperty("usertableuserfield");
134 _userTablePasswordField = properties.getProperty("usertablepasswordfield");
135 _roleTable = properties.getProperty("roletable");
136 _roleTableKey = properties.getProperty("roletablekey");
137 _roleTableRoleField = properties.getProperty("roletablerolefield");
138 _userRoleTable = properties.getProperty("userroletable");
139 _userRoleTableUserKey = properties.getProperty("userroletableuserkey");
140 _userRoleTableRoleKey = properties.getProperty("userroletablerolekey");
141
142 String cachetime = properties.getProperty("cachetime");
143 _cacheTime = cachetime!=null ? new Integer(cachetime).intValue() : 30;
144
145 if (_jdbcDriver == null || _jdbcDriver.equals("")
146 || _url == null || _url.equals("")
147 || _userName == null || _userName.equals("")
148 || _password == null
149 || _cacheTime < 0)
150 {
151 if(Log.isDebugEnabled())Log.debug("UserRealm " + getName()
152 + " has not been properly configured");
153 }
154 _cacheTime *= 1000;
155 _lastHashPurge = 0;
156 _userSql = "select " + _userTableKey + ","
157 + _userTablePasswordField + " from "
158 + _userTable + " where "
159 + _userTableUserField + " = ?";
160 _roleSql = "select r." + _roleTableRoleField
161 + " from " + _roleTable + " r, "
162 + _userRoleTable + " u where u."
163 + _userRoleTableUserKey + " = ?"
164 + " and r." + _roleTableKey + " = u."
165 + _userRoleTableRoleKey;
166 }
167
168
169 public void logout(Principal user)
170 {}
171
172
173
174
175 public void connectDatabase()
176 {
177 try
178 {
179 Class.forName(_jdbcDriver);
180 _con = DriverManager.getConnection(_url, _userName, _password);
181 }
182 catch(SQLException e)
183 {
184 Log.warn("UserRealm " + getName()
185 + " could not connect to database; will try later", e);
186 }
187 catch(ClassNotFoundException e)
188 {
189 Log.warn("UserRealm " + getName()
190 + " could not connect to database; will try later", e);
191 }
192 }
193
194
195 public Principal authenticate(String username,
196 Object credentials,
197 Request request)
198 {
199 synchronized (this)
200 {
201 long now = System.currentTimeMillis();
202 if (now - _lastHashPurge > _cacheTime || _cacheTime == 0)
203 {
204 _users.clear();
205 _roles.clear();
206 _lastHashPurge = now;
207 closeConnection();
208 }
209 Principal user = super.getPrincipal(username);
210 if (user == null)
211 {
212 loadUser(username);
213 user = super.getPrincipal(username);
214 }
215 }
216 return super.authenticate(username, credentials, request);
217 }
218
219
220
221
222
223
224
225 public synchronized boolean isUserInRole(Principal user, String roleName)
226 {
227 if(super.getPrincipal(user.getName())==null)
228 loadUser(user.getName());
229 return super.isUserInRole(user, roleName);
230 }
231
232
233
234
235
236 private void loadUser(String username)
237 {
238 try
239 {
240 if (null==_con)
241 connectDatabase();
242
243 if (null==_con)
244 throw new SQLException("Can't connect to database");
245
246 PreparedStatement stat = _con.prepareStatement(_userSql);
247 stat.setObject(1, username);
248 ResultSet rs = stat.executeQuery();
249
250 if (rs.next())
251 {
252 int key = rs.getInt(_userTableKey);
253 put(username, rs.getString(_userTablePasswordField));
254 stat.close();
255
256 stat = _con.prepareStatement(_roleSql);
257 stat.setInt(1, key);
258 rs = stat.executeQuery();
259
260 while (rs.next())
261 addUserToRole(username, rs.getString(_roleTableRoleField));
262
263 stat.close();
264 }
265 }
266 catch (SQLException e)
267 {
268 Log.warn("UserRealm " + getName()
269 + " could not load user information from database", e);
270 closeConnection();
271 }
272 }
273
274
275
276
277 private void closeConnection ()
278 {
279 if (_con != null)
280 {
281 if (Log.isDebugEnabled()) Log.debug("Closing db connection for JDBCUserRealm");
282 try { _con.close(); }catch (Exception e) {Log.ignore(e);}
283 }
284 _con = null;
285 }
286 }