001: package dinamica.security;
002:
003: import dinamica.*;
004: import javax.sql.DataSource;
005: import java.sql.*;
006: import java.util.Date;
007: import java.util.Calendar;
008:
009: /**
010: * Execute the login and return an exit code:<br><br>
011: * 0 - OK<br>
012: * 1 - LOGIN FAILED<br>
013: * 3 - FORCE NEW PASSWORD<br>
014: * 4 - ACCOUNT LOCKED<br>
015: * <br><br>
016: * This Transaction provides the default login mechanism
017: * against a database based realm, according to the Dinamica
018: * security model database (s_user table).
019: * <br><br>
020: * The request must contain the parameters userlogin and passwd
021: * <br><br>
022: * (c) 2004 Martin Cordova<br>
023: * This code is released under the LGPL license<br>
024: * Dinamica Framework - http://www.martincordova.com
025: * @author Martin Cordova (dinamica@martincordova.com)
026: * */
027: public class Login extends GenericTransaction {
028:
029: /* (non-Javadoc)
030: * @see dinamica.GenericTransaction#service(dinamica.Recordset)
031: */
032: public int service(Recordset inputParams) throws Throwable {
033:
034: //default return code (login OK)
035: int rc = 0;
036:
037: //reuse superclass code
038: super .service(inputParams);
039:
040: //set request attributes in case of forward to another Action
041: getRequest().setAttribute("userlogin",
042: inputParams.getString("userlogin"));
043:
044: //get security datasource
045: String jndiName = (String) getContext().getAttribute(
046: "dinamica.security.datasource");
047: if (jndiName == null)
048: throw new Throwable(
049: "Context attribute [dinamica.security.datasource] is null, check your security filter configuration.");
050:
051: //get datasource and DB connection
052: DataSource ds = Jndi.getDataSource(jndiName);
053: Connection conn = ds.getConnection();
054: this .setConnection(conn);
055:
056: try {
057: //get db channel
058: Db db = getDb();
059:
060: //get sql for login
061: String sqlLogin = getSQL(getResource("login.sql"),
062: inputParams);
063:
064: //get user
065: Recordset rs1 = db.get(sqlLogin);
066:
067: //check result?
068: if (rs1.getRecordCount() == 0) {
069:
070: //get invalid password policy
071: String maxRetries = getConfig().getConfigValue(
072: "login-max-retries");
073: String sCounter = (String) getSession().getAttribute(
074: "dinamica.security.invalidlogins");
075: if (sCounter == null) {
076: sCounter = "1";
077: } else {
078: int i = Integer.parseInt(sCounter);
079: i++;
080: sCounter = String.valueOf(i);
081: int j = Integer.parseInt(maxRetries);
082:
083: //disable account?
084: if (i > j) {
085: String sql = getResource("disable.sql");
086: sql = getSQL(sql, inputParams);
087: db.exec(sql);
088: }
089: }
090:
091: getSession().setAttribute(
092: "dinamica.security.invalidlogins", sCounter);
093:
094: //failed
095: rc = 1;
096: } else {
097: //login ready - check password expiration
098: rs1.next();
099:
100: //save login history record
101: String sqlLog = getResource("insert-loginlog.sql");
102: sqlLog = getSQL(sqlLog, rs1);
103: db.exec(sqlLog);
104:
105: //save session record
106: /*
107: sqlLog = getResource("insert-session.sql");
108: sqlLog = StringUtil.replace(sqlLog, "${jsessionid}", getSession().getId());
109: sqlLog = getSQL(sqlLog, rs1);
110: db.exec(sqlLog);
111: */
112:
113: if (rs1.getInt("enabled") == 1) {
114:
115: int newpass = 0;
116: if (!rs1.isNull("force_newpass"))
117: newpass = rs1.getInt("force_newpass");
118:
119: //force password change?
120: if (newpass == 1) {
121: rc = 3;
122: } else {
123: //check if password has expired
124: String gpolicy = (String) getRequest()
125: .getAttribute(
126: "dinamica.security.passpolicy"); //get default policy
127: String sql1 = getSQL(
128: getResource("check-passdate.sql"), rs1);
129: Recordset rsPass = db.get(sql1, 1);
130: if (rsPass.getRecordCount() > 0) {
131: //use default or specific password expiration policy?
132: int policy = rs1.getInt("pwd_policy");
133: if (policy == -2)
134: policy = Integer.parseInt(gpolicy);
135:
136: //password never expires?
137: if (policy != -1) {
138: rsPass.next();
139: Date d = rsPass.getDate("last_change");
140: if (expired(d, policy))
141: rc = 3;
142: }
143:
144: }
145:
146: //login OK
147: if (rc == 0) {
148:
149: //get user preferences
150: getUserPrefs(db, rs1);
151:
152: //get user roles
153: String sqlRoles = getSQL(
154: getResource("roles.sql"), rs1);
155: Recordset rs2 = db.get(sqlRoles);
156:
157: String roles[] = new String[rs2
158: .getRecordCount()];
159: int i = 0;
160: while (rs2.next()) {
161: roles[i] = rs2.getString("rolename");
162: i++;
163: }
164:
165: //create user object
166: DinamicaUser user = new DinamicaUser(
167: inputParams.getString("userlogin"),
168: roles);
169:
170: //store user object into session attribute
171: getSession().setAttribute(
172: "dinamica.security.login", user);
173:
174: //set redirect URL
175: getRequest().setAttribute(
176: "dinamica.security.uri",
177: inputParams.getString("uri"));
178: }
179: }
180: } else {
181: //account locked or disabled
182: rc = 4;
183: }
184:
185: if (rc == 3) {
186: getSession().setAttribute("dinamica.userlogin",
187: inputParams.getString("userlogin"));
188: }
189:
190: }
191:
192: } catch (Throwable e) {
193: throw e;
194: } finally {
195: if (conn != null)
196: conn.close();
197: }
198:
199: return rc;
200:
201: }
202:
203: /**
204: * Determines if a password has expired
205: * @param d Date of password creation
206: * @param days Days after which the password expires
207: * @return
208: */
209: private boolean expired(java.util.Date d, int days) {
210:
211: boolean b = false;
212:
213: //set password creation date
214: Calendar c1 = Calendar.getInstance();
215: c1.setTime(d);
216:
217: //get today
218: Calendar c2 = Calendar.getInstance();
219:
220: //add N days to password
221: c1.add(Calendar.DATE, days);
222:
223: //check if today is after expiration date
224: if (c2.getTime().after(c1.getTime()))
225: b = true;
226:
227: return b;
228:
229: }
230:
231: /**
232: * Set session attributes containing user preferences
233: * like Locale and Stylesheet
234: * @param db Db channel
235: * @param user Recordset with user info after successful login
236: * @throws Throwable
237: */
238: public void getUserPrefs(Db db, Recordset user) throws Throwable {
239: java.util.Locale l = new java.util.Locale(user
240: .getString("locale"));
241: getSession().setAttribute("dinamica.user.locale", l);
242: }
243:
244: }
|