caching framework cleanup and test extension
Change-Id: I472b0a465e3d2217835ffb1f49e07a1b65a08976
diff --git a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
index ccb8092..1184ac8 100644
--- a/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
+++ b/src/main/java/de/ids_mannheim/korap/security/auth/KustvaktAuthenticationManager.java
@@ -9,20 +9,18 @@
import de.ids_mannheim.korap.interfaces.AuthenticationIface;
import de.ids_mannheim.korap.interfaces.AuthenticationManagerIface;
import de.ids_mannheim.korap.interfaces.EncryptionIface;
+import de.ids_mannheim.korap.interfaces.ValidatorIface;
import de.ids_mannheim.korap.interfaces.db.AuditingIface;
import de.ids_mannheim.korap.interfaces.db.EntityHandlerIface;
import de.ids_mannheim.korap.interfaces.db.UserDataDbIface;
+import de.ids_mannheim.korap.interfaces.defaults.ApacheValidator;
import de.ids_mannheim.korap.user.*;
import de.ids_mannheim.korap.utils.StringUtils;
import de.ids_mannheim.korap.utils.TimeUtils;
-import net.sf.ehcache.Cache;
-import net.sf.ehcache.CacheManager;
-import net.sf.ehcache.Element;
-import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.cache.annotation.CachePut;
+import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.NoSuchAlgorithmException;
import java.util.Collection;
@@ -38,7 +36,6 @@
*/
public class KustvaktAuthenticationManager extends AuthenticationManagerIface {
- private static String KEY = "kustvakt:key";
private static Logger jlog = LoggerFactory
.getLogger(KustvaktAuthenticationManager.class);
private EncryptionIface crypto;
@@ -47,21 +44,25 @@
private KustvaktConfiguration config;
private Collection userdatadaos;
private LoginCounter counter;
- private Cache user_cache;
-
+ private ValidatorIface validator;
public KustvaktAuthenticationManager (EntityHandlerIface userdb,
EncryptionIface crypto,
KustvaktConfiguration config,
AuditingIface auditer,
Collection<UserDataDbIface> userdatadaos) {
- this.user_cache = CacheManager.getInstance().getCache("users");
this.entHandler = userdb;
this.config = config;
this.crypto = crypto;
this.auditing = auditer;
this.counter = new LoginCounter(config);
this.userdatadaos = userdatadaos;
+ // todo: load via beancontext
+ try {
+ this.validator = new ApacheValidator();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
@@ -74,6 +75,7 @@
* @return
* @throws KustvaktException
*/
+ @Override
public TokenContext getTokenStatus (String token, String host,
String useragent) throws KustvaktException {
jlog.info("getting session status of token type '{}'",
@@ -82,41 +84,46 @@
StringUtils.getTokenType(token), null);
if (provider == null)
- // throw exception for missing type paramter
+ // throw exception for missing type parameter
throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
"token type not defined or found", "token_type");
- TokenContext context = provider.getUserStatus(token);
+ TokenContext context = provider.getTokenContext(token);
+ System.out.println("CONTEXT "+ context.toResponse());
+ if (context != null && TimeUtils.isExpired(context.getExpirationTime()))
+ throw new KustvaktException(StatusCodes.EXPIRED);
+
// if (!matchStatus(host, useragent, context))
// provider.removeUserSession(token);
return context;
}
+ @Override
public User getUser (String username) throws KustvaktException {
- User user;
- String key = cache_key(username);
- Element e = user_cache.get(key);
+ //User user;
+ //Object value = this.getCacheValue(username);
if (User.UserFactory.isDemo(username))
return User.UserFactory.getDemoUser();
- if (e != null) {
- Map map = (Map) e.getObjectValue();
- user = User.UserFactory.toUser(map);
- }
- else {
- user = entHandler.getAccount(username);
- user_cache.put(new Element(key, user.toCache()));
+ //if (value != null) {
+ // Map map = (Map) value;
+ // user = User.UserFactory.toUser(map);
+ //}
+ // else {
+ // user = entHandler.getAccount(username);
+ // this.storeInCache(username, user.toCache());
// todo: not valid. for the duration of the session, the host should not change!
- }
+ //}
//todo:
// user.addField(Attributes.HOST, context.getHostAddress());
// user.addField(Attributes.USER_AGENT, context.getUserAgent());
- return user;
+ return entHandler.getAccount(username);
}
+
public TokenContext refresh (TokenContext context) throws KustvaktException {
AuthenticationIface provider = getProvider(context.getTokenType(), null);
if (provider == null) {
@@ -126,7 +133,7 @@
try {
provider.removeUserSession(context.getToken());
User user = getUser(context.getUsername());
- return provider.createUserSession(user, context.params());
+ return provider.createTokenContext(user, context.params());
}
catch (KustvaktException e) {
throw new WrappedException(e, StatusCodes.LOGIN_FAILED);
@@ -163,9 +170,7 @@
}
- // todo: dont use annotations for caching
@Override
- @CachePut(value = "users", key = "#user.getUsername()")
public TokenContext createTokenContext (User user,
Map<String, Object> attr, String provider_key)
throws KustvaktException {
@@ -175,7 +180,7 @@
if (attr.get(Attributes.SCOPES) != null)
this.getUserData(user, UserDetails.class);
- TokenContext context = provider.createUserSession(user, attr);
+ TokenContext context = provider.createTokenContext(user, attr);
if (context == null)
throw new KustvaktException(StatusCodes.NOT_SUPPORTED);
context.setUserAgent((String) attr.get(Attributes.USER_AGENT));
@@ -205,12 +210,11 @@
throw new KustvaktException(StatusCodes.REQUEST_INVALID);
if (!attributes.containsKey(Attributes.EMAIL)
- && crypto.validateEntry(eppn, Attributes.EMAIL) != null)
+ && validator.isValid(eppn, Attributes.EMAIL))
attributes.put(Attributes.EMAIL, eppn);
- // fixme?!
- User user = isRegistered(eppn);
- if (user == null)
+ User user = null;
+ if (isRegistered(eppn))
user = createShibbUserAccount(attributes);
return user;
}
@@ -219,32 +223,30 @@
//todo: what if attributes null?
private User authenticate (String username, String password,
Map<String, Object> attr) throws KustvaktException {
- Map<String, Object> attributes = crypto.validateMap(attr);
- String safeUS;
+ Map<String, Object> attributes = validator.validateMap(attr);
User unknown;
// just to make sure that the plain password does not appear anywhere in the logs!
try {
- safeUS = crypto.validateEntry(username, Attributes.USERNAME);
- }
- catch (KustvaktException e) {
+ validator.validateEntry(username, Attributes.USERNAME);
+ } catch (KustvaktException e) {
throw new WrappedException(e, StatusCodes.LOGIN_FAILED, username);
}
- if (safeUS == null || safeUS.isEmpty())
+ if (username == null || username.isEmpty())
throw new WrappedException(new KustvaktException(username,
StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED);
else {
try {
- unknown = entHandler.getAccount(safeUS);
- }
- catch (EmptyResultException e) {
+ unknown = entHandler.getAccount(username);
+ } catch (EmptyResultException e) {
// mask exception to disable user guessing in possible attacks
throw new WrappedException(new KustvaktException(username,
StatusCodes.BAD_CREDENTIALS), StatusCodes.LOGIN_FAILED,
username);
}
catch (KustvaktException e) {
+ jlog.error("Error: {}", e);
throw new WrappedException(e, StatusCodes.LOGIN_FAILED,
attributes.toString());
}
@@ -302,43 +304,44 @@
else if (unknown instanceof ShibUser) {
//todo
}
- jlog.debug("Authentication done: " + safeUS);
+ jlog.debug("Authentication done: " + username);
return unknown;
}
- public User isRegistered (String username) throws KustvaktException {
+ public boolean isRegistered (String username) {
User user;
if (username == null || username.isEmpty())
- throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
- "username must be set", username);
+ return false;
+ // throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
+ // "username must be set", username);
try {
user = entHandler.getAccount(username);
}
catch (EmptyResultException e) {
jlog.debug("user does not exist ({})", username);
- return null;
+ return false;
}
catch (KustvaktException e) {
- jlog.error("KorAPException", e);
- throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
- "username invalid", username);
+ jlog.error("KorAPException", e.string());
+ return false;
+ //throw new KustvaktException(username, StatusCodes.ILLEGAL_ARGUMENT,
+ // "username invalid", username);
}
- return user;
+ return user != null;
}
public void logout (TokenContext context) throws KustvaktException {
- String key = cache_key(context.getUsername());
try {
AuthenticationIface provider = getProvider(context.getTokenType(),
null);
if (provider == null) {
- //todo:
- return;
+ throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
+ "provider not supported!", context.getTokenType());
}
provider.removeUserSession(context.getToken());
}
@@ -348,7 +351,7 @@
}
auditing.audit(AuditRecord.serviceRecord(context.getUsername(),
StatusCodes.LOGOUT_SUCCESSFUL, context.toString()));
- user_cache.remove(key);
+ this.removeCacheEntry(context.getToken());
}
@@ -359,7 +362,7 @@
this.lockAccount(user);
}
catch (KustvaktException e) {
- jlog.error("user account could not be locked!", e);
+ jlog.error("user account could not be locked", e);
throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
}
throw new WrappedException(new KustvaktException(user.getId(),
@@ -401,8 +404,6 @@
user.setPassword(crypto.secureHash(newPassword));
}
catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
- // throw new KorAPException(StatusCodes.ILLEGAL_ARGUMENT,
- // "Creating password hash failed!", "password");
throw new WrappedException(new KustvaktException(user.getId(),
StatusCodes.ILLEGAL_ARGUMENT, "password invalid",
newPassword), StatusCodes.PASSWORD_RESET_FAILED,
@@ -416,14 +417,11 @@
@Override
public void resetPassword (String uriFragment, String username,
String newPassphrase) throws KustvaktException {
- String safeUser, safePass;
-
try {
- safeUser = crypto.validateEntry(username, Attributes.USERNAME);
- safePass = crypto.validateEntry(newPassphrase, Attributes.PASSWORD);
- }
- catch (KustvaktException e) {
- jlog.error("Error", e);
+ validator.validateEntry(username, Attributes.USERNAME);
+ validator.validateEntry(newPassphrase, Attributes.PASSWORD);
+ } catch (KustvaktException e) {
+ jlog.error("Error: {}", e.string());
throw new WrappedException(new KustvaktException(username,
StatusCodes.ILLEGAL_ARGUMENT, "password invalid",
newPassphrase), StatusCodes.PASSWORD_RESET_FAILED,
@@ -431,9 +429,8 @@
}
try {
- safePass = crypto.secureHash(safePass);
- }
- catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
+ newPassphrase= crypto.secureHash(newPassphrase);
+ } catch (NoSuchAlgorithmException | UnsupportedEncodingException e) {
jlog.error("Encoding/Algorithm Error", e);
throw new WrappedException(new KustvaktException(username,
StatusCodes.ILLEGAL_ARGUMENT, "password invalid",
@@ -441,30 +438,28 @@
username, uriFragment, newPassphrase);
}
int result = entHandler
- .resetPassphrase(safeUser, uriFragment, safePass);
+ .resetPassphrase(username, uriFragment, newPassphrase);
if (result == 0)
throw new WrappedException(new KustvaktException(username,
StatusCodes.EXPIRED, "URI fragment expired", uriFragment),
StatusCodes.PASSWORD_RESET_FAILED, username, uriFragment);
else if (result == 1)
- jlog.info("successfully reset password for user {}", safeUser);
+ jlog.info("successfully reset password for user {}", username);
}
public void confirmRegistration (String uriFragment, String username)
throws KustvaktException {
- String safeUser;
try {
- safeUser = crypto.validateEntry(username, Attributes.USERNAME);
- }
- catch (KustvaktException e) {
- jlog.error("error", e);
+ validator.validateEntry(username, Attributes.USERNAME);
+ } catch (KustvaktException e) {
+ jlog.error("Error: {}", e.string());
throw new WrappedException(e,
StatusCodes.ACCOUNT_CONFIRMATION_FAILED, username,
uriFragment);
}
- int r = entHandler.activateAccount(safeUser, uriFragment);
+ int r = entHandler.activateAccount(username, uriFragment);
if (r == 0) {
User user;
try {
@@ -484,7 +479,7 @@
}
else if (r == 1)
jlog.info("successfully confirmed user registration for user {}",
- safeUser);
+ username);
// register successful audit!
}
@@ -497,7 +492,8 @@
//fixme: remove clientinfo object (not needed), use json representation to get stuff
public User createUserAccount (Map<String, Object> attributes,
boolean confirmation_required) throws KustvaktException {
- Map<String, Object> safeMap = crypto.validateMap(attributes);
+ Map<String, Object> safeMap = validator.validateMap(attributes);
+
if (safeMap.get(Attributes.USERNAME) == null
|| ((String) safeMap.get(Attributes.USERNAME)).isEmpty())
throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
@@ -508,13 +504,13 @@
StatusCodes.ILLEGAL_ARGUMENT, "password must be set",
"password");
- String username = crypto.validateEntry(
+ String username = validator.validateEntry(
(String) safeMap.get(Attributes.USERNAME), Attributes.USERNAME);
- String safePass = crypto.validateEntry(
+ String password = validator.validateEntry(
(String) safeMap.get(Attributes.PASSWORD), Attributes.PASSWORD);
String hash;
try {
- hash = crypto.secureHash(safePass);
+ hash = crypto.secureHash(password);
}
catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
jlog.error("Encryption error", e);
@@ -534,19 +530,21 @@
}
user.setPassword(hash);
try {
+ UserDetails details = new UserDetails();
+ details.read(safeMap, true);
+
+ UserSettings settings = new UserSettings();
+ settings.read(safeMap, true);
+
jlog.info("Creating new user account for user {}",
user.getUsername());
entHandler.createAccount(user);
- UserDetails details = new UserDetails(user.getId());
- details.read(safeMap, true);
- details.checkRequired();
-
- UserSettings settings = new UserSettings(user.getId());
- settings.read(safeMap, true);
- settings.checkRequired();
+ details.setUserId(user.getId());
+ settings.setUserId(user.getId());
UserDataDbIface dao = BeansFactory.getTypeFactory()
.getTypeInterfaceBean(userdatadaos, UserDetails.class);
+ //todo: remove this
assert dao != null;
dao.store(details);
dao = BeansFactory.getTypeFactory().getTypeInterfaceBean(
@@ -555,6 +553,7 @@
dao.store(settings);
}
catch (KustvaktException e) {
+ jlog.error("Error: {}", e.string());
throw new WrappedException(e, StatusCodes.CREATE_ACCOUNT_FAILED,
user.toString());
}
@@ -570,7 +569,7 @@
throws KustvaktException {
jlog.debug("creating shibboleth user account for user attr: {}",
attributes);
- Map<String, Object> safeMap = crypto.validateMap(attributes);
+ Map<String, Object> safeMap = validator.validateMap(attributes);
//todo eppn non-unique.join with idp or use persistent_id as username identifier
ShibUser user = User.UserFactory.getShibInstance(
@@ -579,21 +578,24 @@
(String) safeMap.get(Attributes.CN));
user.setAffiliation((String) safeMap.get(Attributes.EDU_AFFIL));
user.setAccountCreation(TimeUtils.getNow().getMillis());
+
+
+ UserDetails d = new UserDetails();
+ d.read(attributes, true);
+
+ UserSettings s = new UserSettings();
+ s.read(attributes, true);
+
entHandler.createAccount(user);
- UserDetails d = new UserDetails(user.getId());
- d.read(attributes, true);
- d.checkRequired();
+ s.setUserId(user.getId());
+ d.setUserId(user.getId());
UserDataDbIface dao = BeansFactory.getTypeFactory()
.getTypeInterfaceBean(userdatadaos, UserDetails.class);
assert dao != null;
dao.store(d);
- UserSettings s = new UserSettings(user.getId());
- s.read(attributes, true);
- s.checkRequired();
-
dao = BeansFactory.getTypeFactory().getTypeInterfaceBean(userdatadaos,
UserSettings.class);
assert dao != null;
@@ -648,9 +650,9 @@
}
+ // todo: test and rest usage?!
public boolean updateAccount (User user) throws KustvaktException {
boolean result;
- String key = cache_key(user.getUsername());
if (user instanceof DemoUser)
throw new KustvaktException(user.getId(),
StatusCodes.REQUEST_INVALID,
@@ -661,12 +663,12 @@
result = entHandler.updateAccount(user) > 0;
}
catch (KustvaktException e) {
- jlog.error("Error ", e);
+ jlog.error("Error: {}", e.string());
throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
}
}
if (result) {
- user_cache.remove(key);
+ // this.removeCacheEntry(user.getUsername());
auditing.audit(AuditRecord.serviceRecord(user.getId(),
StatusCodes.UPDATE_ACCOUNT_SUCCESSFUL, user.toString()));
}
@@ -676,7 +678,6 @@
public boolean deleteAccount (User user) throws KustvaktException {
boolean result;
- String key = cache_key(user.getUsername());
if (user instanceof DemoUser)
return true;
else {
@@ -684,12 +685,12 @@
result = entHandler.deleteAccount(user.getId()) > 0;
}
catch (KustvaktException e) {
- jlog.error("Error ", e);
+ jlog.error("Error: {}", e.string());
throw new WrappedException(e, StatusCodes.DELETE_ACCOUNT_FAILED);
}
}
if (result) {
- user_cache.remove(key);
+ // this.removeCacheEntry(user.getUsername());
auditing.audit(AuditRecord.serviceRecord(user.getUsername(),
StatusCodes.DELETE_ACCOUNT_SUCCESSFUL, user.toString()));
}
@@ -699,8 +700,8 @@
public Object[] validateResetPasswordRequest (String username, String email)
throws KustvaktException {
- String mail, uritoken;
- mail = crypto.validateEntry(email, Attributes.EMAIL);
+ String uritoken;
+ validator.validateEntry(email, Attributes.EMAIL);
User ident;
try {
ident = entHandler.getAccount(username);
@@ -719,7 +720,7 @@
Userdata data = this.getUserData(ident, UserDetails.class);
KorAPUser user = (KorAPUser) ident;
- if (!mail.equals(data.get(Attributes.EMAIL)))
+ if (!email.equals(data.get(Attributes.EMAIL)))
// throw new NotAuthorizedException(StatusCodes.ILLEGAL_ARGUMENT,
// "invalid parameter: email", "email");
throw new WrappedException(new KustvaktException(user.getId(),
@@ -734,10 +735,10 @@
entHandler.updateAccount(user);
}
catch (KustvaktException e) {
- jlog.error("Error ", e);
+ jlog.error("Error ", e.string());
throw new WrappedException(e, StatusCodes.PASSWORD_RESET_FAILED);
}
- return new Object[] { uritoken, new DateTime(param.getUriExpiration()) };
+ return new Object[] { uritoken, TimeUtils.format(param.getUriExpiration()) };
}
@@ -771,8 +772,7 @@
@Override
public void updateUserData (Userdata data) throws WrappedException {
try {
-
- data.validate(this.crypto);
+ data.validate(this.validator);
UserDataDbIface dao = BeansFactory.getTypeFactory()
.getTypeInterfaceBean(
BeansFactory.getKustvaktContext()
@@ -785,16 +785,4 @@
throw new WrappedException(e, StatusCodes.UPDATE_ACCOUNT_FAILED);
}
}
-
-
- private String cache_key (String input) throws KustvaktException {
- try {
- return crypto.secureHash(KEY + "@" + input);
- }
- catch (Exception e) {
- jlog.error("illegal cache key input '{}'", input);
- throw new KustvaktException(StatusCodes.ILLEGAL_ARGUMENT,
- "missing or illegal cache key", input);
- }
- }
}