[Yanel-commits] rev 30327 - public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet

michi at wyona.com michi at wyona.com
Sun Jan 13 14:24:25 CET 2008


Author: michi
Date: 2008-01-13 14:24:23 +0100 (Sun, 13 Jan 2008)
New Revision: 30327

Modified:
   public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java
Log:
access control refactored such that auhentication is only called when access denied

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	2008-01-13 12:21:22 UTC (rev 30326)
+++ public/yanel/trunk/src/webapp/src/java/org/wyona/yanel/servlet/YanelServlet.java	2008-01-13 13:24:23 UTC (rev 30327)
@@ -185,7 +185,7 @@
         if(doAuthenticate(request, response) != null) return;
 
         // Check authorization
-        if(doAuthorize(request, response) != null) return;
+        if(doAccessControl(request, response) != null) return;
 
         // Check for requests for global data
         Resource resource = getResource(request, response);
@@ -1013,53 +1013,28 @@
     }
 
     /**
-     * Authorize request (and also authenticate for HTTP BASIC)
+     * Check authorization and if not authorized then authenticate
      */
-    private HttpServletResponse doAuthorize(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+    private HttpServletResponse doAccessControl(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
 
-        Usecase usecase = null;
+        // Get usecase
+        Usecase usecase = getUsecase(request);
 
-        // TODO: Replace hardcoded roles by mapping between roles amd query strings ...
-        String value = request.getParameter("yanel.resource.usecase");
-        String workflowTransitionValue = request.getParameter("yanel.resource.workflow.transition");
-        String contentType = request.getContentType();
-        String method = request.getMethod();
-        if (value != null && value.equals("save")) {
-            log.debug("Save data ...");
-            usecase = new Usecase("write");
-        } else if (value != null && value.equals("checkin")) {
-            log.debug("Checkin data ...");
-            usecase = new Usecase("write");
-        } else if (value != null && value.equals("introspection")) {
-            if(log.isDebugEnabled()) log.debug("Dynamically generated introspection ...");
-            usecase = new Usecase("introspection");
-        } else if (value != null && value.equals("checkout")) {
-            log.debug("Checkout data ...");
-            usecase = new Usecase("open");
-        } else if (contentType != null && contentType.indexOf("application/atom+xml") >= 0 && (method.equals(METHOD_PUT) || method.equals(METHOD_POST))) {
-            // TODO: Is posting atom entries different from a general post (see below)?!
-            log.error("DEBUG: Write/Checkin Atom entry ...");
-            usecase = new Usecase("write");
-        // TODO: METHOD_POST is not generally protected, but save, checkin, application/atom+xml are being protected. See doPost(.... 
-        } else if (method.equals(METHOD_PUT)) {
-            log.error("DEBUG: Upload data ...");
-            usecase = new Usecase("write");
-        } else if (method.equals(METHOD_DELETE)) {
-            log.error("DEBUG: Delete resource ...");
-            usecase = new Usecase("delete");
-        } else if (workflowTransitionValue != null) {
-            // TODO: How shall we protect workflow transitions?!
-            log.error("DEBUG: Workflow transition ...");
-            usecase = new Usecase("view");
-        } else {
-            usecase = new Usecase("view");
+        // Get identity
+        Identity identity = null;
+        try {
+            identity = getIdentity(request);
+            if (identity == null) {
+                if (log.isDebugEnabled()) log.debug("Identity is WORLD");
+                identity = new Identity();
+                // TBD: Should add world identity to the session?
+            }
+        } catch (Exception e) {
+            log.error(e, e);
+            throw new ServletException(e.getMessage());
         }
-        value = request.getParameter("yanel.toolbar");
-        if (value != null && value.equals("on")) {
-            log.debug("Turn on toolbar ...");
-            usecase = new Usecase("toolbar");
-        }
 
+        // Set some variables
         boolean authorized = false;
         Realm realm;
         String path;
@@ -1074,6 +1049,8 @@
 
         // HTTP BASIC Authorization (For clients such as for instance Sunbird, OpenOffice or cadaver)
         // IMPORT NOTE: BASIC Authentication needs to be checked on every request, because clients often do not support session handling
+
+/*
         String authorization = request.getHeader("Authorization");
         log.debug("Checking for Authorization Header: " + authorization);
         if (authorization != null) {
@@ -1128,21 +1105,12 @@
                 authorized = false;
             }
         }
+*/
 
 
-        // Custom Authorization
+        // Check Authorization
         try {
             log.debug("Do session based custom authorization");
-            //String[] groupnames = {"null", "null"};
-            HttpSession session = request.getSession(true);
-            Identity identity = getIdentity(request);
-            
-            if (identity == null) {
-                log.debug("Identity is WORLD");
-                identity = new Identity();
-                // TODO: should add world identity to the session?
-            }
-            
             if (log.isDebugEnabled()) log.debug("Check authorization: realm: " + realm + ", path: " + path + ", identity: " + identity.getUsername() + ", Usecase: " + usecase.getName());
             authorized = realm.getPolicyManager().authorize(path, identity, usecase);
             if (log.isDebugEnabled()) log.debug("Check authorization result: " + authorized);
@@ -1153,6 +1121,8 @@
 
 
         if(!authorized) {
+            // TODO: Implement HTTP BASIC/DIGEST response (see above)
+
             log.warn("Access denied: " + getRequestURLQS(request, null, false));
 
             if(!request.isSecure()) {
@@ -1847,6 +1817,60 @@
                 return (Identity)identityMap.get(realm.getID());
             }
         }
+
+        // HTTP BASIC Authentication (For clients such as for instance Sunbird, OpenOffice or cadaver)
+        // IMPORT NOTE: BASIC Authentication needs to be checked on every request, because clients often do not support session handling
+        String authorizationHeader = request.getHeader("Authorization");
+        if (log.isDebugEnabled()) log.debug("Checking for Authorization Header: " + authorizationHeader);
+        if (authorizationHeader != null) {
+            if (authorizationHeader.toUpperCase().startsWith("BASIC")) {
+                log.debug("Using BASIC authorization ...");
+                // Get encoded user and password, comes after "BASIC "
+                String userpassEncoded = authorizationHeader.substring(6);
+                // Decode it, using any base 64 decoder
+                sun.misc.BASE64Decoder dec = new sun.misc.BASE64Decoder();
+                String userpassDecoded = new String(dec.decodeBuffer(userpassEncoded));
+                log.debug("Username and Password Decoded: " + userpassDecoded);
+                String[] up = userpassDecoded.split(":");
+                String username = up[0];
+                String password = up[1];
+                log.debug("username: " + username + ", password: " + password);
+                try {
+                    User user = realm.getIdentityManager().getUserManager().getUser(username);
+                    if (user != null && user.authenticate(password)) {
+                        return new Identity(user);
+                    } else {
+                        log.warn("HTTP BASIC Authentication failed for " + username + "!");
+/*
+                        response.setHeader("WWW-Authenticate", "BASIC realm=\"" + realm.getName() + "\"");
+                        response.sendError(response.SC_UNAUTHORIZED);
+                        PrintWriter writer = response.getWriter();
+                        writer.print("BASIC Authentication Failed!");
+                        return response;
+*/
+                        return null;
+                    }
+                } catch (Exception e) {
+                    log.error(e.getMessage(), e);
+                    throw new ServletException(e.getMessage(), e);
+                }
+            } else if (authorizationHeader.toUpperCase().startsWith("DIGEST")) {
+                log.error("DIGEST is not implemented");
+/*
+                authorized = false;
+                response.sendError(response.SC_UNAUTHORIZED);
+                response.setHeader("WWW-Authenticate", "DIGEST realm=\"" + realm.getName() + "\"");
+                PrintWriter writer = response.getWriter();
+                writer.print("DIGEST is not implemented!");
+*/
+                return null;
+            } else {
+                log.warn("No such authorization type implemented: " + authorizationHeader);
+                return null;
+            }
+        }
+	
+        if(log.isDebugEnabled()) log.debug("No identity yet (neither session nor header based!");
         return null;
     }
 
@@ -2111,4 +2135,53 @@
         yanel.destroy();
         log.warn("Yanel webapp has been shut down.");
     }
+
+    /**
+     *
+     */
+    private Usecase getUsecase(HttpServletRequest request) {
+        Usecase usecase = null;
+
+        // TODO: Replace hardcoded roles by mapping between roles amd query strings ...
+        String value = request.getParameter("yanel.resource.usecase");
+        String workflowTransitionValue = request.getParameter("yanel.resource.workflow.transition");
+        String contentType = request.getContentType();
+        String method = request.getMethod();
+        if (value != null && value.equals("save")) {
+            log.debug("Save data ...");
+            usecase = new Usecase("write");
+        } else if (value != null && value.equals("checkin")) {
+            log.debug("Checkin data ...");
+            usecase = new Usecase("write");
+        } else if (value != null && value.equals("introspection")) {
+            if(log.isDebugEnabled()) log.debug("Dynamically generated introspection ...");
+            usecase = new Usecase("introspection");
+        } else if (value != null && value.equals("checkout")) {
+            log.debug("Checkout data ...");
+            usecase = new Usecase("open");
+        } else if (contentType != null && contentType.indexOf("application/atom+xml") >= 0 && (method.equals(METHOD_PUT) || method.equals(METHOD_POST))) {
+            // TODO: Is posting atom entries different from a general post (see below)?!
+            log.error("DEBUG: Write/Checkin Atom entry ...");
+            usecase = new Usecase("write");
+        // TODO: METHOD_POST is not generally protected, but save, checkin, application/atom+xml are being protected. See doPost(.... 
+        } else if (method.equals(METHOD_PUT)) {
+            log.error("DEBUG: Upload data ...");
+            usecase = new Usecase("write");
+        } else if (method.equals(METHOD_DELETE)) {
+            log.error("DEBUG: Delete resource ...");
+            usecase = new Usecase("delete");
+        } else if (workflowTransitionValue != null) {
+            // TODO: How shall we protect workflow transitions?!
+            log.error("DEBUG: Workflow transition ...");
+            usecase = new Usecase("view");
+        } else {
+            usecase = new Usecase("view");
+        }
+        value = request.getParameter("yanel.toolbar");
+        if (value != null && value.equals("on")) {
+            log.debug("Turn on toolbar ...");
+            usecase = new Usecase("toolbar");
+        }
+        return usecase;
+    }
 }



More information about the Yanel-commits mailing list