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 connectDatabase();
114 }
115
116
117
118
119
120
121 protected void loadConfig()
122 throws IOException
123 {
124 Properties properties = new Properties();
125
126 properties.load(getConfigResource().getInputStream());
127
128 _jdbcDriver = properties.getProperty("jdbcdriver");
129 _url = properties.getProperty("url");
130 _userName = properties.getProperty("username");
131 _password = properties.getProperty("password");
132 _userTable = properties.getProperty("usertable");
133 _userTableKey = properties.getProperty("usertablekey");
134 _userTableUserField = properties.getProperty("usertableuserfield");
135 _userTablePasswordField = properties.getProperty("usertablepasswordfield");
136 _roleTable = properties.getProperty("roletable");
137 _roleTableKey = properties.getProperty("roletablekey");
138 _roleTableRoleField = properties.getProperty("roletablerolefield");
139 _userRoleTable = properties.getProperty("userroletable");
140 _userRoleTableUserKey = properties.getProperty("userroletableuserkey");
141 _userRoleTableRoleKey = properties.getProperty("userroletablerolekey");
142
143 String cachetime = properties.getProperty("cachetime");
144 _cacheTime = cachetime!=null ? new Integer(cachetime).intValue() : 30;
145
146 if (_jdbcDriver == null || _jdbcDriver.equals("")
147 || _url == null || _url.equals("")
148 || _userName == null || _userName.equals("")
149 || _password == null
150 || _cacheTime < 0)
151 {
152 if(Log.isDebugEnabled())Log.debug("UserRealm " + getName()
153 + " has not been properly configured");
154 }
155 _cacheTime *= 1000;
156 _lastHashPurge = 0;
157 _userSql = "select " + _userTableKey + ","
158 + _userTablePasswordField + " from "
159 + _userTable + " where "
160 + _userTableUserField + " = ?";
161 _roleSql = "select r." + _roleTableRoleField
162 + " from " + _roleTable + " r, "
163 + _userRoleTable + " u where u."
164 + _userRoleTableUserKey + " = ?"
165 + " and r." + _roleTableKey + " = u."
166 + _userRoleTableRoleKey;
167 }
168
169
170 public void logout(Principal user)
171 {}
172
173
174
175
176 public void connectDatabase()
177 {
178 try
179 {
180 Class.forName(_jdbcDriver);
181 _con = DriverManager.getConnection(_url, _userName, _password);
182 }
183 catch(SQLException e)
184 {
185 Log.warn("UserRealm " + getName()
186 + " could not connect to database; will try later", e);
187 }
188 catch(ClassNotFoundException e)
189 {
190 Log.warn("UserRealm " + getName()
191 + " could not connect to database; will try later", e);
192 }
193 }
194
195
196 public Principal authenticate(String username,
197 Object credentials,
198 Request request)
199 {
200 synchronized (this)
201 {
202 long now = System.currentTimeMillis();
203 if (now - _lastHashPurge > _cacheTime || _cacheTime == 0)
204 {
205 _users.clear();
206 _roles.clear();
207 _lastHashPurge = now;
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 connectDatabase();
271 }
272 }
273 }