From a39d87eb3956b92ac6c985dc31c22818eaf7919d Mon Sep 17 00:00:00 2001 From: Timm Fitschen <timm.fitschen@ds.mpg.de> Date: Mon, 19 Nov 2018 16:32:35 +0100 Subject: [PATCH] ADD anonymous user --- .../java/caosdb/datetime/UTCDateTime.java | 3 +++ .../java/caosdb/server/CaosAuthenticator.java | 25 ++++++++----------- src/main/java/caosdb/server/CaosDBServer.java | 6 +++-- .../java/caosdb/server/ServerProperties.java | 1 + .../accessControl/AuthenticationUtils.java | 3 +++ .../accessControl/CaosDBAuthorizingRealm.java | 13 ++++++---- .../accessControl/CaosDBDefaultRealm.java | 5 +--- .../accessControl/SessionTokenRealm.java | 9 +------ .../server/accessControl/UserSources.java | 15 +++++++++-- .../caosdb/server/permissions/EntityACL.java | 5 +++- .../AbstractCaosDBServerResource.java | 3 ++- .../server/transaction/Transaction.java | 7 ++++-- 12 files changed, 55 insertions(+), 40 deletions(-) diff --git a/src/main/java/caosdb/datetime/UTCDateTime.java b/src/main/java/caosdb/datetime/UTCDateTime.java index 4da38a4f..3b07af14 100644 --- a/src/main/java/caosdb/datetime/UTCDateTime.java +++ b/src/main/java/caosdb/datetime/UTCDateTime.java @@ -213,6 +213,9 @@ public class UTCDateTime implements Interval { // june 2015 addLeapSecond(2015, 06, 30); + + // dec 2016 + addLeapSecond(2016, 12, 31); } public long getUTCSeconds() { diff --git a/src/main/java/caosdb/server/CaosAuthenticator.java b/src/main/java/caosdb/server/CaosAuthenticator.java index 87290564..ed3646a0 100644 --- a/src/main/java/caosdb/server/CaosAuthenticator.java +++ b/src/main/java/caosdb/server/CaosAuthenticator.java @@ -22,21 +22,19 @@ */ package caosdb.server; -import caosdb.server.accessControl.AuthenticationUtils; -import caosdb.server.accessControl.OneTimeAuthenticationToken; -import caosdb.server.accessControl.SessionToken; -import caosdb.server.resource.DefaultResource; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.shiro.SecurityUtils; -import org.apache.shiro.authc.AccountException; import org.apache.shiro.authc.AuthenticationException; -import org.apache.shiro.authc.CredentialsException; import org.apache.shiro.subject.Subject; import org.restlet.Context; import org.restlet.Request; import org.restlet.Response; import org.restlet.security.Authenticator; +import caosdb.server.accessControl.AuthenticationUtils; +import caosdb.server.accessControl.OneTimeAuthenticationToken; +import caosdb.server.accessControl.SessionToken; +import caosdb.server.resource.DefaultResource; public class CaosAuthenticator extends Authenticator { @@ -62,11 +60,12 @@ public class CaosAuthenticator extends Authenticator { if (sessionToken != null) { subject.login(sessionToken); } - } catch (final CredentialsException e) { - logger.log(Level.INFO, "LOGIN_FAILED", e); - } catch (final AccountException e) { - logger.log(Level.INFO, "LOGIN_FAILED", e); - } catch (final AuthenticationException e) { + + // anonymous users + if(!subject.isAuthenticated() && CaosDBServer.getServerProperty(ServerProperties.KEY_AUTH_OPTIONAL).equalsIgnoreCase("TRUE")){ + subject.login(AuthenticationUtils.ANONYMOUS_USER); + } + } catch (AuthenticationException e) { logger.log(Level.INFO, "LOGIN_FAILED", e); } return subject.isAuthenticated(); @@ -91,10 +90,6 @@ public class CaosAuthenticator extends Authenticator { if (oneTimeToken != null) { subject.login(oneTimeToken); } - } catch (final CredentialsException e) { - logger.log(Level.INFO, "LOGIN_FAILED", e); - } catch (final AccountException e) { - logger.log(Level.INFO, "LOGIN_FAILED", e); } catch (final AuthenticationException e) { logger.log(Level.INFO, "LOGIN_FAILED", e); } diff --git a/src/main/java/caosdb/server/CaosDBServer.java b/src/main/java/caosdb/server/CaosDBServer.java index 5f2d3140..5f907b65 100644 --- a/src/main/java/caosdb/server/CaosDBServer.java +++ b/src/main/java/caosdb/server/CaosDBServer.java @@ -22,6 +22,7 @@ */ package caosdb.server; +import caosdb.server.accessControl.AnonymousRealm; import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.CaosDBAuthorizingRealm; import caosdb.server.accessControl.CaosDBDefaultRealm; @@ -154,9 +155,10 @@ public class CaosDBServer extends Application { mainSec.put("SessionTokenValidator", SessionTokenRealm.class.getCanonicalName()); mainSec.put("OneTimeTokenValidator", OneTimeTokenRealm.class.getCanonicalName()); mainSec.put("CaosDBAuthorizingRealm", CaosDBAuthorizingRealm.class.getCanonicalName()); + mainSec.put("AnonymousRealm", AnonymousRealm.class.getCanonicalName()); mainSec.put( "securityManager.realms", - "$CaosDB, $SessionTokenValidator, $OneTimeTokenValidator, $CaosDBAuthorizingRealm"); + "$CaosDB, $SessionTokenValidator, $OneTimeTokenValidator, $CaosDBAuthorizingRealm, $AnonymousRealm"); // disable shiro's default session management. We have quasi-stateless // sessions @@ -435,7 +437,7 @@ public class CaosDBServer extends Application { private void setSessionCookies(final Response response) { final Subject subject = SecurityUtils.getSubject(); - if (subject.isAuthenticated()) { + if (subject.isAuthenticated() && subject.getPrincipal() != AuthenticationUtils.ANONYMOUS_USER.getPrincipal()) { final SessionToken sessionToken = SessionToken.generate((Principal) subject.getPrincipal(), null); diff --git a/src/main/java/caosdb/server/ServerProperties.java b/src/main/java/caosdb/server/ServerProperties.java index 9a33d228..c1e12afc 100644 --- a/src/main/java/caosdb/server/ServerProperties.java +++ b/src/main/java/caosdb/server/ServerProperties.java @@ -130,6 +130,7 @@ public class ServerProperties extends Properties { serverProperties.setProperty(KEY_USER_SOURCES_INI_FILE, basepath + "/conf/usersources.ini"); serverProperties.setProperty(KEY_USER_FOLDERS, "FALSE"); serverProperties.setProperty(KEY_NEW_USER_DEFAULT_ACTIVITY, "INACTIVE"); + serverProperties.setProperty(KEY_AUTH_OPTIONAL, "FALSE"); serverProperties.setProperty(KEY_MYSQL_HOST, "localhost"); serverProperties.setProperty(KEY_MYSQL_PORT, "3306"); diff --git a/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java b/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java index 78aeda06..d1c70c1b 100644 --- a/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java +++ b/src/main/java/caosdb/server/accessControl/AuthenticationUtils.java @@ -36,6 +36,7 @@ import java.util.Collection; import java.util.LinkedList; import java.util.logging.Level; import java.util.logging.Logger; +import org.apache.shiro.authc.AuthenticationToken; import org.restlet.data.Cookie; import org.restlet.data.CookieSetting; @@ -55,6 +56,8 @@ public class AuthenticationUtils { public static final String SESSION_TOKEN_COOKIE = "SessionToken"; public static final String SESSION_TIMEOUT_COOKIE = "SessionTimeOut"; + public static final AuthenticationToken ANONYMOUS_USER = AnonymousAuthenticationToken.getInstance(); + /** * Create a cookie for a {@link SelfValidatingAuthenticationToken}. Returns null if the parameter * is null or the token is invalid. The cookie will have the httpOnly and secure flags enabled. diff --git a/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java b/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java index a166d723..d23ae70e 100644 --- a/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java +++ b/src/main/java/caosdb/server/accessControl/CaosDBAuthorizingRealm.java @@ -22,11 +22,9 @@ */ package caosdb.server.accessControl; -import com.google.common.base.Objects; import java.util.Arrays; import java.util.List; import java.util.Set; -import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; @@ -34,6 +32,7 @@ import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.SimplePrincipalCollection; +import com.google.common.base.Objects; public class CaosDBAuthorizingRealm extends AuthorizingRealm { @@ -98,6 +97,11 @@ public class CaosDBAuthorizingRealm extends AuthorizingRealm { return false; } } + + @Override + public int hashCode() { + return this.principalCollection.hashCode(); + } } private static final CaosDBRolePermissionResolver role_permission_resolver = @@ -116,7 +120,7 @@ public class CaosDBAuthorizingRealm extends AuthorizingRealm { // find all roles which are associated with this principal in this // realm. - final Set<String> roles = UserSources.resolve((Principal) principals.getPrimaryPrincipal()); + final Set<String> roles = UserSources.resolve(principals); if (roles != null) { authzInfo.setRoles(roles); @@ -139,8 +143,7 @@ public class CaosDBAuthorizingRealm extends AuthorizingRealm { } @Override - protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) - throws AuthenticationException { + protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) { return null; } } diff --git a/src/main/java/caosdb/server/accessControl/CaosDBDefaultRealm.java b/src/main/java/caosdb/server/accessControl/CaosDBDefaultRealm.java index 7eebee42..209487b7 100644 --- a/src/main/java/caosdb/server/accessControl/CaosDBDefaultRealm.java +++ b/src/main/java/caosdb/server/accessControl/CaosDBDefaultRealm.java @@ -22,7 +22,6 @@ */ package caosdb.server.accessControl; -import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; @@ -32,8 +31,7 @@ import org.apache.shiro.realm.AuthenticatingRealm; public class CaosDBDefaultRealm extends AuthenticatingRealm { @Override - protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) - throws AuthenticationException { + protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) { final String realm = ((RealmUsernamePasswordToken) token).getRealm(); final String username = ((RealmUsernamePasswordToken) token).getUsername(); final String password = new String(((RealmUsernamePasswordToken) token).getCredentials()); @@ -50,7 +48,6 @@ public class CaosDBDefaultRealm extends AuthenticatingRealm { setCachingEnabled(false); setAuthenticationCachingEnabled(false); - // setAuthorizationCachingEnabled(false); setAuthenticationTokenClass(RealmUsernamePasswordToken.class); } } diff --git a/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java b/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java index 95c3642d..97b4437d 100644 --- a/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java +++ b/src/main/java/caosdb/server/accessControl/SessionTokenRealm.java @@ -22,7 +22,6 @@ */ package caosdb.server.accessControl; -import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; @@ -32,9 +31,7 @@ import org.apache.shiro.realm.AuthenticatingRealm; public class SessionTokenRealm extends AuthenticatingRealm { @Override - protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) - throws AuthenticationException { - try { + protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token) { final SelfValidatingAuthenticationToken sessionToken = (SelfValidatingAuthenticationToken) token; @@ -42,9 +39,6 @@ public class SessionTokenRealm extends AuthenticatingRealm { if (sessionToken.isValid()) { return new SimpleAuthenticationInfo(sessionToken.getPrincipal(), null, getName()); } - } catch (final Exception e) { - e.printStackTrace(); - } return null; } @@ -53,6 +47,5 @@ public class SessionTokenRealm extends AuthenticatingRealm { setCredentialsMatcher(new AllowAllCredentialsMatcher()); setCachingEnabled(false); setAuthenticationCachingEnabled(false); - // setAuthorizationCachingEnabled(false); } } diff --git a/src/main/java/caosdb/server/accessControl/UserSources.java b/src/main/java/caosdb/server/accessControl/UserSources.java index 55b76c46..ad6581e5 100644 --- a/src/main/java/caosdb/server/accessControl/UserSources.java +++ b/src/main/java/caosdb/server/accessControl/UserSources.java @@ -33,12 +33,15 @@ import caosdb.server.utils.ServerMessages; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.Set; import java.util.logging.LogManager; import java.util.logging.Logger; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.config.Ini; +import org.apache.shiro.subject.PrincipalCollection; public class UserSources extends HashMap<String, UserSource> { @@ -158,8 +161,16 @@ public class UserSources extends HashMap<String, UserSource> { return instance.map.getSectionProperty(Ini.DEFAULT_SECTION_NAME, KEY_DEAULT_REALM); } - public static Set<String> resolve(final Principal p) { - return resolve(p.getRealm(), p.getUsername()); + public static Set<String> resolve(final PrincipalCollection principals) { + if(principals.getPrimaryPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal()){ + // anymous has one role + Set<String> roles = new HashSet<>(); + roles.add("anonymous"); + return roles; + } + + Principal primaryPrincipal = (Principal) principals.getPrimaryPrincipal(); + return resolve(primaryPrincipal.getRealm(), primaryPrincipal.getUsername()); } public static boolean isRoleExisting(final String role) { diff --git a/src/main/java/caosdb/server/permissions/EntityACL.java b/src/main/java/caosdb/server/permissions/EntityACL.java index d389a216..e4037a80 100644 --- a/src/main/java/caosdb/server/permissions/EntityACL.java +++ b/src/main/java/caosdb/server/permissions/EntityACL.java @@ -24,7 +24,7 @@ package caosdb.server.permissions; import static caosdb.server.permissions.Role.OTHER_ROLE; import static caosdb.server.permissions.Role.OWNER_ROLE; - +import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.Principal; import caosdb.server.database.exceptions.TransactionException; import java.util.ArrayList; @@ -74,6 +74,9 @@ public class EntityACL { } public static final EntityACL getOwnerACLFor(final Subject subject) { + if(subject.getPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal()){ + return new EntityACLFactory().create(); + } return getOwnerACLFor((Principal) subject.getPrincipal()); } diff --git a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java index fb819684..9ba1fb68 100644 --- a/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java +++ b/src/main/java/caosdb/server/resource/AbstractCaosDBServerResource.java @@ -26,6 +26,7 @@ import static caosdb.server.utils.Utils.isNonNullInteger; import static java.net.URLDecoder.decode; import caosdb.server.CaosDBException; +import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.Principal; import caosdb.server.database.backend.implementation.MySQL.ConnectionException; import caosdb.server.entity.Message; @@ -155,7 +156,7 @@ public abstract class AbstractCaosDBServerResource extends ServerResource { protected Element generateRootElement() { final Element retRoot = new Element("Response"); - if (getUser() != null && getUser().isAuthenticated()) { + if (getUser() != null && getUser().isAuthenticated() && !getUser().getPrincipal().equals(AuthenticationUtils.ANONYMOUS_USER.getPrincipal())) { retRoot.setAttribute("username", ((Principal) getUser().getPrincipal()).getUsername()); retRoot.setAttribute("realm", ((Principal) getUser().getPrincipal()).getRealm()); } diff --git a/src/main/java/caosdb/server/transaction/Transaction.java b/src/main/java/caosdb/server/transaction/Transaction.java index 2a7562c1..c29efac3 100644 --- a/src/main/java/caosdb/server/transaction/Transaction.java +++ b/src/main/java/caosdb/server/transaction/Transaction.java @@ -23,6 +23,7 @@ package caosdb.server.transaction; import caosdb.datetime.UTCDateTime; +import caosdb.server.accessControl.AuthenticationUtils; import caosdb.server.accessControl.Principal; import caosdb.server.database.Database; import caosdb.server.database.DatabaseMonitor; @@ -222,12 +223,14 @@ public abstract class Transaction<C extends TransactionContainer> extends Abstra // TODO move to post-transaction job private void writeHistory() throws TransactionException, Message { if (logHistory()) { + String realm = getTransactor().getPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal() ? "" :((Principal) getTransactor().getPrincipal()).getRealm(); + String username = getTransactor().getPrincipal() == AuthenticationUtils.ANONYMOUS_USER.getPrincipal() ? "anonymous" : ((Principal) getTransactor().getPrincipal()).getUsername(); Database.execute( new InsertTransactionHistory( getContainer(), this.getClass().getSimpleName(), - ((Principal) getTransactor().getPrincipal()).getRealm(), - ((Principal) getTransactor().getPrincipal()).getUsername(), + realm, + username, getTimestamp()), getAccess()); } -- GitLab