[Yanel-commits] rev 59197 - in public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet: . security/impl
michi at wyona.com
michi at wyona.com
Wed Jul 6 12:00:38 CEST 2011
Author: michi
Date: 2011-07-06 12:00:37 +0200 (Wed, 06 Jul 2011)
New Revision: 59197
Modified:
public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java
public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/AutoLogin.java
public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/DefaultWebAuthenticatorImpl.java
Log:
thanks to Balz auto login is now improved and functional as a prototype
Modified: public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java
===================================================================
--- public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java 2011-07-06 09:03:39 UTC (rev 59196)
+++ public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java 2011-07-06 10:00:37 UTC (rev 59197)
@@ -237,9 +237,18 @@
String yanelUsecase = request.getParameter(YANEL_USECASE);
if(yanelUsecase != null && yanelUsecase.equals("logout")) {
- AutoLogin.removeCookie(request, response);
+ try {
+ log.warn("DEBUG: Disable auto login...");
+ AutoLogin.disableAutoLogin(request, response, getRealm(request).getRepository());
+ } catch (Exception e) {
+ log.error("Exception while disabling auto login: " + e.getMessage(), e);
+ }
// INFO: Logout from Yanel
- if(doLogout(request, response) != null) return;
+ if(doLogout(request, response)) {
+ return;
+ } else {
+ log.error("Logout failed!");
+ }
} else if(yanelUsecase != null && yanelUsecase.equals("create")) { // TODO: Why does that not go through access control?
// INFO: Create a new resource
if(doCreate(request, response) != null) return;
@@ -1071,17 +1080,24 @@
throw new ServletException(e.getMessage(), e);
}
- // Auto-Login
+ // Try Auto-Login
if (identity == null || (identity != null && identity.isWorld())) {
- Cookie autoLoginCookie = AutoLogin.getCookie(request);
- if (autoLoginCookie != null) {
- try {
- if (AutoLogin.matchCookie(autoLoginCookie, realm.getRepository())) {
- // TODO: login
+ //log.debug("Not logged in yet, hence try auto login...");
+ try {
+ if (AutoLogin.tryAutoLogin(request, response, realm)) {
+ log.debug("Auto login successful, hence set identity inside session...");
+ String username = AutoLogin.getUsername(request);
+ if (username != null) {
+ User user = realm.getIdentityManager().getUserManager().getUser(username);
+ setIdentity(new Identity(user, user.getEmail()), request.getSession(), realm);
+ } else {
+ log.error("Auto login successful, but no username available!");
}
- } catch(Exception e) {
- log.error(e, e);
+ } else {
+ //log.debug("No auto login.");
}
+ } catch(Exception e) {
+ log.error(e, e);
}
}
@@ -1404,9 +1420,9 @@
/**
* Do logout
- * @return null for a regular logout and a Neutron response if auth scheme is Neutron
+ * @return true if logout was successful (and set a "Redirect response" for a regular logout and a "Neutron response" if auth scheme is Neutron)
*/
- private HttpServletResponse doLogout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ private boolean doLogout(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
if (yanelUI.isToolbarEnabled(request)) {
// TODO: Check if WORLD has access to the toolbar
@@ -1435,7 +1451,7 @@
response.setStatus(HttpServletResponse.SC_OK);
PrintWriter writer = response.getWriter();
writer.print("Neutron Logout Successful!");
- return response;
+ return true;
}
if (log.isDebugEnabled()) log.debug("Regular Logout Successful!");
@@ -1458,9 +1474,9 @@
response.setHeader("Location", urlWithoutLogoutQS.toString());
response.setStatus(javax.servlet.http.HttpServletResponse.SC_MOVED_PERMANENTLY); // 301
- return response;
+ return true;
} catch (Exception e) {
- log.error(e.getMessage(), e);
+ log.error(e, e);
throw new ServletException(e.getMessage(), e);
}
}
Modified: public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/AutoLogin.java
===================================================================
--- public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/AutoLogin.java 2011-07-06 09:03:39 UTC (rev 59196)
+++ public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/AutoLogin.java 2011-07-06 10:00:37 UTC (rev 59197)
@@ -1,5 +1,8 @@
package org.wyona.yanel.servlet.security.impl;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
import java.util.UUID;
import javax.servlet.http.Cookie;
@@ -7,25 +10,167 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.wyona.commons.xml.XMLHelper;
+import org.wyona.yanel.core.Environment;
+import org.wyona.yanel.core.map.Realm;
+import org.wyona.yanel.core.util.YarepUtil;
+import org.wyona.yarep.core.Node;
+import org.wyona.yarep.core.Repository;
/**
* Utility class in order to support auto login
*/
public class AutoLogin {
-
+
private static Logger log = Logger.getLogger(AutoLogin.class);
private static final String COOKIE_NAME = "YANELAUTOLOGIN";
private static final String SEP = "___";
+
+ private static final String NAMESPACE = "http://www.wyona.org/yanel/1.0";
+ private static final String BASEDIR = "/autologin-tokens/";
+ private static final String EXPIRES_FORMAT = "yyyyMMdd.HH.mm.ss";
+ private static final SimpleDateFormat expiresSdf = new SimpleDateFormat(EXPIRES_FORMAT);
+ private static final String XML_ATTR_USERNAME = "username";
+ private static final String XML_ATTR_EXPIRES = "expires";
+ private static final String XML_ATTR_TOKEN = "token";
+
+ // With the following two parameters you can define after what time a token gets replaced.
+ // However: this expiry date is only verified and maybe replaced if the user starts a new session.
+ // Means: if the session timeout is 4h and you configure here 30min, the cookie token won't be replaced within the session.
+ private static final int TOKEN_EXPIRY_UNIT = Calendar.MINUTE;
+ private static final int TOKEN_EXPIRY_AMOUNT = 30;
/**
- * Set cookie
+ * Disable Auto Login feature (deletes cookie)
*/
- public static Cookie setCookie(String username, HttpServletRequest request, HttpServletResponse response) {
+ public static void disableAutoLogin(HttpServletRequest request, HttpServletResponse response, Repository repo) {
+ Cookie currentCookie = getCookie(request);
+ if (currentCookie != null) {
+ deleteToken(repo, getYarepPath(getUsername(currentCookie), getToken(currentCookie)));
+
+ log.warn("DEBUG: Remove auto login cookie...");
+ Cookie newCookie = new Cookie(COOKIE_NAME, null);
+ newCookie.setMaxAge(0); // INFO: A zero value tells the browser to delete the cookie immediately.
+ response.addCookie(newCookie);
+ } else {
+ log.warn("No auto login cookie to delete!");
+ }
+ }
+
+ /**
+ *
+ */
+ public static void enableAutoLogin(String username, HttpServletResponse response, Realm realm) {
+ try {
+ //set cookie
+ Cookie cookie = setNewCookie(username, response);
+ //save token
+ saveToken(cookie, realm.getRepository());
+ } catch (Exception e) {
+ log.fatal("Could not enable Auto Login feature! Exception: "+e,e);
+ }
+ }
+
+ public static String getUsername(HttpServletRequest request) {
+ return getUsername(getCookie(request));
+ }
+
+ /**
+ * This method checks whether the current user should get logged in automatically based on an existing auto login cookie
+ * @param request HTTP request
+ * @return true means that this user can be logged in automatically.
+ */
+ public static boolean existsAutoLoginCookie(HttpServletRequest request) {
+ try {
+ Cookie cookie = getCookie(request);
+ if (cookie != null) {
+ return true;
+ } else {
+ //log.debug("No auto login cookie exists yet.");
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("Can not find out whether to perform auto login or not! Exception message : " + e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * This method checks whether the current user should get logged in automatically based on the cookie information and the persisted token and if so, then does the auto login
+ * @param request
+ * @param response
+ * @param realm
+ * @return true means that this user can be logged in automatically.
+ */
+ public static boolean tryAutoLogin(HttpServletRequest request, HttpServletResponse response, Realm realm) {
+ try {
+ Cookie cookie = getCookie(request);
+ if (cookie != null) {
+ log.debug("Checking Autologin Cookie");
+ String username = getUsername(cookie);
+ String token = getToken(cookie);
+ if (username != null && token != null) {
+ String yarepPath = getYarepPath(username, token);
+ log.debug("Checking node "+yarepPath);
+ Node node = null;
+ try {
+ node = realm.getRepository().getNode(yarepPath);
+ } catch (Exception e) {
+ log.warn("node '"+yarepPath+"' does not exist");
+ log.warn("We did not login the user automatically although auto login cookie seems to exist!");
+ return false;
+ }
+
+ if (node != null) {
+ Document doc = XMLHelper.readDocument(node.getInputStream());
+ Element el = (Element)doc.getElementsByTagNameNS(NAMESPACE, XML_ATTR_TOKEN).item(0);
+ String savedUsername = el.getAttribute(XML_ATTR_USERNAME);
+ String savedToken = el.getAttribute("value");
+ String expiryString = el.getAttribute(XML_ATTR_EXPIRES);
+ log.debug("Retrieved username '"+username+"' and token '"+savedToken+"' from saved Token");
+ if (username.equals(savedUsername) && token.equals(savedToken)) {
+ log.debug("retrieved cookie matches for user '"+username+"'");
+ if (hasTokenExpired(expiryString)) {
+ Cookie newCookie = setNewCookie(username, response);
+ saveToken(newCookie, realm.getRepository());
+ deleteToken(realm.getRepository(), yarepPath);
+ log.debug("Token was expired and has been renewed now.");
+ }
+ return true;
+ } else {
+ log.warn("Username/Token did no match (" + username + ", " + token + "), hence about auto login");
+ return false;
+ }
+ } else {
+ log.warn("No persistent yarep node containing username/token!");
+ return false;
+ }
+ } else {
+ log.warn("No username/token inside auto login cookie!");
+ return false;
+ }
+ } else {
+ //log.debug("No auto login cookie exists yet.");
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("Can not find out whether to perform auto login or not! Exception message: " + e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * Set cookie in response
+ */
+ private static Cookie setNewCookie(String username, HttpServletResponse response) {
Cookie result = null;
if (username != null) {
String token = UUID.randomUUID().toString();
Cookie cookie = new Cookie(COOKIE_NAME,token+SEP+username);
cookie.setMaxAge(Integer.MAX_VALUE);
+ cookie.setPath("/");
response.addCookie(cookie);
result = cookie;
}
@@ -33,22 +178,21 @@
}
/**
- * Get cookie
+ * Get specific auto login cookie
*/
- public static Cookie getCookie(HttpServletRequest request) {
+ private static Cookie getCookie(HttpServletRequest request) {
Cookie result = null;
try {
Cookie[] cookies = request.getCookies();
if (cookies != null) {
- for (Cookie c : cookies) {
+ for (Cookie c : request.getCookies()) {
if (c.getName().equals(COOKIE_NAME)) {
result = c;
break;
}
}
- } else {
- log.warn("DEBUG: No cookies by browser provided yet!");
}
+
} catch (Exception e) {
log.error("Error in retrieving cookie from request");
log.error(e,e);
@@ -56,19 +200,14 @@
return result;
}
-
- public static String getUsername(HttpServletRequest request) {
+
+ /**
+ * Get username from cookie
+ * @param cookie Auto login cookie
+ */
+ private static String getUsername(Cookie cookie) {
String result = null;
- Cookie cookie = getCookie(request);
if (cookie != null) {
- result = getUsername(cookie);
- }
- return result;
- }
-
- public static String getUsername(Cookie cookie) {
- String result = null;
- if (cookie != null) {
try {
result = cookie.getValue();
result = result.substring(result.lastIndexOf(SEP)+SEP.length());
@@ -80,18 +219,9 @@
return result;
}
- public static String getToken(HttpServletRequest request) {
+ private static String getToken(Cookie cookie) {
String result = null;
- Cookie cookie = getCookie(request);
if (cookie != null) {
- result = getToken(cookie);
- }
- return result;
- }
-
- public static String getToken(Cookie cookie) {
- String result = null;
- if (cookie != null) {
try {
result = cookie.getValue();
result = result.substring(0, result.lastIndexOf(SEP));
@@ -104,26 +234,75 @@
}
/**
- * Remove cookie
+ * Save auto login token persistently
*/
- public static void removeCookie(HttpServletRequest request, HttpServletResponse response) {
- Cookie cookie = new Cookie(COOKIE_NAME,"");
- cookie.setMaxAge(0);
- response.addCookie(cookie);
+ private static void saveToken(Cookie cookie, Repository repo) {
+ String username = getUsername(cookie);
+ String token = getToken(cookie);
+ if (username != null && token != null) {
+ String yarepPath = getYarepPath(username, token);
+ Document doc = XMLHelper.createDocument(NAMESPACE, "root");
+ Element el = doc.createElementNS(NAMESPACE, XML_ATTR_TOKEN);
+ el.setAttribute("value", token);
+ el.setAttribute(XML_ATTR_USERNAME, username);
+ el.setAttribute(XML_ATTR_EXPIRES, getExpiryString());
+ doc.getDocumentElement().appendChild(el);
+
+ // try to delete node if it exists
+ deleteToken(repo, yarepPath);
+
+ // save the token
+ try {
+ Node node = YarepUtil.addNodes(repo, yarepPath, org.wyona.yarep.core.NodeType.RESOURCE);
+ XMLHelper.writeDocument(doc, node.getOutputStream());
+ log.debug("Autologin Token saved at "+yarepPath);
+ } catch (Exception e) {
+ log.error("Could not save token for Auto-Login. Exception: "+e,e);
+ }
+ }
}
+
+ private static String getExpiryString() {
+ String result = null;
+ try {
+ Calendar cal = Calendar.getInstance();
+ cal.add(TOKEN_EXPIRY_UNIT, TOKEN_EXPIRY_AMOUNT);
+ result = expiresSdf.format(cal.getTime());
+
+ } catch (Exception e) {
+ log.error("Can not calculate expiry date! Exception: "+e,e);
+ }
+ return result;
+ }
+
+ private static boolean hasTokenExpired(String expiryString) {
+ boolean result = true;
+ try {
+ if (expiryString != null) {
+ Date expiryDate = expiresSdf.parse(expiryString);
+ if (expiryDate.before(new Date())) {
+ result = true;
+ } else {
+ result = false;
+ }
+ }
+ } catch (Exception e) {
+ log.error("Can not parse the expirydate '"+expiryString+"' from the token XML! Exception: "+e,e);
+ }
+ return result;
+ }
- /**
- * Save auto login token persistently
- */
- public static void saveToken(Cookie cookie, org.wyona.yarep.core.Repository repo) {
- // TODO
+ private static void deleteToken(Repository repo, String yarepPath) {
+ try {
+ if (repo.existsNode(yarepPath)) {
+ repo.getNode(yarepPath).delete();
+ }
+ } catch (Exception e) {
+ // we could log an exception here but deletion is not that important, so we skip the logging.
+ }
}
- /**
- * Check whether cookie and token match
- */
- public static boolean matchCookie(Cookie cookie, org.wyona.yarep.core.Repository repo) {
- // TODO
- return false;
+ private static String getYarepPath(String username, String tokenID) {
+ return BASEDIR+username+"-tokens/"+tokenID+".xml";
}
}
Modified: public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/DefaultWebAuthenticatorImpl.java
===================================================================
--- public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/DefaultWebAuthenticatorImpl.java 2011-07-06 09:03:39 UTC (rev 59196)
+++ public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/security/impl/DefaultWebAuthenticatorImpl.java 2011-07-06 10:00:37 UTC (rev 59197)
@@ -610,9 +610,12 @@
log.warn("TODO: Implement auto-login");
// Set auto login cookie containing username and secure token, whereas create new secure token per session
// Implement this as utility method such that it can be re-used independent of the default authenticator!
+ AutoLogin.enableAutoLogin(loginUsername, response, realm);
+/*
Cookie autoLoginCookie = AutoLogin.setCookie(loginUsername, request, response); // TODO: What about openID?!
//AutoLogin.saveToken(autoLoginCookie, realm.getIdentityManager().getUserManager());
AutoLogin.saveToken(autoLoginCookie, realm.getRepository());
+*/
return true;
} else {
log.debug("Ignore auto login...");
More information about the Yanel-commits
mailing list