From a444205e81419d439635a9e0ff3382ae3f5d9947 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Tue, 25 Oct 2016 10:42:10 +0000 Subject: [PATCH] Fix HTTP sesison auth git-svn-id: https://svn.argeo.org/commons/trunk@9279 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../security/ui/rap/AnonymousEntryPoint.java | 2 +- .../argeo/cms/ui/AbstractCmsEntryPoint.java | 6 +- .../src/org/argeo/cms/auth/AuthConstants.java | 22 +-- .../src/org/argeo/cms/auth/CmsAuthUtils.java | 26 +++ .../cms/auth/HttpSessionLoginModule.java | 150 ++++++++++++------ .../argeo/cms/auth/NodeUserLoginModule.java | 4 +- .../argeo/cms/auth/SingleUserLoginModule.java | 2 +- .../argeo/cms/auth/UserAdminLoginModule.java | 95 ++++++----- .../argeo/cms/internal/kernel/DataHttp.java | 105 +++++++----- .../cms/internal/kernel/KernelUtils.java | 3 +- .../src/org/argeo/node/NodeConstants.java | 2 +- 11 files changed, 268 insertions(+), 149 deletions(-) diff --git a/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java b/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java index a169ce77a..5ff9e4093 100644 --- a/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java +++ b/org.argeo.cms.ui.workbench.rap/src/org/argeo/security/ui/rap/AnonymousEntryPoint.java @@ -56,7 +56,7 @@ public class AnonymousEntryPoint implements EntryPoint { final LoginContext loginContext; try { - loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, + loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject); loginContext.login(); } catch (LoginException e1) { diff --git a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java index 030b4104c..9f7811aa4 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/ui/AbstractCmsEntryPoint.java @@ -77,10 +77,10 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement loginContext.login(); } catch (CredentialNotFoundException e) { try { - loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS); + loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER); loginContext.login(); } catch (LoginException e1) { - throw new CmsException("Cannot log as anonymous", e); + throw new CmsException("Cannot log in as anonymous", e1); } } catch (LoginException e) { throw new CmsException("Cannot initialize subject", e); @@ -175,7 +175,7 @@ public abstract class AbstractCmsEntryPoint extends AbstractEntryPoint implement throw new CmsException("Login context should not be null"); try { loginContext.logout(); - LoginContext anonymousLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS); + LoginContext anonymousLc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER); anonymousLc.login(); authChange(anonymousLc); } catch (LoginException e) { diff --git a/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java b/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java index cd793332c..113e0830c 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java @@ -1,10 +1,10 @@ package org.argeo.cms.auth; import org.argeo.node.NodeConstants; -import org.osgi.service.http.HttpContext; /** Public properties of the CMS Kernel */ -public interface AuthConstants { +@Deprecated +interface AuthConstants { // LOGIN CONTEXTS /** * @deprecated Use {@link NodeConstants#LOGIN_CONTEXT_USER} instead @@ -13,7 +13,7 @@ public interface AuthConstants { /** * @deprecated Use {@link NodeConstants#LOGIN_CONTEXT_ANONYMOUS} instead */ - final static String LOGIN_CONTEXT_ANONYMOUS = NodeConstants.LOGIN_CONTEXT_ANONYMOUS; +// final static String LOGIN_CONTEXT_ANONYMOUS = NodeConstants.LOGIN_CONTEXT_ANONYMOUS; /** * @deprecated Use {@link NodeConstants#LOGIN_CONTEXT_DATA_ADMIN} instead */ @@ -24,11 +24,11 @@ public interface AuthConstants { final static String LOGIN_CONTEXT_SINGLE_USER = NodeConstants.LOGIN_CONTEXT_SINGLE_USER; // RESERVED ROLES - // public final static String ROLE_KERNEL = "OU=node"; - /** - * @deprecated Use {@link NodeConstants#ROLES_BASEDN} instead - */ - public final static String ROLES_BASEDN = NodeConstants.ROLES_BASEDN; + // public final static String ROLE_KERNEL = "OU=node"; + /** + * @deprecated Use {@link NodeConstants#ROLES_BASEDN} instead + */ + public final static String ROLES_BASEDN = NodeConstants.ROLES_BASEDN; /** * @deprecated Use {@link NodeConstants#ROLE_ADMIN} instead */ @@ -49,10 +49,4 @@ public interface AuthConstants { */ public final static String ROLE_ANONYMOUS = NodeConstants.ROLE_ANONYMOUS; - // SHARED STATE KEYS - // compatible with com.sun.security.auth.module.*LoginModule -// public static final String SHARED_STATE_USERNAME = "javax.security.auth.login.name"; -// public static final String SHARED_STATE_PASSWORD = "javax.security.auth.login.password"; - public static final String SHARED_STATE_AUTHORIZATION = HttpContext.AUTHORIZATION; - } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java index 86800e282..d8d7e8721 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/CmsAuthUtils.java @@ -14,13 +14,21 @@ import javax.security.auth.x500.X500Principal; import org.argeo.cms.CmsException; import org.argeo.cms.internal.auth.ImpliedByPrincipal; import org.argeo.node.security.AnonymousPrincipal; +import org.argeo.node.security.DataAdminPrincipal; import org.argeo.node.security.NodeSecurityUtils; import org.osgi.service.useradmin.Authorization; class CmsAuthUtils { + /** From org.osgi.service.http.HttpContext */ + static final String SHARED_STATE_AUTHORIZATION = "org.osgi.service.useradmin.authorization"; + /** From com.sun.security.auth.module.*LoginModule */ + static final String SHARED_STATE_NAME = "javax.security.auth.login.name"; + /** From com.sun.security.auth.module.*LoginModule */ + static final String SHARED_STATE_PWD = "javax.security.auth.login.password"; static void addAuthentication(Subject subject, Authorization authorization) { assert subject != null; + checkSubjectEmpty(subject); assert authorization != null; // required for display name: @@ -65,6 +73,17 @@ class CmsAuthUtils { } } + private static void checkSubjectEmpty(Subject subject) { + if (!subject.getPrincipals(AnonymousPrincipal.class).isEmpty()) + throw new IllegalStateException("Already logged in as anonymous: " + subject); + if (!subject.getPrincipals(X500Principal.class).isEmpty()) + throw new IllegalStateException("Already logged in as user: " + subject); + if (!subject.getPrincipals(DataAdminPrincipal.class).isEmpty()) + throw new IllegalStateException("Already logged in as data admin: " + subject); + if (!subject.getPrincipals(ImpliedByPrincipal.class).isEmpty()) + throw new IllegalStateException("Already authorized: " + subject); + } + static void cleanUp(Subject subject) { // Argeo subject.getPrincipals().removeAll(subject.getPrincipals(X500Principal.class)); @@ -74,6 +93,13 @@ class CmsAuthUtils { // subject.getPrincipals().removeAll(subject.getPrincipals(AnonymousPrincipal.class)); } + // SHARED STATE KEYS + // compatible with com.sun.security.auth.module.*LoginModule + // public static final String SHARED_STATE_USERNAME = + // "javax.security.auth.login.name"; + // public static final String SHARED_STATE_PASSWORD = + // "javax.security.auth.login.password"; + private CmsAuthUtils() { } diff --git a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java index 491acf9bc..da0fe2d46 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/HttpSessionLoginModule.java @@ -24,7 +24,7 @@ import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpContext; import org.osgi.service.useradmin.Authorization; -public class HttpSessionLoginModule implements LoginModule, AuthConstants { +public class HttpSessionLoginModule implements LoginModule { private final static Log log = LogFactory.getLog(HttpSessionLoginModule.class); private Subject subject = null; @@ -50,6 +50,8 @@ public class HttpSessionLoginModule implements LoginModule, AuthConstants { @Override public boolean login() throws LoginException { + if (callbackHandler == null) + return false; HttpRequestCallback httpCallback = new HttpRequestCallback(); try { callbackHandler.handle(new Callback[] { httpCallback }); @@ -61,57 +63,107 @@ public class HttpSessionLoginModule implements LoginModule, AuthConstants { request = httpCallback.getRequest(); if (request == null) return false; - authorization = checkHttp(); + authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION); + if (authorization == null) {// search by session ID + String httpSessionId = request.getSession().getId(); + // authorization = (Authorization) + // request.getSession().getAttribute(HttpContext.AUTHORIZATION); + // if (authorization == null) { + Collection> sr; + try { + sr = bc.getServiceReferences(WebCmsSession.class, + "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")"); + } catch (InvalidSyntaxException e) { + throw new CmsException("Cannot get CMS session for id " + httpSessionId, e); + } + if (sr.size() == 1) { + WebCmsSession cmsSession = bc.getService(sr.iterator().next()); + authorization = cmsSession.getAuthorization(); + if (log.isTraceEnabled()) + log.trace("Retrieved authorization from " + cmsSession); + } else if (sr.size() == 0) + authorization = null; + else + throw new CmsException(sr.size() + ">1 web sessions detected for http session " + httpSessionId); + + } if (authorization == null) return false; - sharedState.put(SHARED_STATE_AUTHORIZATION, authorization); + sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, authorization); return true; } - private Authorization checkHttp() { - Authorization authorization = null; - if (request != null) { - authorization = (Authorization) request.getAttribute(HttpContext.AUTHORIZATION); - if (authorization == null) { - String httpSessionId = request.getSession().getId(); - authorization = (Authorization) request.getSession().getAttribute(HttpContext.AUTHORIZATION); - if (authorization == null) { - Collection> sr; - try { - sr = bc.getServiceReferences(WebCmsSession.class, - "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")"); - } catch (InvalidSyntaxException e) { - throw new CmsException("Cannot get CMS session for id " + httpSessionId, e); - } - if (sr.size() == 1) { - WebCmsSession cmsSession = bc.getService(sr.iterator().next()); - authorization = cmsSession.getAuthorization(); - if (log.isTraceEnabled()) - log.trace("Retrieved authorization from " + cmsSession); - } else if (sr.size() == 0) - return null; - else - throw new CmsException( - sr.size() + ">1 web sessions detected for http session " + httpSessionId); - } - } - } - return authorization; - } + // private Authorization checkHttp() { + // Authorization authorization = null; + // if (request != null) { + // authorization = (Authorization) + // request.getAttribute(HttpContext.AUTHORIZATION); + // if (authorization == null) { + // String httpSessionId = request.getSession().getId(); + // authorization = (Authorization) + // request.getSession().getAttribute(HttpContext.AUTHORIZATION); + // if (authorization == null) { + // Collection> sr; + // try { + // sr = bc.getServiceReferences(WebCmsSession.class, + // "(" + WebCmsSession.CMS_SESSION_ID + "=" + httpSessionId + ")"); + // } catch (InvalidSyntaxException e) { + // throw new CmsException("Cannot get CMS session for id " + httpSessionId, + // e); + // } + // if (sr.size() == 1) { + // WebCmsSession cmsSession = bc.getService(sr.iterator().next()); + // authorization = cmsSession.getAuthorization(); + // if (log.isTraceEnabled()) + // log.trace("Retrieved authorization from " + cmsSession); + // } else if (sr.size() == 0) + // return null; + // else + // throw new CmsException( + // sr.size() + ">1 web sessions detected for http session " + + // httpSessionId); + // } + // } + // } + // return authorization; + // } @Override public boolean commit() throws LoginException { // TODO create CmsSession in another module + Authorization authorizationToRegister; if (authorization == null) { - authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION); + authorizationToRegister = (Authorization) sharedState.get(CmsAuthUtils.SHARED_STATE_AUTHORIZATION); } else { // this login module did the authorization CmsAuthUtils.addAuthentication(subject, authorization); + authorizationToRegister = authorization; } - if (authorization == null) { + if (authorizationToRegister == null) { return false; } if (request == null) return false; + HttpSessionId httpSessionId = registerAuthorization(request, authorizationToRegister); + if (subject.getPrivateCredentials(HttpSessionId.class).size() == 0) + subject.getPrivateCredentials().add(httpSessionId); + else { + String storedSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue(); + // if (storedSessionId.equals(httpSessionId.getValue())) + throw new LoginException( + "Subject already logged with session " + storedSessionId + " (not " + httpSessionId + ")"); + } + + if (authorization != null) { + // CmsAuthUtils.addAuthentication(subject, authorization); + cleanUp(); + return true; + } else { + cleanUp(); + return false; + } + } + + private HttpSessionId registerAuthorization(HttpServletRequest request, Authorization authorization) { String httpSessionId = request.getSession().getId(); if (authorization.getName() != null) { request.setAttribute(HttpContext.REMOTE_USER, authorization.getName()); @@ -143,32 +195,26 @@ public class HttpSessionLoginModule implements LoginModule, AuthConstants { if (log.isTraceEnabled()) log.trace("Added " + request.getServletPath() + " to " + cmsSession + " (" + request.getRequestURI() + ")"); - httpSession.setAttribute(HttpContext.REMOTE_USER, authorization.getName()); - httpSession.setAttribute(HttpContext.AUTHORIZATION, authorization); + // httpSession.setAttribute(HttpContext.REMOTE_USER, + // authorization.getName()); + // httpSession.setAttribute(HttpContext.AUTHORIZATION, + // authorization); } } - if (subject.getPrivateCredentials(HttpSessionId.class).size() == 0) - subject.getPrivateCredentials().add(new HttpSessionId(httpSessionId)); - else { - String storedSessionId = subject.getPrivateCredentials(HttpSessionId.class).iterator().next().getValue(); - if (storedSessionId.equals(httpSessionId)) - throw new LoginException( - "Subject already logged with session " + storedSessionId + " (not " + httpSessionId + ")"); - } - - if (authorization != null) { - CmsAuthUtils.addAuthentication(subject, authorization); - return true; - } else { - return false; - } + return new HttpSessionId(httpSessionId); } @Override public boolean abort() throws LoginException { + cleanUp(); return false; } + private void cleanUp() { + authorization = null; + request = null; + } + @Override public boolean logout() throws LoginException { String httpSessionId; diff --git a/org.argeo.cms/src/org/argeo/cms/auth/NodeUserLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/NodeUserLoginModule.java index 0b638bc2f..03dacef93 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/NodeUserLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/NodeUserLoginModule.java @@ -9,7 +9,7 @@ import javax.security.auth.spi.LoginModule; import org.osgi.service.useradmin.Authorization; -public class NodeUserLoginModule implements LoginModule, AuthConstants { +public class NodeUserLoginModule implements LoginModule { private Subject subject; private Map sharedState = null; @@ -55,7 +55,7 @@ public class NodeUserLoginModule implements LoginModule, AuthConstants { @Override public boolean commit() throws LoginException { - Authorization authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION); + Authorization authorization = (Authorization) sharedState.get(CmsAuthUtils.SHARED_STATE_AUTHORIZATION); if (authorization == null) throw new LoginException("Authorization should not be null"); CmsAuthUtils.addAuthentication(subject, authorization); diff --git a/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java index 6147fc77a..801e4af7c 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/SingleUserLoginModule.java @@ -14,7 +14,7 @@ import org.argeo.cms.internal.auth.ImpliedByPrincipal; import org.argeo.node.NodeConstants; import org.argeo.node.security.DataAdminPrincipal; -public class SingleUserLoginModule implements LoginModule, AuthConstants { +public class SingleUserLoginModule implements LoginModule { private Subject subject; @Override diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index 515f4dc0d..243eb0fec 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -24,12 +24,12 @@ import org.osgi.service.useradmin.Authorization; import org.osgi.service.useradmin.User; import org.osgi.service.useradmin.UserAdmin; -public class UserAdminLoginModule implements LoginModule, AuthConstants { +public class UserAdminLoginModule implements LoginModule { private Subject subject; private CallbackHandler callbackHandler; private Map sharedState = null; - private boolean isAnonymous = false; + // private boolean isAnonymous = false; // private state private BundleContext bc; @@ -46,8 +46,9 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants { // this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = (Map) sharedState; - if (options.containsKey("anonymous")) - isAnonymous = Boolean.parseBoolean(options.get("anonymous").toString()); + // if (options.containsKey("anonymous")) + // isAnonymous = + // Boolean.parseBoolean(options.get("anonymous").toString()); } catch (Exception e) { throw new CmsException("Cannot initialize login module", e); } @@ -55,10 +56,28 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants { @Override public boolean login() throws LoginException { + Authorization sharedAuth = (Authorization) sharedState.get(CmsAuthUtils.SHARED_STATE_AUTHORIZATION); + if (sharedAuth != null) { + if (callbackHandler == null && sharedAuth.getName() != null) + throw new LoginException("Shared authorization should be anonymous"); + return false; + } UserAdmin userAdmin = bc.getService(bc.getServiceReference(UserAdmin.class)); - if (isAnonymous) { + if (callbackHandler == null) {// anonymous authorization = userAdmin.getAuthorization(null); + sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, authorization); + return true; + } + + final String username; + final char[] password; + if (sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME) + && sharedState.containsKey(CmsAuthUtils.SHARED_STATE_PWD)) { + username = (String) sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); + password = (char[]) sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); + // TODO locale? } else { + // ask for username and password NameCallback nameCallback = new NameCallback("User"); PasswordCallback passwordCallback = new PasswordCallback("Password", false); @@ -80,39 +99,43 @@ public class UserAdminLoginModule implements LoginModule, AuthConstants { locale = Locale.getDefault(); UiContext.setLocale(locale); - authorization = (Authorization) sharedState.get(SHARED_STATE_AUTHORIZATION); - - if (authorization == null) { - // create credentials - final String username = nameCallback.getName(); - if (username == null || username.trim().equals("")) { - // authorization = userAdmin.getAuthorization(null); - throw new CredentialNotFoundException("No credentials provided"); - } else { - char[] password = {}; - if (passwordCallback.getPassword() != null) - password = passwordCallback.getPassword(); - else - throw new CredentialNotFoundException("No credentials provided"); - - User user = userAdmin.getUser(null, username); - if (user == null) - throw new FailedLoginException("Invalid credentials"); - if (!user.hasCredential(null, password)) - throw new FailedLoginException("Invalid credentials"); - // return false; - - // Log and monitor new login - // if (log.isDebugEnabled()) - // log.debug("Logged in to CMS with username [" + username + - // "]"); - - authorization = userAdmin.getAuthorization(user); - } + // authorization = (Authorization) + // sharedState.get(CmsAuthUtils.SHARED_STATE_AUTHORIZATION); + // + // if (authorization == null) { + // create credentials + username = nameCallback.getName(); + if (username == null || username.trim().equals("")) { + // authorization = userAdmin.getAuthorization(null); + throw new CredentialNotFoundException("No credentials provided"); } + // char[] password = {}; + if (passwordCallback.getPassword() != null) + password = passwordCallback.getPassword(); + else + throw new CredentialNotFoundException("No credentials provided"); } - if (!sharedState.containsKey(SHARED_STATE_AUTHORIZATION)) - sharedState.put(SHARED_STATE_AUTHORIZATION, authorization); + + // FIXME move Argeo specific convention from user admin to here + User user = userAdmin.getUser(null, username); + if (user == null) + throw new FailedLoginException("Invalid credentials"); + if (!user.hasCredential(null, password)) + throw new FailedLoginException("Invalid credentials"); + // return false; + + // Log and monitor new login + // if (log.isDebugEnabled()) + // log.debug("Logged in to CMS with username [" + username + + // "]"); + + authorization = userAdmin.getAuthorization(user); + assert authorization != null; + + // } + // if + // (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_AUTHORIZATION)) + sharedState.put(CmsAuthUtils.SHARED_STATE_AUTHORIZATION, authorization); return authorization != null; } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java index 469dfd2a7..acde18dc5 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/DataHttp.java @@ -22,7 +22,6 @@ import javax.security.auth.login.LoginException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; import org.apache.commons.codec.binary.Base64; import org.apache.commons.logging.Log; @@ -193,14 +192,14 @@ class DataHttp implements KernelConstants { throws IOException { // optimization - HttpSession httpSession = request.getSession(); - Object remoteUser = httpSession.getAttribute(REMOTE_USER); - Object authorization = httpSession.getAttribute(AUTHORIZATION); - if (remoteUser != null && authorization != null) { - request.setAttribute(REMOTE_USER, remoteUser); - request.setAttribute(AUTHORIZATION, authorization); - return true; - } + // HttpSession httpSession = request.getSession(); + // Object remoteUser = httpSession.getAttribute(REMOTE_USER); + // Object authorization = httpSession.getAttribute(AUTHORIZATION); + // if (remoteUser != null && authorization != null) { + // request.setAttribute(REMOTE_USER, remoteUser); + // request.setAttribute(AUTHORIZATION, authorization); + // return true; + // } // if (anonymous) { // Subject subject = KernelUtils.anonymousLogin(); @@ -213,17 +212,30 @@ class DataHttp implements KernelConstants { // if (log.isTraceEnabled()) // KernelUtils.logRequestHeaders(log, request); + LoginContext lc; try { - new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request)).login(); - return true; + lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, new HttpRequestCallbackHandler(request)); + lc.login(); + // return true; } catch (CredentialNotFoundException e) { - Subject subject = KernelUtils.anonymousLogin(); - authorization = subject.getPrivateCredentials(Authorization.class).iterator().next(); - request.setAttribute(REMOTE_USER, NodeConstants.ROLE_ANONYMOUS); - request.setAttribute(AUTHORIZATION, authorization); - httpSession.setAttribute(REMOTE_USER, NodeConstants.ROLE_ANONYMOUS); - httpSession.setAttribute(AUTHORIZATION, authorization); - return true; + try { + lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER); + lc.login(); + } catch (LoginException e1) { + if (log.isDebugEnabled()) + log.error("Cannot log in anonynous", e1); + return false; + } + // Subject subject = KernelUtils.anonymousLogin(); + // authorization = + // subject.getPrivateCredentials(Authorization.class).iterator().next(); + // request.setAttribute(REMOTE_USER, + // NodeConstants.ROLE_ANONYMOUS); + // request.setAttribute(AUTHORIZATION, authorization); + // httpSession.setAttribute(REMOTE_USER, + // NodeConstants.ROLE_ANONYMOUS); + // httpSession.setAttribute(AUTHORIZATION, authorization); + // return true; // CallbackHandler token = basicAuth(request); // if (token != null) { // try { @@ -245,6 +257,8 @@ class DataHttp implements KernelConstants { } catch (LoginException e) { throw new CmsException("Could not login", e); } + request.setAttribute(NodeConstants.LOGIN_CONTEXT_USER, lc); + return true; } @Override @@ -378,7 +392,20 @@ class DataHttp implements KernelConstants { if (log.isTraceEnabled()) log.trace("Login to workspace " + (workspace == null ? "" : workspace) + " in web session " + request.getSession().getId()); - return repository.login(workspace); + LoginContext lc = (LoginContext) request.getAttribute(NodeConstants.LOGIN_CONTEXT_USER); + if (lc == null) + throw new CmsException("No login context available"); + try { + return Subject.doAs(lc.getSubject(), new PrivilegedExceptionAction() { + @Override + public Session run() throws Exception { + return repository.login(workspace); + } + }); + } catch (PrivilegedActionException e) { + throw new CmsException("Cannot log in to JCR", e); + } + // return repository.login(workspace); } public void releaseSession(Session session) { @@ -404,25 +431,27 @@ class DataHttp implements KernelConstants { @Override protected void service(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { - try { - Subject subject = subjectFromRequest(request); - // TODO make it stronger, with eTags. - // if (CurrentUser.isAnonymous(subject) && - // request.getMethod().equals("GET")) { - // response.setHeader("Cache-Control", "no-transform, public, - // max-age=300, s-maxage=900"); - // } - - Subject.doAs(subject, new PrivilegedExceptionAction() { - @Override - public Void run() throws Exception { - WebdavServlet.super.service(request, response); - return null; - } - }); - } catch (PrivilegedActionException e) { - throw new CmsException("Cannot process webdav request", e.getException()); - } + WebdavServlet.super.service(request, response); + // try { + // Subject subject = subjectFromRequest(request); + // // TODO make it stronger, with eTags. + // // if (CurrentUser.isAnonymous(subject) && + // // request.getMethod().equals("GET")) { + // // response.setHeader("Cache-Control", "no-transform, public, + // // max-age=300, s-maxage=900"); + // // } + // + // Subject.doAs(subject, new PrivilegedExceptionAction() { + // @Override + // public Void run() throws Exception { + // WebdavServlet.super.service(request, response); + // return null; + // } + // }); + // } catch (PrivilegedActionException e) { + // throw new CmsException("Cannot process webdav request", + // e.getException()); + // } } } diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java index e0eb371b1..d9e09bba3 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java @@ -109,11 +109,12 @@ class KernelUtils implements KernelConstants { } // Security + @Deprecated static Subject anonymousLogin() { Subject subject = new Subject(); LoginContext lc; try { - lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_ANONYMOUS, subject); + lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, subject); lc.login(); return subject; } catch (LoginException e) { diff --git a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java index 566ae37d1..2a221abe8 100644 --- a/org.argeo.node.api/src/org/argeo/node/NodeConstants.java +++ b/org.argeo.node.api/src/org/argeo/node/NodeConstants.java @@ -67,7 +67,7 @@ public interface NodeConstants { * LOGIN CONTEXTS */ String LOGIN_CONTEXT_USER = "USER"; - String LOGIN_CONTEXT_ANONYMOUS = "ANONYMOUS"; +// String LOGIN_CONTEXT_ANONYMOUS = "ANONYMOUS"; String LOGIN_CONTEXT_DATA_ADMIN = "DATA_ADMIN"; String LOGIN_CONTEXT_SINGLE_USER = "SINGLE_USER"; -- 2.30.2