[seam-commits] Seam SVN: r10476 - in trunk: modules/trunk/security/src/main/java/org/jboss/seam/security/crypto and 6 other directories.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Sun Apr 19 05:44:30 EDT 2009
Author: shane.bryzak at jboss.com
Date: 2009-04-19 05:44:29 -0400 (Sun, 19 Apr 2009)
New Revision: 10476
Added:
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/AuthorizationException.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Configuration.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Credentials.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityAction.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityPermissionChecker.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntitySecurityListener.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/FacesSecurityEvents.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/HibernateSecurityInterceptor.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Identity.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/JpaTokenStore.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/NotLoggedInException.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RememberMe.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Role.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RunAsOperation.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityFunctions.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityInterceptor.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimpleGroup.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimplePrincipal.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/TokenStore.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/crypto/
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/digest/
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/jaas/
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/management/
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/openid/
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/package-info.java
trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/permission/
Removed:
trunk/src/main/org/jboss/seam/security/AuthorizationException.java
trunk/src/main/org/jboss/seam/security/Configuration.java
trunk/src/main/org/jboss/seam/security/Credentials.java
trunk/src/main/org/jboss/seam/security/EntityAction.java
trunk/src/main/org/jboss/seam/security/EntityPermissionChecker.java
trunk/src/main/org/jboss/seam/security/EntitySecurityListener.java
trunk/src/main/org/jboss/seam/security/FacesSecurityEvents.java
trunk/src/main/org/jboss/seam/security/HibernateSecurityInterceptor.java
trunk/src/main/org/jboss/seam/security/Identity.java
trunk/src/main/org/jboss/seam/security/JpaTokenStore.java
trunk/src/main/org/jboss/seam/security/NotLoggedInException.java
trunk/src/main/org/jboss/seam/security/RememberMe.java
trunk/src/main/org/jboss/seam/security/Role.java
trunk/src/main/org/jboss/seam/security/RunAsOperation.java
trunk/src/main/org/jboss/seam/security/SecurityFunctions.java
trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java
trunk/src/main/org/jboss/seam/security/SimpleGroup.java
trunk/src/main/org/jboss/seam/security/SimplePrincipal.java
trunk/src/main/org/jboss/seam/security/TokenStore.java
trunk/src/main/org/jboss/seam/security/crypto/
trunk/src/main/org/jboss/seam/security/digest/
trunk/src/main/org/jboss/seam/security/jaas/
trunk/src/main/org/jboss/seam/security/management/
trunk/src/main/org/jboss/seam/security/openid/
trunk/src/main/org/jboss/seam/security/package-info.java
trunk/src/main/org/jboss/seam/security/permission/
Log:
move security module
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/AuthorizationException.java (from rev 10443, trunk/src/main/org/jboss/seam/security/AuthorizationException.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/AuthorizationException.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/AuthorizationException.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,17 @@
+package org.jboss.seam.security;
+
+import javax.ejb.ApplicationException;
+
+/**
+ * Thrown when an authenticated user has insufficient rights to carry out an action.
+ *
+ * @author Shane Bryzak
+ */
+ at ApplicationException(rollback=true)
+public class AuthorizationException extends RuntimeException
+{
+ public AuthorizationException(String message)
+ {
+ super(message);
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/AuthorizationException.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Configuration.java (from rev 10443, trunk/src/main/org/jboss/seam/security/Configuration.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Configuration.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Configuration.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,75 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.APPLICATION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.util.HashMap;
+
+import javax.security.auth.login.AppConfigurationEntry;
+import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Factory;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.security.jaas.SeamLoginModule;
+
+/**
+ * Factory for the JAAS Configuration used by Seam Security.
+ *
+ * @author Shane Bryzak
+ *
+ */
+ at Name("org.jboss.seam.security.configurationFactory")
+ at BypassInterceptors
+ at Scope(ScopeType.STATELESS)
+ at Install(precedence = BUILT_IN)
+public class Configuration
+{
+ static final String DEFAULT_JAAS_CONFIG_NAME = "default";
+
+ protected javax.security.auth.login.Configuration createConfiguration()
+ {
+ return new javax.security.auth.login.Configuration()
+ {
+ private AppConfigurationEntry[] aces = { createAppConfigurationEntry() };
+
+ @Override
+ public AppConfigurationEntry[] getAppConfigurationEntry(String name)
+ {
+ return DEFAULT_JAAS_CONFIG_NAME.equals(name) ? aces : null;
+ }
+
+ @Override
+ public void refresh() {}
+ };
+ }
+
+ protected AppConfigurationEntry createAppConfigurationEntry()
+ {
+ return new AppConfigurationEntry(
+ SeamLoginModule.class.getName(),
+ LoginModuleControlFlag.REQUIRED,
+ new HashMap<String,String>()
+ );
+ }
+
+ @Factory(value="org.jboss.seam.security.configuration", autoCreate=true, scope=APPLICATION)
+ public javax.security.auth.login.Configuration getConfiguration()
+ {
+ return createConfiguration();
+ }
+
+ public static javax.security.auth.login.Configuration instance()
+ {
+ if ( !Contexts.isApplicationContextActive() )
+ {
+ throw new IllegalStateException("No active application scope");
+ }
+ return (javax.security.auth.login.Configuration) Component.getInstance("org.jboss.seam.security.configuration");
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Configuration.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Credentials.java (from rev 10443, trunk/src/main/org/jboss/seam/security/Credentials.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Credentials.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Credentials.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,139 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.SESSION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.io.IOException;
+import java.io.Serializable;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.core.Events;
+import org.jboss.seam.log.LogProvider;
+import org.jboss.seam.log.Logging;
+
+ at Name("org.jboss.seam.security.credentials")
+ at Scope(SESSION)
+ at Install(precedence = BUILT_IN)
+ at BypassInterceptors
+public class Credentials implements Serializable
+{
+ public static final String EVENT_INIT_CREDENTIALS = "org.jboss.seam.security.initCredentials";
+ public static final String EVENT_CREDENTIALS_UPDATED = "org.jboss.seam.security.credentialsUpdated";
+
+ private static final LogProvider log = Logging.getLogProvider(Credentials.class);
+
+ private String username;
+ private String password;
+
+ private boolean invalid = false;
+
+ private boolean initialized;
+
+ public boolean isInitialized()
+ {
+ return initialized;
+ }
+
+ public void setInitialized(boolean initialized)
+ {
+ this.initialized = initialized;
+ }
+
+ public String getUsername()
+ {
+ if (!isInitialized() && Events.exists())
+ {
+ setInitialized(true);
+ Events.instance().raiseEvent(EVENT_INIT_CREDENTIALS, this);
+ }
+
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ if (this.username != username && (this.username == null || !this.username.equals(username)))
+ {
+ this.username = username;
+ invalid = false;
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_CREDENTIALS_UPDATED);
+ }
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ if (this.password != password && (this.password == null || !this.password.equals(password)))
+ {
+ this.password = password;
+ invalid = false;
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_CREDENTIALS_UPDATED);
+ }
+ }
+
+ public boolean isSet()
+ {
+ return getUsername() != null && password != null;
+ }
+
+ public boolean isInvalid()
+ {
+ return invalid;
+ }
+
+ public void invalidate()
+ {
+ invalid = true;
+ }
+
+ public void clear()
+ {
+ username = null;
+ password = null;
+ }
+
+
+ /**
+ * Creates a callback handler that can handle a standard username/password
+ * callback, using the username and password properties.
+ */
+ public CallbackHandler createCallbackHandler()
+ {
+ return new CallbackHandler()
+ {
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException
+ {
+ for (int i=0; i < callbacks.length; i++)
+ {
+ if (callbacks[i] instanceof NameCallback)
+ {
+ ( (NameCallback) callbacks[i] ).setName(getUsername());
+ }
+ else if (callbacks[i] instanceof PasswordCallback)
+ {
+ ( (PasswordCallback) callbacks[i] ).setPassword( getPassword() != null ?
+ getPassword().toCharArray() : null );
+ }
+ else
+ {
+ log.warn("Unsupported callback " + callbacks[i]);
+ }
+ }
+ }
+ };
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Credentials.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityAction.java (from rev 10443, trunk/src/main/org/jboss/seam/security/EntityAction.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityAction.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityAction.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,23 @@
+package org.jboss.seam.security;
+
+/**
+ * Actions that may be performed upon entities
+ * in JPA or Hibernate.
+ *
+ * @author Shane Bryzak
+ *
+ */
+public enum EntityAction {
+
+ READ,
+ INSERT,
+ UPDATE,
+ DELETE;
+
+ @Override
+ public String toString()
+ {
+ return super.name().toLowerCase();
+ }
+
+}
\ No newline at end of file
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityAction.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityPermissionChecker.java (from rev 10443, trunk/src/main/org/jboss/seam/security/EntityPermissionChecker.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityPermissionChecker.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityPermissionChecker.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,124 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.APPLICATION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.lang.reflect.Method;
+
+import javax.persistence.EntityManager;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.Startup;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.annotations.security.Restrict;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.persistence.PersistenceProvider;
+import org.jboss.seam.util.Strings;
+
+/**
+ * Entity permission checks
+ *
+ * @author Shane Bryzak
+ */
+ at Name("org.jboss.seam.security.entityPermissionChecker")
+ at Scope(APPLICATION)
+ at Install(precedence = BUILT_IN)
+ at BypassInterceptors
+ at Startup
+public class EntityPermissionChecker
+{
+ private String entityManagerName = "entityManager";
+
+ private EntityManager getEntityManager()
+ {
+ return (EntityManager) Component.getInstance(entityManagerName);
+ }
+
+ public String getEntityManagerName()
+ {
+ return entityManagerName;
+ }
+
+ public void setEntityManagerName(String name)
+ {
+ this.entityManagerName = name;
+ }
+
+ public static EntityPermissionChecker instance()
+ {
+ if ( !Contexts.isApplicationContextActive() )
+ {
+ throw new IllegalStateException("No active application context");
+ }
+
+ EntityPermissionChecker instance = (EntityPermissionChecker) Component.getInstance(
+ EntityPermissionChecker.class, ScopeType.APPLICATION);
+
+ if (instance == null)
+ {
+ throw new IllegalStateException("No EntityPermissionChecker could be created");
+ }
+
+ return instance;
+ }
+
+ public void checkEntityPermission(Object entity, EntityAction action)
+ {
+ if (!Identity.isSecurityEnabled()) return;
+
+ if (!Contexts.isSessionContextActive()) return;
+
+ Identity identity = Identity.instance();
+
+ identity.tryLogin();
+
+ PersistenceProvider provider = PersistenceProvider.instance();
+ Class beanClass = provider.getBeanClass(entity);
+
+ if (beanClass != null)
+ {
+ Method m = null;
+ switch (action)
+ {
+ case READ:
+ m = provider.getPostLoadMethod(entity, getEntityManager());
+ break;
+ case INSERT:
+ m = provider.getPrePersistMethod(entity, getEntityManager());
+ break;
+ case UPDATE:
+ m = provider.getPreUpdateMethod(entity, getEntityManager());
+ break;
+ case DELETE:
+ m = provider.getPreRemoveMethod(entity, getEntityManager());
+ }
+
+ Restrict restrict = null;
+
+ if (m != null && m.isAnnotationPresent(Restrict.class))
+ {
+ restrict = m.getAnnotation(Restrict.class);
+ }
+ else if (entity.getClass().isAnnotationPresent(Restrict.class))
+ {
+ restrict = entity.getClass().getAnnotation(Restrict.class);
+ }
+
+ if (restrict != null)
+ {
+ if (Strings.isEmpty(restrict.value()))
+ {
+ identity.checkPermission(entity, action.toString());
+ }
+ else
+ {
+ identity.checkRestriction(restrict.value());
+ }
+ }
+ }
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntityPermissionChecker.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntitySecurityListener.java (from rev 10443, trunk/src/main/org/jboss/seam/security/EntitySecurityListener.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntitySecurityListener.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntitySecurityListener.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,44 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.security.EntityAction.DELETE;
+import static org.jboss.seam.security.EntityAction.INSERT;
+import static org.jboss.seam.security.EntityAction.READ;
+import static org.jboss.seam.security.EntityAction.UPDATE;
+
+import javax.persistence.PostLoad;
+import javax.persistence.PrePersist;
+import javax.persistence.PreRemove;
+import javax.persistence.PreUpdate;
+
+
+/**
+ * Facilitates security checks for entity beans.
+ *
+ * @author Shane Bryzak
+ */
+public class EntitySecurityListener
+{
+ @PostLoad
+ public void postLoad(Object entity)
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, READ);
+ }
+
+ @PrePersist
+ public void prePersist(Object entity)
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, INSERT);
+ }
+
+ @PreUpdate
+ public void preUpdate(Object entity)
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, UPDATE);
+ }
+
+ @PreRemove
+ public void preRemove(Object entity)
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, DELETE);
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/EntitySecurityListener.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/FacesSecurityEvents.java (from rev 10443, trunk/src/main/org/jboss/seam/security/FacesSecurityEvents.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/FacesSecurityEvents.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/FacesSecurityEvents.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,106 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.APPLICATION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import javax.security.auth.login.LoginException;
+
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Observer;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.Startup;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.international.StatusMessages;
+import org.jboss.seam.international.StatusMessage.Severity;
+
+/**
+ * Produces FacesMessages in response of certain security events, and helps to decouple the
+ * Identity component from JSF.
+ *
+ * @author Shane Bryzak
+ */
+ at Name("org.jboss.seam.security.facesSecurityEvents")
+ at Scope(APPLICATION)
+ at Install(precedence = BUILT_IN, classDependencies = "javax.faces.context.FacesContext")
+ at BypassInterceptors
+ at Startup
+public class FacesSecurityEvents
+{
+ @Observer(Identity.EVENT_POST_AUTHENTICATE)
+ public void postAuthenticate(Identity identity)
+ {
+ //org.jboss.security.saml.SSOManager.processManualLoginNotification(
+ //ServletContexts.instance().getRequest(), identity.getPrincipal().getName());
+ }
+
+ @Observer(Identity.EVENT_LOGIN_FAILED)
+ public void addLoginFailedMessage(LoginException ex)
+ {
+ StatusMessages.instance().addFromResourceBundleOrDefault(
+ getLoginFailedMessageSeverity(),
+ getLoginFailedMessageKey(),
+ getLoginFailedMessage(),
+ ex);
+ }
+
+ public String getLoginFailedMessage()
+ {
+ return "Login failed";
+ }
+
+ public Severity getLoginFailedMessageSeverity()
+ {
+ return Severity.INFO;
+ }
+
+ public String getLoginFailedMessageKey()
+ {
+ return "org.jboss.seam.loginFailed";
+ }
+
+ @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
+ public void addLoginSuccessfulMessage()
+ {
+ StatusMessages.instance().addFromResourceBundleOrDefault(
+ getLoginSuccessfulMessageSeverity(),
+ getLoginSuccessfulMessageKey(),
+ getLoginSuccessfulMessage(),
+ Identity.instance().getCredentials().getUsername());
+ }
+
+ @Observer(Identity.EVENT_NOT_LOGGED_IN)
+ public void addNotLoggedInMessage()
+ {
+ StatusMessages.instance().addFromResourceBundleOrDefault(
+ Severity.WARN,
+ "org.jboss.seam.NotLoggedIn",
+ "Please log in first"
+ );
+ }
+
+ public Severity getLoginSuccessfulMessageSeverity()
+ {
+ return Severity.INFO;
+ }
+
+ public String getLoginSuccessfulMessage()
+ {
+ return "Welcome, #0";
+ }
+
+ public String getLoginSuccessfulMessageKey()
+ {
+ return "org.jboss.seam.loginSuccessful";
+ }
+
+ @Observer(Identity.EVENT_ALREADY_LOGGED_IN)
+ public void addAlreadyLoggedInMessage()
+ {
+ StatusMessages.instance().addFromResourceBundleOrDefault (
+ Severity.WARN,
+ "org.jboss.seam.AlreadyLoggedIn",
+ "You are already logged in, please log out first if you wish to log in again"
+ );
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/FacesSecurityEvents.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/HibernateSecurityInterceptor.java (from rev 10443, trunk/src/main/org/jboss/seam/security/HibernateSecurityInterceptor.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/HibernateSecurityInterceptor.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/HibernateSecurityInterceptor.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,100 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.security.EntityAction.DELETE;
+import static org.jboss.seam.security.EntityAction.INSERT;
+import static org.jboss.seam.security.EntityAction.READ;
+import static org.jboss.seam.security.EntityAction.UPDATE;
+
+import java.io.Serializable;
+
+import org.hibernate.EmptyInterceptor;
+import org.hibernate.Interceptor;
+import org.hibernate.type.Type;
+import org.jboss.seam.Entity.NotEntityException;
+
+/**
+ * Facilitates security checks for Hibernate entities
+ *
+ * @author Shane Bryzak
+ *
+ */
+public class HibernateSecurityInterceptor extends EmptyInterceptor
+{
+ private Interceptor wrappedInterceptor;
+
+ public HibernateSecurityInterceptor(Interceptor wrappedInterceptor)
+ {
+ this.wrappedInterceptor = wrappedInterceptor;
+ }
+
+ @Override
+ public boolean onLoad(Object entity, Serializable id, Object[] state,
+ String[] propertyNames, Type[] types)
+ {
+ try
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, READ);
+ }
+ catch (NotEntityException e)
+ {
+ // Not a JPA entity
+ }
+
+ return wrappedInterceptor != null ?
+ wrappedInterceptor.onLoad(entity, id, state, propertyNames, types) :
+ false;
+ }
+
+ @Override
+ public void onDelete(Object entity, Serializable id, Object[] state,
+ String[] propertyNames, Type[] types)
+ {
+ try
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, DELETE);
+ }
+ catch (NotEntityException e)
+ {
+ // Not a JPA entity
+ }
+
+ if (wrappedInterceptor != null)
+ wrappedInterceptor.onDelete(entity, id, state, propertyNames, types);
+ }
+
+ @Override
+ public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
+ Object[] previousState, String[] propertyNames, Type[] types)
+ {
+ try
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, UPDATE);
+ }
+ catch (NotEntityException e)
+ {
+ // Not a JPA entity
+ }
+
+ return wrappedInterceptor != null ?
+ wrappedInterceptor.onFlushDirty(entity, id, currentState,
+ previousState, propertyNames, types) : false;
+ }
+
+ @Override
+ public boolean onSave(Object entity, Serializable id, Object[] state,
+ String[] propertyNames, Type[] types)
+ {
+ try
+ {
+ EntityPermissionChecker.instance().checkEntityPermission(entity, INSERT);
+ }
+ catch (NotEntityException e)
+ {
+ // Not a JPA entity
+ }
+
+ return wrappedInterceptor != null ?
+ wrappedInterceptor.onSave(entity, id, state, propertyNames, types) :
+ false;
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/HibernateSecurityInterceptor.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Identity.java (from rev 10443, trunk/src/main/org/jboss/seam/security/Identity.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Identity.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Identity.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,752 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.SESSION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.Startup;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.core.Events;
+import org.jboss.seam.core.Expressions;
+import org.jboss.seam.core.Expressions.MethodExpression;
+import org.jboss.seam.log.LogProvider;
+import org.jboss.seam.log.Logging;
+import org.jboss.seam.security.permission.PermissionMapper;
+import org.jboss.seam.web.Session;
+
+/**
+ * API for authorization and authentication via Seam security. This base
+ * implementation supports role-based authorization only. Subclasses may add
+ * more sophisticated permissioning mechanisms.
+ *
+ * @author Shane Bryzak
+ */
+ at Name("org.jboss.seam.security.identity")
+ at Scope(SESSION)
+ at Install(precedence = BUILT_IN)
+ at BypassInterceptors
+ at Startup
+public class Identity implements Serializable
+{
+ private static final long serialVersionUID = 3751659008033189259L;
+
+ // Event keys
+ public static final String EVENT_LOGIN_SUCCESSFUL = "org.jboss.seam.security.loginSuccessful";
+ public static final String EVENT_LOGIN_FAILED = "org.jboss.seam.security.loginFailed";
+ public static final String EVENT_NOT_LOGGED_IN = "org.jboss.seam.security.notLoggedIn";
+ public static final String EVENT_NOT_AUTHORIZED = "org.jboss.seam.security.notAuthorized";
+ public static final String EVENT_PRE_AUTHENTICATE = "org.jboss.seam.security.preAuthenticate";
+ public static final String EVENT_POST_AUTHENTICATE = "org.jboss.seam.security.postAuthenticate";
+ public static final String EVENT_LOGGED_OUT = "org.jboss.seam.security.loggedOut";
+ public static final String EVENT_ALREADY_LOGGED_IN = "org.jboss.seam.security.alreadyLoggedIn";
+ public static final String EVENT_QUIET_LOGIN = "org.jboss.seam.security.quietLogin";
+
+ protected static boolean securityEnabled = true;
+
+ public static final String ROLES_GROUP = "Roles";
+
+ // Context variables
+ private static final String LOGIN_TRIED = "org.jboss.seam.security.loginTried";
+ private static final String SILENT_LOGIN = "org.jboss.seam.security.silentLogin";
+
+ private static final LogProvider log = Logging.getLogProvider(Identity.class);
+
+ private Credentials credentials;
+
+ private MethodExpression authenticateMethod;
+
+ private Principal principal;
+ private Subject subject;
+
+ private RememberMe rememberMe;
+
+ private transient ThreadLocal<Boolean> systemOp;
+
+ private String jaasConfigName = null;
+
+ private List<String> preAuthenticationRoles = new ArrayList<String>();
+
+ private PermissionMapper permissionMapper;
+
+ /**
+ * Flag that indicates we are in the process of authenticating
+ */
+ private boolean authenticating = false;
+
+ @Create
+ public void create()
+ {
+ subject = new Subject();
+
+ if (Contexts.isApplicationContextActive())
+ {
+ permissionMapper = (PermissionMapper) Component.getInstance(PermissionMapper.class);
+ }
+
+ if (Contexts.isSessionContextActive())
+ {
+ rememberMe = (RememberMe) Component.getInstance(RememberMe.class, true);
+ credentials = (Credentials) Component.getInstance(Credentials.class);
+ }
+
+ if (credentials == null)
+ {
+ // Must have credentials for unit tests
+ credentials = new Credentials();
+ }
+ }
+
+ public static boolean isSecurityEnabled()
+ {
+ return securityEnabled;
+ }
+
+ public static void setSecurityEnabled(boolean enabled)
+ {
+ securityEnabled = enabled;
+ }
+
+ public static Identity instance()
+ {
+ if ( !Contexts.isSessionContextActive() )
+ {
+ throw new IllegalStateException("No active session context");
+ }
+
+ Identity instance = (Identity) Component.getInstance(Identity.class, ScopeType.SESSION);
+
+ if (instance == null)
+ {
+ throw new IllegalStateException("No Identity could be created");
+ }
+
+ return instance;
+ }
+
+ /**
+ * Simple check that returns true if the user is logged in, without attempting to authenticate
+ *
+ * @return true if the user is logged in
+ */
+ public boolean isLoggedIn()
+ {
+ // If there is a principal set, then the user is logged in.
+ return getPrincipal() != null;
+ }
+
+ /**
+ * Will attempt to authenticate quietly if the user's credentials are set and they haven't
+ * authenticated already. A quiet authentication doesn't throw any exceptions if authentication
+ * fails.
+ *
+ * @return true if the user is logged in, false otherwise
+ */
+ public boolean tryLogin()
+ {
+ if (!authenticating && getPrincipal() == null && credentials.isSet() &&
+ Contexts.isEventContextActive() &&
+ !Contexts.getEventContext().isSet(LOGIN_TRIED))
+ {
+ Contexts.getEventContext().set(LOGIN_TRIED, true);
+ quietLogin();
+ }
+
+ return isLoggedIn();
+ }
+
+ @Deprecated
+ public boolean isLoggedIn(boolean attemptLogin)
+ {
+ return attemptLogin ? tryLogin() : isLoggedIn();
+ }
+
+
+ public void acceptExternallyAuthenticatedPrincipal(Principal principal) {
+ getSubject().getPrincipals().add(principal);
+ this.principal = principal;
+ }
+
+ public Principal getPrincipal()
+ {
+ return principal;
+ }
+
+ public Subject getSubject()
+ {
+ return subject;
+ }
+
+ /**
+ * Performs an authorization check, based on the specified security expression.
+ *
+ * @param expr The security expression to evaluate
+ * @throws NotLoggedInException Thrown if the authorization check fails and
+ * the user is not authenticated
+ * @throws AuthorizationException Thrown if the authorization check fails and
+ * the user is authenticated
+ */
+ public void checkRestriction(String expr)
+ {
+ if (!securityEnabled) return;
+
+ if ( !evaluateExpression(expr) )
+ {
+ if ( !isLoggedIn() )
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
+ log.debug(String.format(
+ "Error evaluating expression [%s] - User not logged in", expr));
+ throw new NotLoggedInException();
+ }
+ else
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
+ throw new AuthorizationException(String.format(
+ "Authorization check failed for expression [%s]", expr));
+ }
+ }
+ }
+
+ /**
+ * Attempts to authenticate the user. This method is distinct to the
+ * authenticate() method in that it raises events in response to whether
+ * authentication is successful or not. The following events may be raised
+ * by calling login():
+ *
+ * org.jboss.seam.security.loginSuccessful - raised when authentication is successful
+ * org.jboss.seam.security.loginFailed - raised when authentication fails
+ * org.jboss.seam.security.alreadyLoggedIn - raised if the user is already authenticated
+ *
+ * @return String returns "loggedIn" if user is authenticated, or null if not.
+ */
+ public String login()
+ {
+ try
+ {
+ if (isLoggedIn())
+ {
+ // If authentication has already occurred during this request via a silent login,
+ // and login() is explicitly called then we still want to raise the LOGIN_SUCCESSFUL event,
+ // and then return.
+ if (Contexts.isEventContextActive() && Contexts.getEventContext().isSet(SILENT_LOGIN))
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_SUCCESSFUL);
+ return "loggedIn";
+ }
+
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_ALREADY_LOGGED_IN);
+ return "loggedIn";
+ }
+
+ authenticate();
+
+ if (!isLoggedIn())
+ {
+ throw new LoginException();
+ }
+
+ if ( log.isDebugEnabled() )
+ {
+ log.debug("Login successful for: " + getCredentials().getUsername());
+ }
+
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_SUCCESSFUL);
+ return "loggedIn";
+ }
+ catch (LoginException ex)
+ {
+ credentials.invalidate();
+
+ if ( log.isDebugEnabled() )
+ {
+ log.debug("Login failed for: " + getCredentials().getUsername(), ex);
+ }
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_FAILED, ex);
+ }
+
+ return null;
+ }
+
+ /**
+ * Attempts a quiet login, suppressing any login exceptions and not creating
+ * any faces messages. This method is intended to be used primarily as an
+ * internal API call, however has been made public for convenience.
+ */
+ public void quietLogin()
+ {
+ try
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_QUIET_LOGIN);
+
+ // Ensure that we haven't been authenticated as a result of the EVENT_QUIET_LOGIN event
+ if (!isLoggedIn())
+ {
+ if (credentials.isSet())
+ {
+ authenticate();
+ if (isLoggedIn() && Contexts.isEventContextActive())
+ {
+ Contexts.getEventContext().set(SILENT_LOGIN, true);
+ }
+ }
+ }
+ }
+ catch (LoginException ex)
+ {
+ credentials.invalidate();
+ }
+ }
+
+
+
+ /**
+ *
+ * @throws LoginException
+ */
+ public synchronized void authenticate()
+ throws LoginException
+ {
+ // If we're already authenticated, then don't authenticate again
+ if (!isLoggedIn() && !credentials.isInvalid())
+ {
+ principal = null;
+ subject = new Subject();
+ authenticate( getLoginContext() );
+ }
+ }
+
+
+ protected void authenticate(LoginContext loginContext)
+ throws LoginException
+ {
+ try
+ {
+ authenticating = true;
+ preAuthenticate();
+ loginContext.login();
+ postAuthenticate();
+ }
+ finally
+ {
+ // Set password to null whether authentication is successful or not
+ credentials.setPassword(null);
+ authenticating = false;
+ }
+ }
+
+ /**
+ * Clears any roles added by calling addRole() while not authenticated.
+ * This method may be overridden by a subclass if different
+ * pre-authentication logic should occur.
+ */
+ protected void preAuthenticate()
+ {
+ preAuthenticationRoles.clear();
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_PRE_AUTHENTICATE);
+ }
+
+ /**
+ * Extracts the principal from the subject, and populates the roles of the
+ * authenticated user. This method may be overridden by a subclass if
+ * different post-authentication logic should occur.
+ */
+ protected void postAuthenticate()
+ {
+ // Populate the working memory with the user's principals
+ for ( Principal p : getSubject().getPrincipals() )
+ {
+ if ( !(p instanceof Group))
+ {
+ if (principal == null)
+ {
+ principal = p;
+ break;
+ }
+ }
+ }
+
+ if (!preAuthenticationRoles.isEmpty() && isLoggedIn())
+ {
+ for (String role : preAuthenticationRoles)
+ {
+ addRole(role);
+ }
+ preAuthenticationRoles.clear();
+ }
+
+ credentials.setPassword(null);
+
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_POST_AUTHENTICATE, this);
+ }
+
+ /**
+ * Resets all security state and credentials
+ */
+ public void unAuthenticate()
+ {
+ principal = null;
+ subject = new Subject();
+
+ credentials.clear();
+ }
+
+ protected LoginContext getLoginContext() throws LoginException
+ {
+ if (getJaasConfigName() != null)
+ {
+ return new LoginContext(getJaasConfigName(), getSubject(),
+ credentials.createCallbackHandler());
+ }
+
+ return new LoginContext(Configuration.DEFAULT_JAAS_CONFIG_NAME, getSubject(),
+ credentials.createCallbackHandler(), Configuration.instance());
+ }
+
+ public void logout()
+ {
+ if (isLoggedIn())
+ {
+ unAuthenticate();
+ Session.instance().invalidate();
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGGED_OUT);
+ }
+ }
+
+ /**
+ * Checks if the authenticated user is a member of the specified role.
+ *
+ * @param role String The name of the role to check
+ * @return boolean True if the user is a member of the specified role
+ */
+ public boolean hasRole(String role)
+ {
+ if (!securityEnabled) return true;
+ if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
+
+ tryLogin();
+
+ for ( Group sg : getSubject().getPrincipals(Group.class) )
+ {
+ if ( ROLES_GROUP.equals( sg.getName() ) )
+ {
+ return sg.isMember( new Role(role) );
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Adds a role to the authenticated user. If the user is not logged in,
+ * the role will be added to a list of roles that will be granted to the
+ * user upon successful authentication, but only during the authentication
+ * process.
+ *
+ * @param role The name of the role to add
+ */
+ public boolean addRole(String role)
+ {
+ if (role == null || "".equals(role)) return false;
+
+ if (!isLoggedIn())
+ {
+ preAuthenticationRoles.add(role);
+ return false;
+ }
+ else
+ {
+ for ( Group sg : getSubject().getPrincipals(Group.class) )
+ {
+ if ( ROLES_GROUP.equals( sg.getName() ) )
+ {
+ return sg.addMember(new Role(role));
+ }
+ }
+
+ SimpleGroup roleGroup = new SimpleGroup(ROLES_GROUP);
+ roleGroup.addMember(new Role(role));
+ getSubject().getPrincipals().add(roleGroup);
+ return true;
+ }
+ }
+
+ /**
+ * Removes a role from the authenticated user
+ *
+ * @param role The name of the role to remove
+ */
+ public void removeRole(String role)
+ {
+ for ( Group sg : getSubject().getPrincipals(Group.class) )
+ {
+ if ( ROLES_GROUP.equals( sg.getName() ) )
+ {
+ Enumeration e = sg.members();
+ while (e.hasMoreElements())
+ {
+ Principal member = (Principal) e.nextElement();
+ if (member.getName().equals(role))
+ {
+ sg.removeMember(member);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+
+ /**
+ * Checks that the current authenticated user is a member of
+ * the specified role.
+ *
+ * @param role String The name of the role to check
+ * @throws AuthorizationException if the authenticated user is not a member of the role
+ */
+ public void checkRole(String role)
+ {
+ tryLogin();
+
+ if ( !hasRole(role) )
+ {
+ if ( !isLoggedIn() )
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
+ throw new NotLoggedInException();
+ }
+ else
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
+ throw new AuthorizationException(String.format(
+ "Authorization check failed for role [%s]", role));
+ }
+ }
+ }
+
+ /**
+ * Checks that the current authenticated user has permission for
+ * the specified name and action
+ *
+ * @param name String The permission name
+ * @param action String The permission action
+ * @param arg Object Optional object parameter used to make a permission decision
+ * @throws AuthorizationException if the user does not have the specified permission
+ */
+ public void checkPermission(String name, String action, Object...arg)
+ {
+ if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return;
+
+ tryLogin();
+
+ if ( !hasPermission(name, action, arg) )
+ {
+ if ( !isLoggedIn() )
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
+ throw new NotLoggedInException();
+ }
+ else
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
+ throw new AuthorizationException(String.format(
+ "Authorization check failed for permission [%s,%s]", name, action));
+ }
+ }
+ }
+
+ public void checkPermission(Object target, String action)
+ {
+ if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return;
+
+ tryLogin();
+
+ if ( !hasPermission(target, action) )
+ {
+ if ( !isLoggedIn() )
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
+ throw new NotLoggedInException();
+ }
+ else
+ {
+ if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
+ throw new AuthorizationException(String.format(
+ "Authorization check failed for permission[%s,%s]", target, action));
+ }
+ }
+ }
+
+ /**
+ * Performs a permission check for the specified name and action
+ *
+ * @param name String The permission name
+ * @param action String The permission action
+ * @param arg Object Optional object parameter used to make a permission decision
+ * @return boolean True if the user has the specified permission
+ */
+ public boolean hasPermission(String name, String action, Object...arg)
+ {
+ if (!securityEnabled) return true;
+ if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
+ if (permissionMapper == null) return false;
+
+ if (arg != null)
+ {
+ return permissionMapper.resolvePermission(arg[0], action);
+ }
+ else
+ {
+ return permissionMapper.resolvePermission(name, action);
+ }
+ }
+
+ public void filterByPermission(Collection collection, String action)
+ {
+ permissionMapper.filterByPermission(collection, action);
+ }
+
+ public boolean hasPermission(Object target, String action)
+ {
+ if (!securityEnabled) return true;
+ if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
+ if (permissionMapper == null) return false;
+ if (target == null) return false;
+
+ return permissionMapper.resolvePermission(target, action);
+ }
+
+ /**
+ * Evaluates the specified security expression, which must return a boolean
+ * value.
+ *
+ * @param expr String The expression to evaluate
+ * @return boolean The result of the expression evaluation
+ */
+ protected boolean evaluateExpression(String expr)
+ {
+ return Expressions.instance().createValueExpression(expr, Boolean.class).getValue();
+ }
+
+ /**
+ * @see org.jboss.seam.security.Credentials#getUsername()
+ */
+ @Deprecated
+ public String getUsername()
+ {
+ return credentials.getUsername();
+ }
+
+ /**
+ * @see org.jboss.seam.security.Credentials#setUsername(String)
+ */
+ @Deprecated
+ public void setUsername(String username)
+ {
+ credentials.setUsername(username);
+ }
+
+ /**
+ * @see org.jboss.seam.security.Credentials#getPassword()
+ */
+ @Deprecated
+ public String getPassword()
+ {
+ return credentials.getPassword();
+ }
+
+ /**
+ * @see org.jboss.seam.security.Credentials#setPassword(String)
+ */
+ @Deprecated
+ public void setPassword(String password)
+ {
+ credentials.setPassword(password);
+ }
+
+ /**
+ * @see org.jboss.seam.security.RememberMe#isEnabled()
+ */
+ @Deprecated
+ public boolean isRememberMe()
+ {
+ return rememberMe != null ? rememberMe.isEnabled() : false;
+ }
+
+ /**
+ * @see org.jboss.seam.security.RememberMe#setEnabled(boolean)
+ */
+ @Deprecated
+ public void setRememberMe(boolean remember)
+ {
+ if (rememberMe != null) rememberMe.setEnabled(remember);
+ }
+
+ public Credentials getCredentials()
+ {
+ return credentials;
+ }
+
+ public MethodExpression getAuthenticateMethod()
+ {
+ return authenticateMethod;
+ }
+
+ public void setAuthenticateMethod(MethodExpression authMethod)
+ {
+ this.authenticateMethod = authMethod;
+ }
+
+ public String getJaasConfigName()
+ {
+ return jaasConfigName;
+ }
+
+ public void setJaasConfigName(String jaasConfigName)
+ {
+ this.jaasConfigName = jaasConfigName;
+ }
+
+ synchronized void runAs(RunAsOperation operation)
+ {
+ Principal savedPrincipal = getPrincipal();
+ Subject savedSubject = getSubject();
+
+ try
+ {
+ principal = operation.getPrincipal();
+ subject = operation.getSubject();
+
+ if (systemOp == null)
+ {
+ systemOp = new ThreadLocal<Boolean>();
+ }
+
+ systemOp.set(operation.isSystemOperation());
+
+ operation.execute();
+ }
+ finally
+ {
+ systemOp.set(false);
+ principal = savedPrincipal;
+ subject = savedSubject;
+ }
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Identity.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/JpaTokenStore.java (from rev 10443, trunk/src/main/org/jboss/seam/security/JpaTokenStore.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/JpaTokenStore.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/JpaTokenStore.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,165 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.APPLICATION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.io.Serializable;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.annotations.security.TokenUsername;
+import org.jboss.seam.annotations.security.TokenValue;
+import org.jboss.seam.core.Expressions;
+import org.jboss.seam.core.Expressions.ValueExpression;
+import org.jboss.seam.security.management.IdentityManagementException;
+import org.jboss.seam.util.AnnotatedBeanProperty;
+
+/**
+ * A TokenStore implementation, stores tokens inside a database table.
+ *
+ * @author Shane Bryzak
+ */
+ at Name("org.jboss.seam.security.tokenStore")
+ at Install(precedence = BUILT_IN, value=false)
+ at Scope(APPLICATION)
+ at BypassInterceptors
+public class JpaTokenStore implements TokenStore, Serializable
+{
+ private Class tokenClass;
+
+ private ValueExpression<EntityManager> entityManager;
+
+ private AnnotatedBeanProperty<TokenUsername> tokenUsernameProperty;
+ private AnnotatedBeanProperty<TokenValue> tokenValueProperty;
+
+ @Create
+ public void create()
+ {
+ if (entityManager == null)
+ {
+ entityManager = Expressions.instance().createValueExpression("#{entityManager}", EntityManager.class);
+ }
+
+ tokenUsernameProperty = new AnnotatedBeanProperty<TokenUsername>(tokenClass, TokenUsername.class);
+ tokenValueProperty = new AnnotatedBeanProperty<TokenValue>(tokenClass, TokenValue.class);
+
+ if (!tokenUsernameProperty.isSet())
+ {
+ throw new IllegalStateException("Invalid tokenClass " + tokenClass.getName() +
+ " - required annotation @TokenUsername not found on any Field or Method.");
+ }
+
+ if (!tokenValueProperty.isSet())
+ {
+ throw new IllegalStateException("Invalid tokenClass " + tokenClass.getName() +
+ " - required annotation @TokenValue not found on any Field or Method.");
+ }
+ }
+
+ public void createToken(String username, String value)
+ {
+ if (tokenClass == null)
+ {
+ throw new IllegalStateException("Could not create token, tokenClass not set");
+ }
+
+ try
+ {
+ Object token = tokenClass.newInstance();
+
+ tokenUsernameProperty.setValue(token, username);
+ tokenValueProperty.setValue(token, value);
+
+ lookupEntityManager().persist(token);
+ }
+ catch (Exception ex)
+ {
+ if (ex instanceof IdentityManagementException)
+ {
+ throw (IdentityManagementException) ex;
+ }
+ else
+ {
+ throw new IdentityManagementException("Could not create account", ex);
+ }
+ }
+ }
+
+ public boolean validateToken(String username, String value)
+ {
+ return lookupToken(username, value) != null;
+ }
+
+ public void invalidateToken(String username, String value)
+ {
+ Object token = lookupToken(username, value);
+ if (token != null)
+ {
+ lookupEntityManager().remove(token);
+ }
+ }
+
+ public void invalidateAll(String username)
+ {
+ Query query = lookupEntityManager().createQuery(
+ "select t from " + tokenClass.getName() + " t where " + tokenUsernameProperty.getName() +
+ " = :username")
+ .setParameter("username", username);
+
+ for (Object token : query.getResultList())
+ {
+ lookupEntityManager().remove(token);
+ }
+ }
+
+ public Object lookupToken(String username, String value)
+ {
+ try
+ {
+ Object token = lookupEntityManager().createQuery(
+ "select t from " + tokenClass.getName() + " t where " + tokenUsernameProperty.getName() +
+ " = :username and " + tokenValueProperty.getName() + " = :value")
+ .setParameter("username", username)
+ .setParameter("value", value)
+ .getSingleResult();
+
+ return token;
+ }
+ catch (NoResultException ex)
+ {
+ return null;
+ }
+ }
+
+ public Class getTokenClass()
+ {
+ return tokenClass;
+ }
+
+ public void setTokenClass(Class tokenClass)
+ {
+ this.tokenClass = tokenClass;
+ }
+
+ private EntityManager lookupEntityManager()
+ {
+ return entityManager.getValue();
+ }
+
+ public ValueExpression getEntityManager()
+ {
+ return entityManager;
+ }
+
+ public void setEntityManager(ValueExpression expression)
+ {
+ this.entityManager = expression;
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/JpaTokenStore.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/NotLoggedInException.java (from rev 10443, trunk/src/main/org/jboss/seam/security/NotLoggedInException.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/NotLoggedInException.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/NotLoggedInException.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,11 @@
+package org.jboss.seam.security;
+
+import javax.ejb.ApplicationException;
+
+/**
+ * Thrown when an unauthenticated user attempts to execute a restricted action.
+ *
+ * @author Shane Bryzak
+ */
+ at ApplicationException(rollback=true)
+public class NotLoggedInException extends RuntimeException {}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/NotLoggedInException.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RememberMe.java (from rev 10443, trunk/src/main/org/jboss/seam/security/RememberMe.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RememberMe.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RememberMe.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,410 @@
+package org.jboss.seam.security;
+
+import static org.jboss.seam.ScopeType.SESSION;
+import static org.jboss.seam.annotations.Install.BUILT_IN;
+
+import java.io.Serializable;
+import java.rmi.server.UID;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Random;
+
+import javax.faces.context.FacesContext;
+
+import org.jboss.seam.Component;
+import org.jboss.seam.annotations.Create;
+import org.jboss.seam.annotations.Install;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Observer;
+import org.jboss.seam.annotations.Scope;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.faces.Selector;
+import org.jboss.seam.security.management.IdentityManager;
+import org.jboss.seam.util.Base64;
+
+/**
+ * Remember-me functionality is provided by this class, in two different flavours. The first mode
+ * provides username-only persistence, and is considered to be secure as the user (or their browser)
+ * is still required to provide a password. The second mode provides an auto-login feature, however
+ * is NOT considered to be secure and is vulnerable to XSS attacks compromising the user's account.
+ *
+ * Use the auto-login mode with caution!
+ *
+ * @author Shane Bryzak
+ */
+ at Name("org.jboss.seam.security.rememberMe")
+ at Scope(SESSION)
+ at Install(precedence = BUILT_IN, classDependencies = "javax.faces.context.FacesContext")
+ at BypassInterceptors
+public class RememberMe implements Serializable
+{
+ class UsernameSelector extends Selector
+ {
+ @Override
+ public String getCookieName()
+ {
+ return "org.jboss.seam.security.username";
+ }
+
+ @Override
+ public void setDirty()
+ {
+ super.setDirty();
+ }
+
+ @Override
+ public String getCookieValue()
+ {
+ return super.getCookieValue();
+ }
+
+ @Override
+ public void clearCookieValue()
+ {
+ super.clearCookieValue();
+ }
+
+ @Override
+ public void setCookieValueIfEnabled(String value)
+ {
+ super.setCookieValueIfEnabled(value);
+ }
+ }
+
+ class TokenSelector extends UsernameSelector
+ {
+ @Override
+ public String getCookieName()
+ {
+ return "org.jboss.seam.security.authtoken";
+ }
+ }
+
+ private class DecodedToken
+ {
+ private String username;
+ private String value;
+
+ public DecodedToken(String cookieValue)
+ {
+ if (cookieValue != null)
+ {
+ try
+ {
+ String decoded = new String(Base64.decode(cookieValue));
+ username = decoded.substring(0, decoded.indexOf(':'));
+ value = decoded.substring(decoded.indexOf(':') + 1);
+ }
+ catch (Exception ex)
+ {
+ // swallow
+ }
+ }
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+
+ private UsernameSelector usernameSelector;
+
+ private TokenSelector tokenSelector;
+ private TokenStore tokenStore;
+
+ private boolean enabled;
+
+ private int cookieMaxAge = Selector.DEFAULT_MAX_AGE;
+
+ private boolean autoLoggedIn;
+
+ private Random random = new Random(System.currentTimeMillis());
+
+ public enum Mode { disabled, usernameOnly, autoLogin}
+
+ private Mode mode = Mode.usernameOnly;
+
+ public Mode getMode()
+ {
+ return mode;
+ }
+
+ public void setMode(Mode mode)
+ {
+ this.mode = mode;
+ }
+
+ public boolean isEnabled()
+ {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled)
+ {
+ if (this.enabled != enabled)
+ {
+ this.enabled = enabled;
+ // selector is null during component initialization (setup handled in @Create method)
+ if (usernameSelector != null && mode.equals(Mode.usernameOnly))
+ {
+ usernameSelector.setCookieEnabled(enabled);
+ usernameSelector.setDirty();
+ }
+ // selector is null during component initialization (setup handled in @Create method)
+ else if (tokenSelector != null && mode.equals(Mode.autoLogin))
+ {
+ tokenSelector.setCookieEnabled(enabled);
+ tokenSelector.setDirty();
+ }
+ }
+ }
+
+ public int getCookieMaxAge() {
+ return cookieMaxAge;
+ }
+
+ public void setCookieMaxAge(int cookieMaxAge) {
+ this.cookieMaxAge = cookieMaxAge;
+ }
+
+ public TokenStore getTokenStore()
+ {
+ return tokenStore;
+ }
+
+ public void setTokenStore(TokenStore tokenStore)
+ {
+ this.tokenStore = tokenStore;
+ }
+
+ @Create
+ public void create()
+ {
+ if (mode.equals(Mode.usernameOnly))
+ {
+ usernameSelector = new UsernameSelector();
+ usernameSelector.setCookieEnabled(enabled);
+ }
+ else if (mode.equals(Mode.autoLogin))
+ {
+ tokenSelector = new TokenSelector();
+ tokenSelector.setCookieEnabled(enabled);
+
+ // Default to JpaTokenStore
+ if (tokenStore == null)
+ {
+ tokenStore = (TokenStore) Component.getInstance(JpaTokenStore.class, true);
+ }
+ }
+ }
+
+ protected String generateTokenValue()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(new UID().toString());
+ sb.append(":");
+ sb.append(random.nextLong());
+ return sb.toString();
+ }
+
+ protected String encodeToken(String username, String value)
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append(username);
+ sb.append(":");
+ sb.append(value);
+ return Base64.encodeBytes(sb.toString().getBytes());
+ }
+
+ public String getCookiePath()
+ {
+ FacesContext ctx = FacesContext.getCurrentInstance();
+ return ctx != null ? ctx.getExternalContext().getRequestContextPath() : null;
+ }
+
+ @Observer(Credentials.EVENT_INIT_CREDENTIALS)
+ public void initCredentials(Credentials credentials)
+ {
+ String cookiePath = getCookiePath();
+
+ if (mode.equals(Mode.usernameOnly))
+ {
+ if (cookiePath != null)
+ {
+ usernameSelector.setCookiePath(cookiePath);
+ }
+
+ String username = usernameSelector.getCookieValue();
+ if (username!=null)
+ {
+ setEnabled(true);
+ credentials.setUsername(username);
+ }
+
+ usernameSelector.setDirty();
+ }
+ else if (mode.equals(Mode.autoLogin))
+ {
+ if (cookiePath != null)
+ {
+ tokenSelector.setCookiePath(cookiePath);
+ }
+
+ String token = tokenSelector.getCookieValue();
+ if (token != null)
+ {
+ setEnabled(true);
+
+ DecodedToken decoded = new DecodedToken(token);
+
+ if (tokenStore.validateToken(decoded.getUsername(), decoded.getValue()))
+ {
+ credentials.setUsername(decoded.getUsername());
+ credentials.setPassword(decoded.getValue());
+ }
+ else
+ {
+ // Have we been compromised? Just in case, invalidate all authentication tokens
+ tokenStore.invalidateAll(decoded.getUsername());
+ }
+ }
+ }
+ }
+
+ /**
+ * I hate these hacks...
+ */
+ private class BoolWrapper
+ {
+ boolean value;
+ }
+
+ @Observer(Identity.EVENT_QUIET_LOGIN)
+ public void quietLogin()
+ {
+ final Identity identity = Identity.instance();
+
+ if (mode.equals(Mode.autoLogin) && isEnabled())
+ {
+ final String username = identity.getCredentials().getUsername();
+ final BoolWrapper userEnabled = new BoolWrapper();
+ final List<String> roles = new ArrayList<String>();
+
+ // Double check our credentials again
+ if (tokenStore.validateToken(username, identity.getCredentials().getPassword()))
+ {
+ new RunAsOperation(true) {
+ @Override
+ public void execute()
+ {
+ if (IdentityManager.instance().isUserEnabled(username))
+ {
+ userEnabled.value = true;
+
+ for (String role : IdentityManager.instance().getImpliedRoles(username))
+ {
+ roles.add(role);
+ }
+ }
+ }
+ }.run();
+
+ if (userEnabled.value)
+ {
+ identity.unAuthenticate();
+ identity.preAuthenticate();
+
+ // populate the roles
+ for (String role : roles)
+ {
+ identity.addRole(role);
+ }
+
+ // Set the principal
+ identity.getSubject().getPrincipals().add(new SimplePrincipal(username));
+ identity.postAuthenticate();
+
+ autoLoggedIn = true;
+ }
+ }
+ }
+ }
+
+ @Observer(Identity.EVENT_LOGGED_OUT)
+ public void loggedOut()
+ {
+ if (mode.equals(Mode.autoLogin))
+ {
+ tokenSelector.clearCookieValue();
+ }
+ }
+
+ @Observer(Identity.EVENT_POST_AUTHENTICATE)
+ public void postAuthenticate(Identity identity)
+ {
+ if (mode.equals(Mode.usernameOnly))
+ {
+ // Password is set to null during authentication, so we set dirty
+ usernameSelector.setDirty();
+
+ if ( !enabled )
+ {
+ usernameSelector.clearCookieValue();
+ }
+ else
+ {
+ usernameSelector.setCookieMaxAge(cookieMaxAge);
+ usernameSelector.setCookieValueIfEnabled( Identity.instance().getCredentials().getUsername() );
+ }
+ }
+ else if (mode.equals(Mode.autoLogin))
+ {
+ tokenSelector.setDirty();
+
+ DecodedToken decoded = new DecodedToken(tokenSelector.getCookieValue());
+
+ // Invalidate the current token (if it exists) whether enabled or not
+ if (decoded.getUsername() != null)
+ {
+ tokenStore.invalidateToken(decoded.getUsername(), decoded.getValue());
+ }
+
+ if ( !enabled )
+ {
+ tokenSelector.clearCookieValue();
+ }
+ else
+ {
+ String value = generateTokenValue();
+ tokenStore.createToken(identity.getPrincipal().getName(), value);
+ tokenSelector.setCookieEnabled(enabled);
+ tokenSelector.setCookieMaxAge(cookieMaxAge);
+ tokenSelector.setCookieValueIfEnabled(encodeToken(identity.getPrincipal().getName(), value));
+ }
+ }
+ }
+
+ @Observer(Credentials.EVENT_CREDENTIALS_UPDATED)
+ public void credentialsUpdated()
+ {
+ if (mode.equals(Mode.usernameOnly))
+ {
+ usernameSelector.setDirty();
+ }
+ }
+
+ /**
+ * A flag that an application can use to protect sensitive operations if the user has been
+ * auto-authenticated.
+ */
+ public boolean isAutoLoggedIn()
+ {
+ return autoLoggedIn;
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RememberMe.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Role.java (from rev 10443, trunk/src/main/org/jboss/seam/security/Role.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Role.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Role.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,28 @@
+package org.jboss.seam.security;
+
+/**
+ * Represents a user role. A conditional role is a special type of role that is assigned to a user
+ * based on the contextual state of a permission check.
+ *
+ * @author Shane Bryzak
+ */
+public class Role extends SimplePrincipal
+{
+ private boolean conditional;
+
+ public Role(String name)
+ {
+ super(name);
+ }
+
+ public Role(String name, boolean conditional)
+ {
+ this(name);
+ this.conditional = conditional;
+ }
+
+ public boolean isConditional()
+ {
+ return conditional;
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/Role.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RunAsOperation.java (from rev 10443, trunk/src/main/org/jboss/seam/security/RunAsOperation.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RunAsOperation.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RunAsOperation.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,77 @@
+package org.jboss.seam.security;
+
+import java.security.Principal;
+import java.security.acl.Group;
+
+import javax.security.auth.Subject;
+
+/**
+ * Defines a security operation that can be executed within a particular
+ * security context.
+ *
+ * @author Shane Bryzak
+ */
+public abstract class RunAsOperation
+{
+ private Principal principal;
+ private Subject subject;
+
+ private boolean systemOp = false;
+
+ public RunAsOperation()
+ {
+ principal = new SimplePrincipal(null);
+ subject = new Subject();
+ }
+
+ /**
+ * A system operation allows any security checks to pass
+ *
+ * @param systemOp
+ */
+ public RunAsOperation(boolean systemOp)
+ {
+ this();
+ this.systemOp = systemOp;
+ }
+
+ public abstract void execute();
+
+ public Principal getPrincipal()
+ {
+ return principal;
+ }
+
+ public Subject getSubject()
+ {
+ return subject;
+ }
+
+ public RunAsOperation addRole(String role)
+ {
+ for ( Group sg : getSubject().getPrincipals(Group.class) )
+ {
+ if ( Identity.ROLES_GROUP.equals( sg.getName() ) )
+ {
+ sg.addMember(new SimplePrincipal(role));
+ break;
+ }
+ }
+
+ SimpleGroup roleGroup = new SimpleGroup(Identity.ROLES_GROUP);
+ roleGroup.addMember(new SimplePrincipal(role));
+ getSubject().getPrincipals().add(roleGroup);
+
+ return this;
+ }
+
+ public boolean isSystemOperation()
+ {
+ return systemOp;
+ }
+
+ public void run()
+ {
+ Identity.instance().runAs(this);
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/RunAsOperation.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityFunctions.java (from rev 10443, trunk/src/main/org/jboss/seam/security/SecurityFunctions.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityFunctions.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityFunctions.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,31 @@
+package org.jboss.seam.security;
+
+/**
+ * Delegating wrapper for EL security functions.
+ *
+ * @author Shane Bryzak
+ */
+public class SecurityFunctions
+{
+ public static boolean hasRole(String name)
+ {
+ return Identity.instance().hasRole(name);
+ }
+
+ public static boolean hasPermission(String name, String action, Object arg)
+ {
+ if (arg != null)
+ {
+ return Identity.instance().hasPermission(name, action, arg);
+ }
+ else
+ {
+ return Identity.instance().hasPermission(name, action);
+ }
+ }
+
+ public static boolean hasPermission(Object target, String action)
+ {
+ return Identity.instance().hasPermission(target, action);
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityFunctions.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityInterceptor.java (from rev 10443, trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityInterceptor.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityInterceptor.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,301 @@
+package org.jboss.seam.security;
+
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.seam.annotations.intercept.AroundInvoke;
+import org.jboss.seam.annotations.intercept.Interceptor;
+import org.jboss.seam.annotations.intercept.InterceptorType;
+import org.jboss.seam.annotations.security.PermissionCheck;
+import org.jboss.seam.annotations.security.Restrict;
+import org.jboss.seam.annotations.security.RoleCheck;
+import org.jboss.seam.async.AsynchronousInterceptor;
+import org.jboss.seam.intercept.AbstractInterceptor;
+import org.jboss.seam.intercept.InvocationContext;
+import org.jboss.seam.transaction.RollbackInterceptor;
+import org.jboss.seam.util.Strings;
+
+/**
+ * Provides authorization services for component invocations.
+ *
+ * @author Shane Bryzak
+ */
+ at Interceptor(type=InterceptorType.CLIENT,
+ around=AsynchronousInterceptor.class, within = RollbackInterceptor.class)
+public class SecurityInterceptor extends AbstractInterceptor implements Serializable
+{
+ private static final long serialVersionUID = -6567750187000766925L;
+
+ /**
+ * You may encounter a JVM bug where the field initializer is not evaluated for a transient field after deserialization.
+ * @see "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6252102"
+ */
+ private transient volatile Map<Method,Restriction> restrictions = new HashMap<Method,Restriction>();
+
+ private class Restriction
+ {
+ private String expression;
+
+ private String permissionTarget;
+ private String permissionAction;
+
+ private Map<String, Object> methodRestrictions;
+ private Map<Integer,Set<String>> paramRestrictions;
+ private Set<String> roleRestrictions;
+
+ public void setExpression(String expression)
+ {
+ this.expression = expression;
+ }
+
+ public void setPermissionTarget(String target)
+ {
+ this.permissionTarget = target;
+ }
+
+ public void setPermissionAction(String action)
+ {
+ this.permissionAction = action;
+ }
+
+ public void addMethodRestriction(Object target, String action)
+ {
+ if (methodRestrictions == null)
+ {
+ methodRestrictions = new HashMap<String, Object>();
+ }
+
+ methodRestrictions.put(action, target);
+ }
+
+ public void addRoleRestriction(String role)
+ {
+ if (roleRestrictions == null)
+ {
+ roleRestrictions = new HashSet<String>();
+ }
+
+ roleRestrictions.add(role);
+ }
+
+ public void addParameterRestriction(int index, String action)
+ {
+ Set<String> actions = null;
+
+ if (paramRestrictions == null)
+ {
+ paramRestrictions = new HashMap<Integer,Set<String>>();
+ }
+
+ if (!paramRestrictions.containsKey(index))
+ {
+ actions = new HashSet<String>();
+ paramRestrictions.put(index, actions);
+ }
+ else
+ {
+ actions = paramRestrictions.get(index);
+ }
+
+ actions.add(action);
+ }
+
+ public void check(Object[] parameters)
+ {
+ if (Identity.isSecurityEnabled())
+ {
+ if (expression != null)
+ {
+ Identity.instance().checkRestriction(expression);
+ }
+
+ if (methodRestrictions != null)
+ {
+ for (String action : methodRestrictions.keySet())
+ {
+ Identity.instance().checkPermission(methodRestrictions.get(action), action);
+ }
+ }
+
+ if (paramRestrictions != null)
+ {
+ for (Integer idx : paramRestrictions.keySet())
+ {
+ Set<String> actions = paramRestrictions.get(idx);
+ for (String action : actions)
+ {
+ Identity.instance().checkPermission(parameters[idx], action);
+ }
+ }
+ }
+
+ if (roleRestrictions != null)
+ {
+ for (String role : roleRestrictions)
+ {
+ Identity.instance().checkRole(role);
+ }
+ }
+
+ if (permissionTarget != null && permissionAction != null)
+ {
+ Identity.instance().checkPermission(permissionTarget, permissionAction);
+ }
+ }
+ }
+ }
+
+ @AroundInvoke
+ public Object aroundInvoke(InvocationContext invocation) throws Exception
+ {
+ Method interfaceMethod = invocation.getMethod();
+
+ if (!"hashCode".equals(interfaceMethod.getName()))
+ {
+ Restriction restriction = getRestriction(interfaceMethod);
+ if ( restriction != null ) restriction.check(invocation.getParameters());
+ }
+
+ return invocation.proceed();
+ }
+
+ private Restriction getRestriction(Method interfaceMethod) throws Exception
+ {
+ // see field declaration as to why this is done
+ if (restrictions == null)
+ {
+ synchronized(this)
+ {
+ restrictions = new HashMap<Method, Restriction>();
+ }
+ }
+
+ if (!restrictions.containsKey(interfaceMethod))
+ {
+ synchronized(restrictions)
+ {
+ // FIXME this logic should be abstracted rather than sitting in the middle of this interceptor
+ if (!restrictions.containsKey(interfaceMethod))
+ {
+ Restriction restriction = null;
+
+ Method method = getComponent().getBeanClass().getMethod(
+ interfaceMethod.getName(), interfaceMethod.getParameterTypes() );
+
+ Restrict restrict = null;
+
+ if ( method.isAnnotationPresent(Restrict.class) )
+ {
+ restrict = method.getAnnotation(Restrict.class);
+ }
+ else if ( getComponent().getBeanClass().isAnnotationPresent(Restrict.class) )
+ {
+ if ( !getComponent().isLifecycleMethod(method) )
+ {
+ restrict = getComponent().getBeanClass().getAnnotation(Restrict.class);
+ }
+ }
+
+ if (restrict != null)
+ {
+ if (restriction == null) restriction = new Restriction();
+
+ if ( Strings.isEmpty(restrict.value()) )
+ {
+ restriction.setPermissionTarget(getComponent().getName());
+ restriction.setPermissionAction(method.getName());
+ }
+ else
+ {
+ restriction.setExpression(restrict.value());
+ }
+ }
+
+ for (Annotation annotation : method.getDeclaringClass().getAnnotations())
+ {
+ if (annotation.annotationType().isAnnotationPresent(RoleCheck.class))
+ {
+ if (restriction == null) restriction = new Restriction();
+ restriction.addRoleRestriction(annotation.annotationType().getSimpleName().toLowerCase());
+ }
+ }
+
+ for (Annotation annotation : method.getAnnotations())
+ {
+ if (annotation.annotationType().isAnnotationPresent(PermissionCheck.class))
+ {
+ PermissionCheck permissionCheck = annotation.annotationType().getAnnotation(
+ PermissionCheck.class);
+
+ Method valueMethod = null;
+ for (Method m : annotation.annotationType().getDeclaredMethods())
+ {
+ valueMethod = m;
+ break;
+ }
+
+ if (valueMethod != null)
+ {
+ if (restriction == null) restriction = new Restriction();
+ Object target = valueMethod.invoke(annotation);
+ if (!target.equals(void.class))
+ {
+ if (restriction == null) restriction = new Restriction();
+ restriction.addMethodRestriction(target,
+ getPermissionAction(permissionCheck, annotation));
+ }
+ }
+ }
+ if (annotation.annotationType().isAnnotationPresent(RoleCheck.class))
+ {
+ if (restriction == null) restriction = new Restriction();
+ restriction.addRoleRestriction(annotation.annotationType().getSimpleName().toLowerCase());
+ }
+ }
+
+ for (int i = 0; i < method.getParameterAnnotations().length; i++)
+ {
+ Annotation[] annotations = method.getParameterAnnotations()[i];
+ for (Annotation annotation : annotations)
+ {
+ if (annotation.annotationType().isAnnotationPresent(PermissionCheck.class))
+ {
+ PermissionCheck permissionCheck = annotation.annotationType().getAnnotation(
+ PermissionCheck.class);
+ if (restriction == null) restriction = new Restriction();
+ restriction.addParameterRestriction(i,
+ getPermissionAction(permissionCheck, annotation));
+ }
+ }
+ }
+
+ restrictions.put(interfaceMethod, restriction);
+ return restriction;
+ }
+ }
+ }
+ return restrictions.get(interfaceMethod);
+ }
+
+ private String getPermissionAction(PermissionCheck check, Annotation annotation)
+ {
+ if (!"".equals(check.value()))
+ {
+ return check.value();
+ }
+ else
+ {
+ return annotation.annotationType().getSimpleName().toLowerCase();
+ }
+ }
+
+ public boolean isInterceptorEnabled()
+ {
+ return getComponent().isSecure() && !getComponent().beanClassHasAnnotation("javax.jws.WebService");
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SecurityInterceptor.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimpleGroup.java (from rev 10443, trunk/src/main/org/jboss/seam/security/SimpleGroup.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimpleGroup.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimpleGroup.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,93 @@
+package org.jboss.seam.security;
+
+import java.io.Serializable;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Implementation of the Group interface, used for holding roles etc.
+ *
+ * @author Shane Bryzak
+ */
+public class SimpleGroup implements Group, Serializable
+{
+ private static final long serialVersionUID = 5766373925836425908L;
+
+ /**
+ * The name of the group
+ */
+ private String name;
+
+ /**
+ * The members of this group
+ */
+ private Set<Principal> members = new HashSet<Principal>();
+
+ public SimpleGroup(String name)
+ {
+ this.name = name;
+ }
+
+ public boolean addMember(Principal user)
+ {
+ return members.add(user);
+ }
+
+ public boolean isMember(Principal member)
+ {
+ if ( members.contains(member) )
+ {
+ return true;
+ }
+ else
+ {
+ for (Principal m : members)
+ {
+ if (m instanceof Group && ((Group) m).isMember(member))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public Enumeration<? extends Principal> members()
+ {
+ return Collections.enumeration(members);
+ }
+
+ public boolean removeMember(Principal user)
+ {
+ return members.remove(user);
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof SimpleGroup)
+ {
+ SimpleGroup other = (SimpleGroup) obj;
+ return other.name.equals(name);
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return name.hashCode();
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimpleGroup.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimplePrincipal.java (from rev 10443, trunk/src/main/org/jboss/seam/security/SimplePrincipal.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimplePrincipal.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimplePrincipal.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,54 @@
+package org.jboss.seam.security;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+/**
+ * Simple implementation of the Principal interface, supporting a named user.
+ *
+ * @author Shane Bryzak
+ */
+public class SimplePrincipal implements Principal, Serializable
+{
+ private static final long serialVersionUID = 5609375932836425908L;
+
+ private String name;
+
+ public SimplePrincipal(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj instanceof Principal)
+ {
+ Principal other = (Principal) obj;
+ return name == null ?
+ other.getName() == null :
+ name.equals( other.getName() );
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return name != null ? name.hashCode() : super.hashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/SimplePrincipal.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/TokenStore.java (from rev 10443, trunk/src/main/org/jboss/seam/security/TokenStore.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/TokenStore.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/TokenStore.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,15 @@
+package org.jboss.seam.security;
+
+/**
+ * A store containing user authentication tokens. Used in conjunction with the RememberMe
+ * component to auto-login users that present a valid cookie-based token.
+ *
+ * @author Shane Bryzak
+ */
+public interface TokenStore
+{
+ void createToken(String username, String value);
+ boolean validateToken(String username, String value);
+ void invalidateToken(String username, String value);
+ void invalidateAll(String username);
+}
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/TokenStore.java
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/crypto (from rev 10443, trunk/src/main/org/jboss/seam/security/crypto)
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/crypto
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/digest (from rev 10443, trunk/src/main/org/jboss/seam/security/digest)
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/digest
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/jaas (from rev 10443, trunk/src/main/org/jboss/seam/security/jaas)
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/jaas
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/management (from rev 10443, trunk/src/main/org/jboss/seam/security/management)
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/management
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/openid (from rev 10443, trunk/src/main/org/jboss/seam/security/openid)
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/openid
___________________________________________________________________
Name: svn:mergeinfo
+
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/package-info.java (from rev 10443, trunk/src/main/org/jboss/seam/security/package-info.java)
===================================================================
--- trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/package-info.java (rev 0)
+++ trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/package-info.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -0,0 +1,12 @@
+/**
+ * Seam Security
+ *
+ * @see org.jboss.seam.security.Identity
+ * @see org.jboss.seam.annotations.security.Restrict
+ */
+ at Namespace(value="http://jboss.com/products/seam/security", prefix="org.jboss.seam.security")
+ at AutoCreate
+package org.jboss.seam.security;
+
+import org.jboss.seam.annotations.AutoCreate;
+import org.jboss.seam.annotations.Namespace;
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/package-info.java
___________________________________________________________________
Name: svn:keywords
+ Author Date Id Revision
Name: svn:mergeinfo
+
Name: svn:eol-style
+ native
Copied: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/permission (from rev 10443, trunk/src/main/org/jboss/seam/security/permission)
Property changes on: trunk/modules/trunk/security/src/main/java/org/jboss/seam/security/permission
___________________________________________________________________
Name: svn:mergeinfo
+
Deleted: trunk/src/main/org/jboss/seam/security/AuthorizationException.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/AuthorizationException.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/AuthorizationException.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,17 +0,0 @@
-package org.jboss.seam.security;
-
-import javax.ejb.ApplicationException;
-
-/**
- * Thrown when an authenticated user has insufficient rights to carry out an action.
- *
- * @author Shane Bryzak
- */
- at ApplicationException(rollback=true)
-public class AuthorizationException extends RuntimeException
-{
- public AuthorizationException(String message)
- {
- super(message);
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/Configuration.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/Configuration.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/Configuration.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,75 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.util.HashMap;
-
-import javax.security.auth.login.AppConfigurationEntry;
-import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
-
-import org.jboss.seam.Component;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.Factory;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.contexts.Contexts;
-import org.jboss.seam.security.jaas.SeamLoginModule;
-
-/**
- * Factory for the JAAS Configuration used by Seam Security.
- *
- * @author Shane Bryzak
- *
- */
- at Name("org.jboss.seam.security.configurationFactory")
- at BypassInterceptors
- at Scope(ScopeType.STATELESS)
- at Install(precedence = BUILT_IN)
-public class Configuration
-{
- static final String DEFAULT_JAAS_CONFIG_NAME = "default";
-
- protected javax.security.auth.login.Configuration createConfiguration()
- {
- return new javax.security.auth.login.Configuration()
- {
- private AppConfigurationEntry[] aces = { createAppConfigurationEntry() };
-
- @Override
- public AppConfigurationEntry[] getAppConfigurationEntry(String name)
- {
- return DEFAULT_JAAS_CONFIG_NAME.equals(name) ? aces : null;
- }
-
- @Override
- public void refresh() {}
- };
- }
-
- protected AppConfigurationEntry createAppConfigurationEntry()
- {
- return new AppConfigurationEntry(
- SeamLoginModule.class.getName(),
- LoginModuleControlFlag.REQUIRED,
- new HashMap<String,String>()
- );
- }
-
- @Factory(value="org.jboss.seam.security.configuration", autoCreate=true, scope=APPLICATION)
- public javax.security.auth.login.Configuration getConfiguration()
- {
- return createConfiguration();
- }
-
- public static javax.security.auth.login.Configuration instance()
- {
- if ( !Contexts.isApplicationContextActive() )
- {
- throw new IllegalStateException("No active application scope");
- }
- return (javax.security.auth.login.Configuration) Component.getInstance("org.jboss.seam.security.configuration");
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/Credentials.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/Credentials.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/Credentials.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,139 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.SESSION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.io.IOException;
-import java.io.Serializable;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.core.Events;
-import org.jboss.seam.log.LogProvider;
-import org.jboss.seam.log.Logging;
-
- at Name("org.jboss.seam.security.credentials")
- at Scope(SESSION)
- at Install(precedence = BUILT_IN)
- at BypassInterceptors
-public class Credentials implements Serializable
-{
- public static final String EVENT_INIT_CREDENTIALS = "org.jboss.seam.security.initCredentials";
- public static final String EVENT_CREDENTIALS_UPDATED = "org.jboss.seam.security.credentialsUpdated";
-
- private static final LogProvider log = Logging.getLogProvider(Credentials.class);
-
- private String username;
- private String password;
-
- private boolean invalid = false;
-
- private boolean initialized;
-
- public boolean isInitialized()
- {
- return initialized;
- }
-
- public void setInitialized(boolean initialized)
- {
- this.initialized = initialized;
- }
-
- public String getUsername()
- {
- if (!isInitialized() && Events.exists())
- {
- setInitialized(true);
- Events.instance().raiseEvent(EVENT_INIT_CREDENTIALS, this);
- }
-
- return username;
- }
-
- public void setUsername(String username)
- {
- if (this.username != username && (this.username == null || !this.username.equals(username)))
- {
- this.username = username;
- invalid = false;
- if (Events.exists()) Events.instance().raiseEvent(EVENT_CREDENTIALS_UPDATED);
- }
- }
-
- public String getPassword()
- {
- return password;
- }
-
- public void setPassword(String password)
- {
- if (this.password != password && (this.password == null || !this.password.equals(password)))
- {
- this.password = password;
- invalid = false;
- if (Events.exists()) Events.instance().raiseEvent(EVENT_CREDENTIALS_UPDATED);
- }
- }
-
- public boolean isSet()
- {
- return getUsername() != null && password != null;
- }
-
- public boolean isInvalid()
- {
- return invalid;
- }
-
- public void invalidate()
- {
- invalid = true;
- }
-
- public void clear()
- {
- username = null;
- password = null;
- }
-
-
- /**
- * Creates a callback handler that can handle a standard username/password
- * callback, using the username and password properties.
- */
- public CallbackHandler createCallbackHandler()
- {
- return new CallbackHandler()
- {
- public void handle(Callback[] callbacks)
- throws IOException, UnsupportedCallbackException
- {
- for (int i=0; i < callbacks.length; i++)
- {
- if (callbacks[i] instanceof NameCallback)
- {
- ( (NameCallback) callbacks[i] ).setName(getUsername());
- }
- else if (callbacks[i] instanceof PasswordCallback)
- {
- ( (PasswordCallback) callbacks[i] ).setPassword( getPassword() != null ?
- getPassword().toCharArray() : null );
- }
- else
- {
- log.warn("Unsupported callback " + callbacks[i]);
- }
- }
- }
- };
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/EntityAction.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/EntityAction.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/EntityAction.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,23 +0,0 @@
-package org.jboss.seam.security;
-
-/**
- * Actions that may be performed upon entities
- * in JPA or Hibernate.
- *
- * @author Shane Bryzak
- *
- */
-public enum EntityAction {
-
- READ,
- INSERT,
- UPDATE,
- DELETE;
-
- @Override
- public String toString()
- {
- return super.name().toLowerCase();
- }
-
-}
\ No newline at end of file
Deleted: trunk/src/main/org/jboss/seam/security/EntityPermissionChecker.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/EntityPermissionChecker.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/EntityPermissionChecker.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,124 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.lang.reflect.Method;
-
-import javax.persistence.EntityManager;
-
-import org.jboss.seam.Component;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.Startup;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.annotations.security.Restrict;
-import org.jboss.seam.contexts.Contexts;
-import org.jboss.seam.persistence.PersistenceProvider;
-import org.jboss.seam.util.Strings;
-
-/**
- * Entity permission checks
- *
- * @author Shane Bryzak
- */
- at Name("org.jboss.seam.security.entityPermissionChecker")
- at Scope(APPLICATION)
- at Install(precedence = BUILT_IN)
- at BypassInterceptors
- at Startup
-public class EntityPermissionChecker
-{
- private String entityManagerName = "entityManager";
-
- private EntityManager getEntityManager()
- {
- return (EntityManager) Component.getInstance(entityManagerName);
- }
-
- public String getEntityManagerName()
- {
- return entityManagerName;
- }
-
- public void setEntityManagerName(String name)
- {
- this.entityManagerName = name;
- }
-
- public static EntityPermissionChecker instance()
- {
- if ( !Contexts.isApplicationContextActive() )
- {
- throw new IllegalStateException("No active application context");
- }
-
- EntityPermissionChecker instance = (EntityPermissionChecker) Component.getInstance(
- EntityPermissionChecker.class, ScopeType.APPLICATION);
-
- if (instance == null)
- {
- throw new IllegalStateException("No EntityPermissionChecker could be created");
- }
-
- return instance;
- }
-
- public void checkEntityPermission(Object entity, EntityAction action)
- {
- if (!Identity.isSecurityEnabled()) return;
-
- if (!Contexts.isSessionContextActive()) return;
-
- Identity identity = Identity.instance();
-
- identity.tryLogin();
-
- PersistenceProvider provider = PersistenceProvider.instance();
- Class beanClass = provider.getBeanClass(entity);
-
- if (beanClass != null)
- {
- Method m = null;
- switch (action)
- {
- case READ:
- m = provider.getPostLoadMethod(entity, getEntityManager());
- break;
- case INSERT:
- m = provider.getPrePersistMethod(entity, getEntityManager());
- break;
- case UPDATE:
- m = provider.getPreUpdateMethod(entity, getEntityManager());
- break;
- case DELETE:
- m = provider.getPreRemoveMethod(entity, getEntityManager());
- }
-
- Restrict restrict = null;
-
- if (m != null && m.isAnnotationPresent(Restrict.class))
- {
- restrict = m.getAnnotation(Restrict.class);
- }
- else if (entity.getClass().isAnnotationPresent(Restrict.class))
- {
- restrict = entity.getClass().getAnnotation(Restrict.class);
- }
-
- if (restrict != null)
- {
- if (Strings.isEmpty(restrict.value()))
- {
- identity.checkPermission(entity, action.toString());
- }
- else
- {
- identity.checkRestriction(restrict.value());
- }
- }
- }
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/EntitySecurityListener.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/EntitySecurityListener.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/EntitySecurityListener.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,44 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.security.EntityAction.DELETE;
-import static org.jboss.seam.security.EntityAction.INSERT;
-import static org.jboss.seam.security.EntityAction.READ;
-import static org.jboss.seam.security.EntityAction.UPDATE;
-
-import javax.persistence.PostLoad;
-import javax.persistence.PrePersist;
-import javax.persistence.PreRemove;
-import javax.persistence.PreUpdate;
-
-
-/**
- * Facilitates security checks for entity beans.
- *
- * @author Shane Bryzak
- */
-public class EntitySecurityListener
-{
- @PostLoad
- public void postLoad(Object entity)
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, READ);
- }
-
- @PrePersist
- public void prePersist(Object entity)
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, INSERT);
- }
-
- @PreUpdate
- public void preUpdate(Object entity)
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, UPDATE);
- }
-
- @PreRemove
- public void preRemove(Object entity)
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, DELETE);
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/FacesSecurityEvents.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/FacesSecurityEvents.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/FacesSecurityEvents.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,106 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import javax.security.auth.login.LoginException;
-
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Observer;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.Startup;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.international.StatusMessages;
-import org.jboss.seam.international.StatusMessage.Severity;
-
-/**
- * Produces FacesMessages in response of certain security events, and helps to decouple the
- * Identity component from JSF.
- *
- * @author Shane Bryzak
- */
- at Name("org.jboss.seam.security.facesSecurityEvents")
- at Scope(APPLICATION)
- at Install(precedence = BUILT_IN, classDependencies = "javax.faces.context.FacesContext")
- at BypassInterceptors
- at Startup
-public class FacesSecurityEvents
-{
- @Observer(Identity.EVENT_POST_AUTHENTICATE)
- public void postAuthenticate(Identity identity)
- {
- //org.jboss.security.saml.SSOManager.processManualLoginNotification(
- //ServletContexts.instance().getRequest(), identity.getPrincipal().getName());
- }
-
- @Observer(Identity.EVENT_LOGIN_FAILED)
- public void addLoginFailedMessage(LoginException ex)
- {
- StatusMessages.instance().addFromResourceBundleOrDefault(
- getLoginFailedMessageSeverity(),
- getLoginFailedMessageKey(),
- getLoginFailedMessage(),
- ex);
- }
-
- public String getLoginFailedMessage()
- {
- return "Login failed";
- }
-
- public Severity getLoginFailedMessageSeverity()
- {
- return Severity.INFO;
- }
-
- public String getLoginFailedMessageKey()
- {
- return "org.jboss.seam.loginFailed";
- }
-
- @Observer(Identity.EVENT_LOGIN_SUCCESSFUL)
- public void addLoginSuccessfulMessage()
- {
- StatusMessages.instance().addFromResourceBundleOrDefault(
- getLoginSuccessfulMessageSeverity(),
- getLoginSuccessfulMessageKey(),
- getLoginSuccessfulMessage(),
- Identity.instance().getCredentials().getUsername());
- }
-
- @Observer(Identity.EVENT_NOT_LOGGED_IN)
- public void addNotLoggedInMessage()
- {
- StatusMessages.instance().addFromResourceBundleOrDefault(
- Severity.WARN,
- "org.jboss.seam.NotLoggedIn",
- "Please log in first"
- );
- }
-
- public Severity getLoginSuccessfulMessageSeverity()
- {
- return Severity.INFO;
- }
-
- public String getLoginSuccessfulMessage()
- {
- return "Welcome, #0";
- }
-
- public String getLoginSuccessfulMessageKey()
- {
- return "org.jboss.seam.loginSuccessful";
- }
-
- @Observer(Identity.EVENT_ALREADY_LOGGED_IN)
- public void addAlreadyLoggedInMessage()
- {
- StatusMessages.instance().addFromResourceBundleOrDefault (
- Severity.WARN,
- "org.jboss.seam.AlreadyLoggedIn",
- "You are already logged in, please log out first if you wish to log in again"
- );
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/HibernateSecurityInterceptor.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/HibernateSecurityInterceptor.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/HibernateSecurityInterceptor.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,100 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.security.EntityAction.DELETE;
-import static org.jboss.seam.security.EntityAction.INSERT;
-import static org.jboss.seam.security.EntityAction.READ;
-import static org.jboss.seam.security.EntityAction.UPDATE;
-
-import java.io.Serializable;
-
-import org.hibernate.EmptyInterceptor;
-import org.hibernate.Interceptor;
-import org.hibernate.type.Type;
-import org.jboss.seam.Entity.NotEntityException;
-
-/**
- * Facilitates security checks for Hibernate entities
- *
- * @author Shane Bryzak
- *
- */
-public class HibernateSecurityInterceptor extends EmptyInterceptor
-{
- private Interceptor wrappedInterceptor;
-
- public HibernateSecurityInterceptor(Interceptor wrappedInterceptor)
- {
- this.wrappedInterceptor = wrappedInterceptor;
- }
-
- @Override
- public boolean onLoad(Object entity, Serializable id, Object[] state,
- String[] propertyNames, Type[] types)
- {
- try
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, READ);
- }
- catch (NotEntityException e)
- {
- // Not a JPA entity
- }
-
- return wrappedInterceptor != null ?
- wrappedInterceptor.onLoad(entity, id, state, propertyNames, types) :
- false;
- }
-
- @Override
- public void onDelete(Object entity, Serializable id, Object[] state,
- String[] propertyNames, Type[] types)
- {
- try
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, DELETE);
- }
- catch (NotEntityException e)
- {
- // Not a JPA entity
- }
-
- if (wrappedInterceptor != null)
- wrappedInterceptor.onDelete(entity, id, state, propertyNames, types);
- }
-
- @Override
- public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
- Object[] previousState, String[] propertyNames, Type[] types)
- {
- try
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, UPDATE);
- }
- catch (NotEntityException e)
- {
- // Not a JPA entity
- }
-
- return wrappedInterceptor != null ?
- wrappedInterceptor.onFlushDirty(entity, id, currentState,
- previousState, propertyNames, types) : false;
- }
-
- @Override
- public boolean onSave(Object entity, Serializable id, Object[] state,
- String[] propertyNames, Type[] types)
- {
- try
- {
- EntityPermissionChecker.instance().checkEntityPermission(entity, INSERT);
- }
- catch (NotEntityException e)
- {
- // Not a JPA entity
- }
-
- return wrappedInterceptor != null ?
- wrappedInterceptor.onSave(entity, id, state, propertyNames, types) :
- false;
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/Identity.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/Identity.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/Identity.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,752 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.SESSION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.io.Serializable;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.List;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
-
-import org.jboss.seam.Component;
-import org.jboss.seam.ScopeType;
-import org.jboss.seam.annotations.Create;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.Startup;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.contexts.Contexts;
-import org.jboss.seam.core.Events;
-import org.jboss.seam.core.Expressions;
-import org.jboss.seam.core.Expressions.MethodExpression;
-import org.jboss.seam.log.LogProvider;
-import org.jboss.seam.log.Logging;
-import org.jboss.seam.security.permission.PermissionMapper;
-import org.jboss.seam.web.Session;
-
-/**
- * API for authorization and authentication via Seam security. This base
- * implementation supports role-based authorization only. Subclasses may add
- * more sophisticated permissioning mechanisms.
- *
- * @author Shane Bryzak
- */
- at Name("org.jboss.seam.security.identity")
- at Scope(SESSION)
- at Install(precedence = BUILT_IN)
- at BypassInterceptors
- at Startup
-public class Identity implements Serializable
-{
- private static final long serialVersionUID = 3751659008033189259L;
-
- // Event keys
- public static final String EVENT_LOGIN_SUCCESSFUL = "org.jboss.seam.security.loginSuccessful";
- public static final String EVENT_LOGIN_FAILED = "org.jboss.seam.security.loginFailed";
- public static final String EVENT_NOT_LOGGED_IN = "org.jboss.seam.security.notLoggedIn";
- public static final String EVENT_NOT_AUTHORIZED = "org.jboss.seam.security.notAuthorized";
- public static final String EVENT_PRE_AUTHENTICATE = "org.jboss.seam.security.preAuthenticate";
- public static final String EVENT_POST_AUTHENTICATE = "org.jboss.seam.security.postAuthenticate";
- public static final String EVENT_LOGGED_OUT = "org.jboss.seam.security.loggedOut";
- public static final String EVENT_ALREADY_LOGGED_IN = "org.jboss.seam.security.alreadyLoggedIn";
- public static final String EVENT_QUIET_LOGIN = "org.jboss.seam.security.quietLogin";
-
- protected static boolean securityEnabled = true;
-
- public static final String ROLES_GROUP = "Roles";
-
- // Context variables
- private static final String LOGIN_TRIED = "org.jboss.seam.security.loginTried";
- private static final String SILENT_LOGIN = "org.jboss.seam.security.silentLogin";
-
- private static final LogProvider log = Logging.getLogProvider(Identity.class);
-
- private Credentials credentials;
-
- private MethodExpression authenticateMethod;
-
- private Principal principal;
- private Subject subject;
-
- private RememberMe rememberMe;
-
- private transient ThreadLocal<Boolean> systemOp;
-
- private String jaasConfigName = null;
-
- private List<String> preAuthenticationRoles = new ArrayList<String>();
-
- private PermissionMapper permissionMapper;
-
- /**
- * Flag that indicates we are in the process of authenticating
- */
- private boolean authenticating = false;
-
- @Create
- public void create()
- {
- subject = new Subject();
-
- if (Contexts.isApplicationContextActive())
- {
- permissionMapper = (PermissionMapper) Component.getInstance(PermissionMapper.class);
- }
-
- if (Contexts.isSessionContextActive())
- {
- rememberMe = (RememberMe) Component.getInstance(RememberMe.class, true);
- credentials = (Credentials) Component.getInstance(Credentials.class);
- }
-
- if (credentials == null)
- {
- // Must have credentials for unit tests
- credentials = new Credentials();
- }
- }
-
- public static boolean isSecurityEnabled()
- {
- return securityEnabled;
- }
-
- public static void setSecurityEnabled(boolean enabled)
- {
- securityEnabled = enabled;
- }
-
- public static Identity instance()
- {
- if ( !Contexts.isSessionContextActive() )
- {
- throw new IllegalStateException("No active session context");
- }
-
- Identity instance = (Identity) Component.getInstance(Identity.class, ScopeType.SESSION);
-
- if (instance == null)
- {
- throw new IllegalStateException("No Identity could be created");
- }
-
- return instance;
- }
-
- /**
- * Simple check that returns true if the user is logged in, without attempting to authenticate
- *
- * @return true if the user is logged in
- */
- public boolean isLoggedIn()
- {
- // If there is a principal set, then the user is logged in.
- return getPrincipal() != null;
- }
-
- /**
- * Will attempt to authenticate quietly if the user's credentials are set and they haven't
- * authenticated already. A quiet authentication doesn't throw any exceptions if authentication
- * fails.
- *
- * @return true if the user is logged in, false otherwise
- */
- public boolean tryLogin()
- {
- if (!authenticating && getPrincipal() == null && credentials.isSet() &&
- Contexts.isEventContextActive() &&
- !Contexts.getEventContext().isSet(LOGIN_TRIED))
- {
- Contexts.getEventContext().set(LOGIN_TRIED, true);
- quietLogin();
- }
-
- return isLoggedIn();
- }
-
- @Deprecated
- public boolean isLoggedIn(boolean attemptLogin)
- {
- return attemptLogin ? tryLogin() : isLoggedIn();
- }
-
-
- public void acceptExternallyAuthenticatedPrincipal(Principal principal) {
- getSubject().getPrincipals().add(principal);
- this.principal = principal;
- }
-
- public Principal getPrincipal()
- {
- return principal;
- }
-
- public Subject getSubject()
- {
- return subject;
- }
-
- /**
- * Performs an authorization check, based on the specified security expression.
- *
- * @param expr The security expression to evaluate
- * @throws NotLoggedInException Thrown if the authorization check fails and
- * the user is not authenticated
- * @throws AuthorizationException Thrown if the authorization check fails and
- * the user is authenticated
- */
- public void checkRestriction(String expr)
- {
- if (!securityEnabled) return;
-
- if ( !evaluateExpression(expr) )
- {
- if ( !isLoggedIn() )
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
- log.debug(String.format(
- "Error evaluating expression [%s] - User not logged in", expr));
- throw new NotLoggedInException();
- }
- else
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
- throw new AuthorizationException(String.format(
- "Authorization check failed for expression [%s]", expr));
- }
- }
- }
-
- /**
- * Attempts to authenticate the user. This method is distinct to the
- * authenticate() method in that it raises events in response to whether
- * authentication is successful or not. The following events may be raised
- * by calling login():
- *
- * org.jboss.seam.security.loginSuccessful - raised when authentication is successful
- * org.jboss.seam.security.loginFailed - raised when authentication fails
- * org.jboss.seam.security.alreadyLoggedIn - raised if the user is already authenticated
- *
- * @return String returns "loggedIn" if user is authenticated, or null if not.
- */
- public String login()
- {
- try
- {
- if (isLoggedIn())
- {
- // If authentication has already occurred during this request via a silent login,
- // and login() is explicitly called then we still want to raise the LOGIN_SUCCESSFUL event,
- // and then return.
- if (Contexts.isEventContextActive() && Contexts.getEventContext().isSet(SILENT_LOGIN))
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_SUCCESSFUL);
- return "loggedIn";
- }
-
- if (Events.exists()) Events.instance().raiseEvent(EVENT_ALREADY_LOGGED_IN);
- return "loggedIn";
- }
-
- authenticate();
-
- if (!isLoggedIn())
- {
- throw new LoginException();
- }
-
- if ( log.isDebugEnabled() )
- {
- log.debug("Login successful for: " + getCredentials().getUsername());
- }
-
- if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_SUCCESSFUL);
- return "loggedIn";
- }
- catch (LoginException ex)
- {
- credentials.invalidate();
-
- if ( log.isDebugEnabled() )
- {
- log.debug("Login failed for: " + getCredentials().getUsername(), ex);
- }
- if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_FAILED, ex);
- }
-
- return null;
- }
-
- /**
- * Attempts a quiet login, suppressing any login exceptions and not creating
- * any faces messages. This method is intended to be used primarily as an
- * internal API call, however has been made public for convenience.
- */
- public void quietLogin()
- {
- try
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_QUIET_LOGIN);
-
- // Ensure that we haven't been authenticated as a result of the EVENT_QUIET_LOGIN event
- if (!isLoggedIn())
- {
- if (credentials.isSet())
- {
- authenticate();
- if (isLoggedIn() && Contexts.isEventContextActive())
- {
- Contexts.getEventContext().set(SILENT_LOGIN, true);
- }
- }
- }
- }
- catch (LoginException ex)
- {
- credentials.invalidate();
- }
- }
-
-
-
- /**
- *
- * @throws LoginException
- */
- public synchronized void authenticate()
- throws LoginException
- {
- // If we're already authenticated, then don't authenticate again
- if (!isLoggedIn() && !credentials.isInvalid())
- {
- principal = null;
- subject = new Subject();
- authenticate( getLoginContext() );
- }
- }
-
-
- protected void authenticate(LoginContext loginContext)
- throws LoginException
- {
- try
- {
- authenticating = true;
- preAuthenticate();
- loginContext.login();
- postAuthenticate();
- }
- finally
- {
- // Set password to null whether authentication is successful or not
- credentials.setPassword(null);
- authenticating = false;
- }
- }
-
- /**
- * Clears any roles added by calling addRole() while not authenticated.
- * This method may be overridden by a subclass if different
- * pre-authentication logic should occur.
- */
- protected void preAuthenticate()
- {
- preAuthenticationRoles.clear();
- if (Events.exists()) Events.instance().raiseEvent(EVENT_PRE_AUTHENTICATE);
- }
-
- /**
- * Extracts the principal from the subject, and populates the roles of the
- * authenticated user. This method may be overridden by a subclass if
- * different post-authentication logic should occur.
- */
- protected void postAuthenticate()
- {
- // Populate the working memory with the user's principals
- for ( Principal p : getSubject().getPrincipals() )
- {
- if ( !(p instanceof Group))
- {
- if (principal == null)
- {
- principal = p;
- break;
- }
- }
- }
-
- if (!preAuthenticationRoles.isEmpty() && isLoggedIn())
- {
- for (String role : preAuthenticationRoles)
- {
- addRole(role);
- }
- preAuthenticationRoles.clear();
- }
-
- credentials.setPassword(null);
-
- if (Events.exists()) Events.instance().raiseEvent(EVENT_POST_AUTHENTICATE, this);
- }
-
- /**
- * Resets all security state and credentials
- */
- public void unAuthenticate()
- {
- principal = null;
- subject = new Subject();
-
- credentials.clear();
- }
-
- protected LoginContext getLoginContext() throws LoginException
- {
- if (getJaasConfigName() != null)
- {
- return new LoginContext(getJaasConfigName(), getSubject(),
- credentials.createCallbackHandler());
- }
-
- return new LoginContext(Configuration.DEFAULT_JAAS_CONFIG_NAME, getSubject(),
- credentials.createCallbackHandler(), Configuration.instance());
- }
-
- public void logout()
- {
- if (isLoggedIn())
- {
- unAuthenticate();
- Session.instance().invalidate();
- if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGGED_OUT);
- }
- }
-
- /**
- * Checks if the authenticated user is a member of the specified role.
- *
- * @param role String The name of the role to check
- * @return boolean True if the user is a member of the specified role
- */
- public boolean hasRole(String role)
- {
- if (!securityEnabled) return true;
- if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
-
- tryLogin();
-
- for ( Group sg : getSubject().getPrincipals(Group.class) )
- {
- if ( ROLES_GROUP.equals( sg.getName() ) )
- {
- return sg.isMember( new Role(role) );
- }
- }
- return false;
- }
-
- /**
- * Adds a role to the authenticated user. If the user is not logged in,
- * the role will be added to a list of roles that will be granted to the
- * user upon successful authentication, but only during the authentication
- * process.
- *
- * @param role The name of the role to add
- */
- public boolean addRole(String role)
- {
- if (role == null || "".equals(role)) return false;
-
- if (!isLoggedIn())
- {
- preAuthenticationRoles.add(role);
- return false;
- }
- else
- {
- for ( Group sg : getSubject().getPrincipals(Group.class) )
- {
- if ( ROLES_GROUP.equals( sg.getName() ) )
- {
- return sg.addMember(new Role(role));
- }
- }
-
- SimpleGroup roleGroup = new SimpleGroup(ROLES_GROUP);
- roleGroup.addMember(new Role(role));
- getSubject().getPrincipals().add(roleGroup);
- return true;
- }
- }
-
- /**
- * Removes a role from the authenticated user
- *
- * @param role The name of the role to remove
- */
- public void removeRole(String role)
- {
- for ( Group sg : getSubject().getPrincipals(Group.class) )
- {
- if ( ROLES_GROUP.equals( sg.getName() ) )
- {
- Enumeration e = sg.members();
- while (e.hasMoreElements())
- {
- Principal member = (Principal) e.nextElement();
- if (member.getName().equals(role))
- {
- sg.removeMember(member);
- break;
- }
- }
-
- }
- }
- }
-
- /**
- * Checks that the current authenticated user is a member of
- * the specified role.
- *
- * @param role String The name of the role to check
- * @throws AuthorizationException if the authenticated user is not a member of the role
- */
- public void checkRole(String role)
- {
- tryLogin();
-
- if ( !hasRole(role) )
- {
- if ( !isLoggedIn() )
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
- throw new NotLoggedInException();
- }
- else
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
- throw new AuthorizationException(String.format(
- "Authorization check failed for role [%s]", role));
- }
- }
- }
-
- /**
- * Checks that the current authenticated user has permission for
- * the specified name and action
- *
- * @param name String The permission name
- * @param action String The permission action
- * @param arg Object Optional object parameter used to make a permission decision
- * @throws AuthorizationException if the user does not have the specified permission
- */
- public void checkPermission(String name, String action, Object...arg)
- {
- if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return;
-
- tryLogin();
-
- if ( !hasPermission(name, action, arg) )
- {
- if ( !isLoggedIn() )
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
- throw new NotLoggedInException();
- }
- else
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
- throw new AuthorizationException(String.format(
- "Authorization check failed for permission [%s,%s]", name, action));
- }
- }
- }
-
- public void checkPermission(Object target, String action)
- {
- if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return;
-
- tryLogin();
-
- if ( !hasPermission(target, action) )
- {
- if ( !isLoggedIn() )
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_LOGGED_IN);
- throw new NotLoggedInException();
- }
- else
- {
- if (Events.exists()) Events.instance().raiseEvent(EVENT_NOT_AUTHORIZED);
- throw new AuthorizationException(String.format(
- "Authorization check failed for permission[%s,%s]", target, action));
- }
- }
- }
-
- /**
- * Performs a permission check for the specified name and action
- *
- * @param name String The permission name
- * @param action String The permission action
- * @param arg Object Optional object parameter used to make a permission decision
- * @return boolean True if the user has the specified permission
- */
- public boolean hasPermission(String name, String action, Object...arg)
- {
- if (!securityEnabled) return true;
- if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
- if (permissionMapper == null) return false;
-
- if (arg != null)
- {
- return permissionMapper.resolvePermission(arg[0], action);
- }
- else
- {
- return permissionMapper.resolvePermission(name, action);
- }
- }
-
- public void filterByPermission(Collection collection, String action)
- {
- permissionMapper.filterByPermission(collection, action);
- }
-
- public boolean hasPermission(Object target, String action)
- {
- if (!securityEnabled) return true;
- if (systemOp != null && Boolean.TRUE.equals(systemOp.get())) return true;
- if (permissionMapper == null) return false;
- if (target == null) return false;
-
- return permissionMapper.resolvePermission(target, action);
- }
-
- /**
- * Evaluates the specified security expression, which must return a boolean
- * value.
- *
- * @param expr String The expression to evaluate
- * @return boolean The result of the expression evaluation
- */
- protected boolean evaluateExpression(String expr)
- {
- return Expressions.instance().createValueExpression(expr, Boolean.class).getValue();
- }
-
- /**
- * @see org.jboss.seam.security.Credentials#getUsername()
- */
- @Deprecated
- public String getUsername()
- {
- return credentials.getUsername();
- }
-
- /**
- * @see org.jboss.seam.security.Credentials#setUsername(String)
- */
- @Deprecated
- public void setUsername(String username)
- {
- credentials.setUsername(username);
- }
-
- /**
- * @see org.jboss.seam.security.Credentials#getPassword()
- */
- @Deprecated
- public String getPassword()
- {
- return credentials.getPassword();
- }
-
- /**
- * @see org.jboss.seam.security.Credentials#setPassword(String)
- */
- @Deprecated
- public void setPassword(String password)
- {
- credentials.setPassword(password);
- }
-
- /**
- * @see org.jboss.seam.security.RememberMe#isEnabled()
- */
- @Deprecated
- public boolean isRememberMe()
- {
- return rememberMe != null ? rememberMe.isEnabled() : false;
- }
-
- /**
- * @see org.jboss.seam.security.RememberMe#setEnabled(boolean)
- */
- @Deprecated
- public void setRememberMe(boolean remember)
- {
- if (rememberMe != null) rememberMe.setEnabled(remember);
- }
-
- public Credentials getCredentials()
- {
- return credentials;
- }
-
- public MethodExpression getAuthenticateMethod()
- {
- return authenticateMethod;
- }
-
- public void setAuthenticateMethod(MethodExpression authMethod)
- {
- this.authenticateMethod = authMethod;
- }
-
- public String getJaasConfigName()
- {
- return jaasConfigName;
- }
-
- public void setJaasConfigName(String jaasConfigName)
- {
- this.jaasConfigName = jaasConfigName;
- }
-
- synchronized void runAs(RunAsOperation operation)
- {
- Principal savedPrincipal = getPrincipal();
- Subject savedSubject = getSubject();
-
- try
- {
- principal = operation.getPrincipal();
- subject = operation.getSubject();
-
- if (systemOp == null)
- {
- systemOp = new ThreadLocal<Boolean>();
- }
-
- systemOp.set(operation.isSystemOperation());
-
- operation.execute();
- }
- finally
- {
- systemOp.set(false);
- principal = savedPrincipal;
- subject = savedSubject;
- }
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/JpaTokenStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/JpaTokenStore.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/JpaTokenStore.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,165 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.APPLICATION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.io.Serializable;
-
-import javax.persistence.EntityManager;
-import javax.persistence.NoResultException;
-import javax.persistence.Query;
-
-import org.jboss.seam.annotations.Create;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.annotations.security.TokenUsername;
-import org.jboss.seam.annotations.security.TokenValue;
-import org.jboss.seam.core.Expressions;
-import org.jboss.seam.core.Expressions.ValueExpression;
-import org.jboss.seam.security.management.IdentityManagementException;
-import org.jboss.seam.util.AnnotatedBeanProperty;
-
-/**
- * A TokenStore implementation, stores tokens inside a database table.
- *
- * @author Shane Bryzak
- */
- at Name("org.jboss.seam.security.tokenStore")
- at Install(precedence = BUILT_IN, value=false)
- at Scope(APPLICATION)
- at BypassInterceptors
-public class JpaTokenStore implements TokenStore, Serializable
-{
- private Class tokenClass;
-
- private ValueExpression<EntityManager> entityManager;
-
- private AnnotatedBeanProperty<TokenUsername> tokenUsernameProperty;
- private AnnotatedBeanProperty<TokenValue> tokenValueProperty;
-
- @Create
- public void create()
- {
- if (entityManager == null)
- {
- entityManager = Expressions.instance().createValueExpression("#{entityManager}", EntityManager.class);
- }
-
- tokenUsernameProperty = new AnnotatedBeanProperty<TokenUsername>(tokenClass, TokenUsername.class);
- tokenValueProperty = new AnnotatedBeanProperty<TokenValue>(tokenClass, TokenValue.class);
-
- if (!tokenUsernameProperty.isSet())
- {
- throw new IllegalStateException("Invalid tokenClass " + tokenClass.getName() +
- " - required annotation @TokenUsername not found on any Field or Method.");
- }
-
- if (!tokenValueProperty.isSet())
- {
- throw new IllegalStateException("Invalid tokenClass " + tokenClass.getName() +
- " - required annotation @TokenValue not found on any Field or Method.");
- }
- }
-
- public void createToken(String username, String value)
- {
- if (tokenClass == null)
- {
- throw new IllegalStateException("Could not create token, tokenClass not set");
- }
-
- try
- {
- Object token = tokenClass.newInstance();
-
- tokenUsernameProperty.setValue(token, username);
- tokenValueProperty.setValue(token, value);
-
- lookupEntityManager().persist(token);
- }
- catch (Exception ex)
- {
- if (ex instanceof IdentityManagementException)
- {
- throw (IdentityManagementException) ex;
- }
- else
- {
- throw new IdentityManagementException("Could not create account", ex);
- }
- }
- }
-
- public boolean validateToken(String username, String value)
- {
- return lookupToken(username, value) != null;
- }
-
- public void invalidateToken(String username, String value)
- {
- Object token = lookupToken(username, value);
- if (token != null)
- {
- lookupEntityManager().remove(token);
- }
- }
-
- public void invalidateAll(String username)
- {
- Query query = lookupEntityManager().createQuery(
- "select t from " + tokenClass.getName() + " t where " + tokenUsernameProperty.getName() +
- " = :username")
- .setParameter("username", username);
-
- for (Object token : query.getResultList())
- {
- lookupEntityManager().remove(token);
- }
- }
-
- public Object lookupToken(String username, String value)
- {
- try
- {
- Object token = lookupEntityManager().createQuery(
- "select t from " + tokenClass.getName() + " t where " + tokenUsernameProperty.getName() +
- " = :username and " + tokenValueProperty.getName() + " = :value")
- .setParameter("username", username)
- .setParameter("value", value)
- .getSingleResult();
-
- return token;
- }
- catch (NoResultException ex)
- {
- return null;
- }
- }
-
- public Class getTokenClass()
- {
- return tokenClass;
- }
-
- public void setTokenClass(Class tokenClass)
- {
- this.tokenClass = tokenClass;
- }
-
- private EntityManager lookupEntityManager()
- {
- return entityManager.getValue();
- }
-
- public ValueExpression getEntityManager()
- {
- return entityManager;
- }
-
- public void setEntityManager(ValueExpression expression)
- {
- this.entityManager = expression;
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/NotLoggedInException.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/NotLoggedInException.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/NotLoggedInException.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,11 +0,0 @@
-package org.jboss.seam.security;
-
-import javax.ejb.ApplicationException;
-
-/**
- * Thrown when an unauthenticated user attempts to execute a restricted action.
- *
- * @author Shane Bryzak
- */
- at ApplicationException(rollback=true)
-public class NotLoggedInException extends RuntimeException {}
Deleted: trunk/src/main/org/jboss/seam/security/RememberMe.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/RememberMe.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/RememberMe.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,410 +0,0 @@
-package org.jboss.seam.security;
-
-import static org.jboss.seam.ScopeType.SESSION;
-import static org.jboss.seam.annotations.Install.BUILT_IN;
-
-import java.io.Serializable;
-import java.rmi.server.UID;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-import javax.faces.context.FacesContext;
-
-import org.jboss.seam.Component;
-import org.jboss.seam.annotations.Create;
-import org.jboss.seam.annotations.Install;
-import org.jboss.seam.annotations.Name;
-import org.jboss.seam.annotations.Observer;
-import org.jboss.seam.annotations.Scope;
-import org.jboss.seam.annotations.intercept.BypassInterceptors;
-import org.jboss.seam.faces.Selector;
-import org.jboss.seam.security.management.IdentityManager;
-import org.jboss.seam.util.Base64;
-
-/**
- * Remember-me functionality is provided by this class, in two different flavours. The first mode
- * provides username-only persistence, and is considered to be secure as the user (or their browser)
- * is still required to provide a password. The second mode provides an auto-login feature, however
- * is NOT considered to be secure and is vulnerable to XSS attacks compromising the user's account.
- *
- * Use the auto-login mode with caution!
- *
- * @author Shane Bryzak
- */
- at Name("org.jboss.seam.security.rememberMe")
- at Scope(SESSION)
- at Install(precedence = BUILT_IN, classDependencies = "javax.faces.context.FacesContext")
- at BypassInterceptors
-public class RememberMe implements Serializable
-{
- class UsernameSelector extends Selector
- {
- @Override
- public String getCookieName()
- {
- return "org.jboss.seam.security.username";
- }
-
- @Override
- public void setDirty()
- {
- super.setDirty();
- }
-
- @Override
- public String getCookieValue()
- {
- return super.getCookieValue();
- }
-
- @Override
- public void clearCookieValue()
- {
- super.clearCookieValue();
- }
-
- @Override
- public void setCookieValueIfEnabled(String value)
- {
- super.setCookieValueIfEnabled(value);
- }
- }
-
- class TokenSelector extends UsernameSelector
- {
- @Override
- public String getCookieName()
- {
- return "org.jboss.seam.security.authtoken";
- }
- }
-
- private class DecodedToken
- {
- private String username;
- private String value;
-
- public DecodedToken(String cookieValue)
- {
- if (cookieValue != null)
- {
- try
- {
- String decoded = new String(Base64.decode(cookieValue));
- username = decoded.substring(0, decoded.indexOf(':'));
- value = decoded.substring(decoded.indexOf(':') + 1);
- }
- catch (Exception ex)
- {
- // swallow
- }
- }
- }
-
- public String getUsername()
- {
- return username;
- }
-
- public String getValue()
- {
- return value;
- }
- }
-
- private UsernameSelector usernameSelector;
-
- private TokenSelector tokenSelector;
- private TokenStore tokenStore;
-
- private boolean enabled;
-
- private int cookieMaxAge = Selector.DEFAULT_MAX_AGE;
-
- private boolean autoLoggedIn;
-
- private Random random = new Random(System.currentTimeMillis());
-
- public enum Mode { disabled, usernameOnly, autoLogin}
-
- private Mode mode = Mode.usernameOnly;
-
- public Mode getMode()
- {
- return mode;
- }
-
- public void setMode(Mode mode)
- {
- this.mode = mode;
- }
-
- public boolean isEnabled()
- {
- return enabled;
- }
-
- public void setEnabled(boolean enabled)
- {
- if (this.enabled != enabled)
- {
- this.enabled = enabled;
- // selector is null during component initialization (setup handled in @Create method)
- if (usernameSelector != null && mode.equals(Mode.usernameOnly))
- {
- usernameSelector.setCookieEnabled(enabled);
- usernameSelector.setDirty();
- }
- // selector is null during component initialization (setup handled in @Create method)
- else if (tokenSelector != null && mode.equals(Mode.autoLogin))
- {
- tokenSelector.setCookieEnabled(enabled);
- tokenSelector.setDirty();
- }
- }
- }
-
- public int getCookieMaxAge() {
- return cookieMaxAge;
- }
-
- public void setCookieMaxAge(int cookieMaxAge) {
- this.cookieMaxAge = cookieMaxAge;
- }
-
- public TokenStore getTokenStore()
- {
- return tokenStore;
- }
-
- public void setTokenStore(TokenStore tokenStore)
- {
- this.tokenStore = tokenStore;
- }
-
- @Create
- public void create()
- {
- if (mode.equals(Mode.usernameOnly))
- {
- usernameSelector = new UsernameSelector();
- usernameSelector.setCookieEnabled(enabled);
- }
- else if (mode.equals(Mode.autoLogin))
- {
- tokenSelector = new TokenSelector();
- tokenSelector.setCookieEnabled(enabled);
-
- // Default to JpaTokenStore
- if (tokenStore == null)
- {
- tokenStore = (TokenStore) Component.getInstance(JpaTokenStore.class, true);
- }
- }
- }
-
- protected String generateTokenValue()
- {
- StringBuilder sb = new StringBuilder();
- sb.append(new UID().toString());
- sb.append(":");
- sb.append(random.nextLong());
- return sb.toString();
- }
-
- protected String encodeToken(String username, String value)
- {
- StringBuilder sb = new StringBuilder();
- sb.append(username);
- sb.append(":");
- sb.append(value);
- return Base64.encodeBytes(sb.toString().getBytes());
- }
-
- public String getCookiePath()
- {
- FacesContext ctx = FacesContext.getCurrentInstance();
- return ctx != null ? ctx.getExternalContext().getRequestContextPath() : null;
- }
-
- @Observer(Credentials.EVENT_INIT_CREDENTIALS)
- public void initCredentials(Credentials credentials)
- {
- String cookiePath = getCookiePath();
-
- if (mode.equals(Mode.usernameOnly))
- {
- if (cookiePath != null)
- {
- usernameSelector.setCookiePath(cookiePath);
- }
-
- String username = usernameSelector.getCookieValue();
- if (username!=null)
- {
- setEnabled(true);
- credentials.setUsername(username);
- }
-
- usernameSelector.setDirty();
- }
- else if (mode.equals(Mode.autoLogin))
- {
- if (cookiePath != null)
- {
- tokenSelector.setCookiePath(cookiePath);
- }
-
- String token = tokenSelector.getCookieValue();
- if (token != null)
- {
- setEnabled(true);
-
- DecodedToken decoded = new DecodedToken(token);
-
- if (tokenStore.validateToken(decoded.getUsername(), decoded.getValue()))
- {
- credentials.setUsername(decoded.getUsername());
- credentials.setPassword(decoded.getValue());
- }
- else
- {
- // Have we been compromised? Just in case, invalidate all authentication tokens
- tokenStore.invalidateAll(decoded.getUsername());
- }
- }
- }
- }
-
- /**
- * I hate these hacks...
- */
- private class BoolWrapper
- {
- boolean value;
- }
-
- @Observer(Identity.EVENT_QUIET_LOGIN)
- public void quietLogin()
- {
- final Identity identity = Identity.instance();
-
- if (mode.equals(Mode.autoLogin) && isEnabled())
- {
- final String username = identity.getCredentials().getUsername();
- final BoolWrapper userEnabled = new BoolWrapper();
- final List<String> roles = new ArrayList<String>();
-
- // Double check our credentials again
- if (tokenStore.validateToken(username, identity.getCredentials().getPassword()))
- {
- new RunAsOperation(true) {
- @Override
- public void execute()
- {
- if (IdentityManager.instance().isUserEnabled(username))
- {
- userEnabled.value = true;
-
- for (String role : IdentityManager.instance().getImpliedRoles(username))
- {
- roles.add(role);
- }
- }
- }
- }.run();
-
- if (userEnabled.value)
- {
- identity.unAuthenticate();
- identity.preAuthenticate();
-
- // populate the roles
- for (String role : roles)
- {
- identity.addRole(role);
- }
-
- // Set the principal
- identity.getSubject().getPrincipals().add(new SimplePrincipal(username));
- identity.postAuthenticate();
-
- autoLoggedIn = true;
- }
- }
- }
- }
-
- @Observer(Identity.EVENT_LOGGED_OUT)
- public void loggedOut()
- {
- if (mode.equals(Mode.autoLogin))
- {
- tokenSelector.clearCookieValue();
- }
- }
-
- @Observer(Identity.EVENT_POST_AUTHENTICATE)
- public void postAuthenticate(Identity identity)
- {
- if (mode.equals(Mode.usernameOnly))
- {
- // Password is set to null during authentication, so we set dirty
- usernameSelector.setDirty();
-
- if ( !enabled )
- {
- usernameSelector.clearCookieValue();
- }
- else
- {
- usernameSelector.setCookieMaxAge(cookieMaxAge);
- usernameSelector.setCookieValueIfEnabled( Identity.instance().getCredentials().getUsername() );
- }
- }
- else if (mode.equals(Mode.autoLogin))
- {
- tokenSelector.setDirty();
-
- DecodedToken decoded = new DecodedToken(tokenSelector.getCookieValue());
-
- // Invalidate the current token (if it exists) whether enabled or not
- if (decoded.getUsername() != null)
- {
- tokenStore.invalidateToken(decoded.getUsername(), decoded.getValue());
- }
-
- if ( !enabled )
- {
- tokenSelector.clearCookieValue();
- }
- else
- {
- String value = generateTokenValue();
- tokenStore.createToken(identity.getPrincipal().getName(), value);
- tokenSelector.setCookieEnabled(enabled);
- tokenSelector.setCookieMaxAge(cookieMaxAge);
- tokenSelector.setCookieValueIfEnabled(encodeToken(identity.getPrincipal().getName(), value));
- }
- }
- }
-
- @Observer(Credentials.EVENT_CREDENTIALS_UPDATED)
- public void credentialsUpdated()
- {
- if (mode.equals(Mode.usernameOnly))
- {
- usernameSelector.setDirty();
- }
- }
-
- /**
- * A flag that an application can use to protect sensitive operations if the user has been
- * auto-authenticated.
- */
- public boolean isAutoLoggedIn()
- {
- return autoLoggedIn;
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/Role.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/Role.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/Role.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,28 +0,0 @@
-package org.jboss.seam.security;
-
-/**
- * Represents a user role. A conditional role is a special type of role that is assigned to a user
- * based on the contextual state of a permission check.
- *
- * @author Shane Bryzak
- */
-public class Role extends SimplePrincipal
-{
- private boolean conditional;
-
- public Role(String name)
- {
- super(name);
- }
-
- public Role(String name, boolean conditional)
- {
- this(name);
- this.conditional = conditional;
- }
-
- public boolean isConditional()
- {
- return conditional;
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/RunAsOperation.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/RunAsOperation.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/RunAsOperation.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,77 +0,0 @@
-package org.jboss.seam.security;
-
-import java.security.Principal;
-import java.security.acl.Group;
-
-import javax.security.auth.Subject;
-
-/**
- * Defines a security operation that can be executed within a particular
- * security context.
- *
- * @author Shane Bryzak
- */
-public abstract class RunAsOperation
-{
- private Principal principal;
- private Subject subject;
-
- private boolean systemOp = false;
-
- public RunAsOperation()
- {
- principal = new SimplePrincipal(null);
- subject = new Subject();
- }
-
- /**
- * A system operation allows any security checks to pass
- *
- * @param systemOp
- */
- public RunAsOperation(boolean systemOp)
- {
- this();
- this.systemOp = systemOp;
- }
-
- public abstract void execute();
-
- public Principal getPrincipal()
- {
- return principal;
- }
-
- public Subject getSubject()
- {
- return subject;
- }
-
- public RunAsOperation addRole(String role)
- {
- for ( Group sg : getSubject().getPrincipals(Group.class) )
- {
- if ( Identity.ROLES_GROUP.equals( sg.getName() ) )
- {
- sg.addMember(new SimplePrincipal(role));
- break;
- }
- }
-
- SimpleGroup roleGroup = new SimpleGroup(Identity.ROLES_GROUP);
- roleGroup.addMember(new SimplePrincipal(role));
- getSubject().getPrincipals().add(roleGroup);
-
- return this;
- }
-
- public boolean isSystemOperation()
- {
- return systemOp;
- }
-
- public void run()
- {
- Identity.instance().runAs(this);
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/SecurityFunctions.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SecurityFunctions.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/SecurityFunctions.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,31 +0,0 @@
-package org.jboss.seam.security;
-
-/**
- * Delegating wrapper for EL security functions.
- *
- * @author Shane Bryzak
- */
-public class SecurityFunctions
-{
- public static boolean hasRole(String name)
- {
- return Identity.instance().hasRole(name);
- }
-
- public static boolean hasPermission(String name, String action, Object arg)
- {
- if (arg != null)
- {
- return Identity.instance().hasPermission(name, action, arg);
- }
- else
- {
- return Identity.instance().hasPermission(name, action);
- }
- }
-
- public static boolean hasPermission(Object target, String action)
- {
- return Identity.instance().hasPermission(target, action);
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/SecurityInterceptor.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,301 +0,0 @@
-package org.jboss.seam.security;
-
-import java.io.Serializable;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.seam.annotations.intercept.AroundInvoke;
-import org.jboss.seam.annotations.intercept.Interceptor;
-import org.jboss.seam.annotations.intercept.InterceptorType;
-import org.jboss.seam.annotations.security.PermissionCheck;
-import org.jboss.seam.annotations.security.Restrict;
-import org.jboss.seam.annotations.security.RoleCheck;
-import org.jboss.seam.async.AsynchronousInterceptor;
-import org.jboss.seam.intercept.AbstractInterceptor;
-import org.jboss.seam.intercept.InvocationContext;
-import org.jboss.seam.transaction.RollbackInterceptor;
-import org.jboss.seam.util.Strings;
-
-/**
- * Provides authorization services for component invocations.
- *
- * @author Shane Bryzak
- */
- at Interceptor(type=InterceptorType.CLIENT,
- around=AsynchronousInterceptor.class, within = RollbackInterceptor.class)
-public class SecurityInterceptor extends AbstractInterceptor implements Serializable
-{
- private static final long serialVersionUID = -6567750187000766925L;
-
- /**
- * You may encounter a JVM bug where the field initializer is not evaluated for a transient field after deserialization.
- * @see "http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6252102"
- */
- private transient volatile Map<Method,Restriction> restrictions = new HashMap<Method,Restriction>();
-
- private class Restriction
- {
- private String expression;
-
- private String permissionTarget;
- private String permissionAction;
-
- private Map<String, Object> methodRestrictions;
- private Map<Integer,Set<String>> paramRestrictions;
- private Set<String> roleRestrictions;
-
- public void setExpression(String expression)
- {
- this.expression = expression;
- }
-
- public void setPermissionTarget(String target)
- {
- this.permissionTarget = target;
- }
-
- public void setPermissionAction(String action)
- {
- this.permissionAction = action;
- }
-
- public void addMethodRestriction(Object target, String action)
- {
- if (methodRestrictions == null)
- {
- methodRestrictions = new HashMap<String, Object>();
- }
-
- methodRestrictions.put(action, target);
- }
-
- public void addRoleRestriction(String role)
- {
- if (roleRestrictions == null)
- {
- roleRestrictions = new HashSet<String>();
- }
-
- roleRestrictions.add(role);
- }
-
- public void addParameterRestriction(int index, String action)
- {
- Set<String> actions = null;
-
- if (paramRestrictions == null)
- {
- paramRestrictions = new HashMap<Integer,Set<String>>();
- }
-
- if (!paramRestrictions.containsKey(index))
- {
- actions = new HashSet<String>();
- paramRestrictions.put(index, actions);
- }
- else
- {
- actions = paramRestrictions.get(index);
- }
-
- actions.add(action);
- }
-
- public void check(Object[] parameters)
- {
- if (Identity.isSecurityEnabled())
- {
- if (expression != null)
- {
- Identity.instance().checkRestriction(expression);
- }
-
- if (methodRestrictions != null)
- {
- for (String action : methodRestrictions.keySet())
- {
- Identity.instance().checkPermission(methodRestrictions.get(action), action);
- }
- }
-
- if (paramRestrictions != null)
- {
- for (Integer idx : paramRestrictions.keySet())
- {
- Set<String> actions = paramRestrictions.get(idx);
- for (String action : actions)
- {
- Identity.instance().checkPermission(parameters[idx], action);
- }
- }
- }
-
- if (roleRestrictions != null)
- {
- for (String role : roleRestrictions)
- {
- Identity.instance().checkRole(role);
- }
- }
-
- if (permissionTarget != null && permissionAction != null)
- {
- Identity.instance().checkPermission(permissionTarget, permissionAction);
- }
- }
- }
- }
-
- @AroundInvoke
- public Object aroundInvoke(InvocationContext invocation) throws Exception
- {
- Method interfaceMethod = invocation.getMethod();
-
- if (!"hashCode".equals(interfaceMethod.getName()))
- {
- Restriction restriction = getRestriction(interfaceMethod);
- if ( restriction != null ) restriction.check(invocation.getParameters());
- }
-
- return invocation.proceed();
- }
-
- private Restriction getRestriction(Method interfaceMethod) throws Exception
- {
- // see field declaration as to why this is done
- if (restrictions == null)
- {
- synchronized(this)
- {
- restrictions = new HashMap<Method, Restriction>();
- }
- }
-
- if (!restrictions.containsKey(interfaceMethod))
- {
- synchronized(restrictions)
- {
- // FIXME this logic should be abstracted rather than sitting in the middle of this interceptor
- if (!restrictions.containsKey(interfaceMethod))
- {
- Restriction restriction = null;
-
- Method method = getComponent().getBeanClass().getMethod(
- interfaceMethod.getName(), interfaceMethod.getParameterTypes() );
-
- Restrict restrict = null;
-
- if ( method.isAnnotationPresent(Restrict.class) )
- {
- restrict = method.getAnnotation(Restrict.class);
- }
- else if ( getComponent().getBeanClass().isAnnotationPresent(Restrict.class) )
- {
- if ( !getComponent().isLifecycleMethod(method) )
- {
- restrict = getComponent().getBeanClass().getAnnotation(Restrict.class);
- }
- }
-
- if (restrict != null)
- {
- if (restriction == null) restriction = new Restriction();
-
- if ( Strings.isEmpty(restrict.value()) )
- {
- restriction.setPermissionTarget(getComponent().getName());
- restriction.setPermissionAction(method.getName());
- }
- else
- {
- restriction.setExpression(restrict.value());
- }
- }
-
- for (Annotation annotation : method.getDeclaringClass().getAnnotations())
- {
- if (annotation.annotationType().isAnnotationPresent(RoleCheck.class))
- {
- if (restriction == null) restriction = new Restriction();
- restriction.addRoleRestriction(annotation.annotationType().getSimpleName().toLowerCase());
- }
- }
-
- for (Annotation annotation : method.getAnnotations())
- {
- if (annotation.annotationType().isAnnotationPresent(PermissionCheck.class))
- {
- PermissionCheck permissionCheck = annotation.annotationType().getAnnotation(
- PermissionCheck.class);
-
- Method valueMethod = null;
- for (Method m : annotation.annotationType().getDeclaredMethods())
- {
- valueMethod = m;
- break;
- }
-
- if (valueMethod != null)
- {
- if (restriction == null) restriction = new Restriction();
- Object target = valueMethod.invoke(annotation);
- if (!target.equals(void.class))
- {
- if (restriction == null) restriction = new Restriction();
- restriction.addMethodRestriction(target,
- getPermissionAction(permissionCheck, annotation));
- }
- }
- }
- if (annotation.annotationType().isAnnotationPresent(RoleCheck.class))
- {
- if (restriction == null) restriction = new Restriction();
- restriction.addRoleRestriction(annotation.annotationType().getSimpleName().toLowerCase());
- }
- }
-
- for (int i = 0; i < method.getParameterAnnotations().length; i++)
- {
- Annotation[] annotations = method.getParameterAnnotations()[i];
- for (Annotation annotation : annotations)
- {
- if (annotation.annotationType().isAnnotationPresent(PermissionCheck.class))
- {
- PermissionCheck permissionCheck = annotation.annotationType().getAnnotation(
- PermissionCheck.class);
- if (restriction == null) restriction = new Restriction();
- restriction.addParameterRestriction(i,
- getPermissionAction(permissionCheck, annotation));
- }
- }
- }
-
- restrictions.put(interfaceMethod, restriction);
- return restriction;
- }
- }
- }
- return restrictions.get(interfaceMethod);
- }
-
- private String getPermissionAction(PermissionCheck check, Annotation annotation)
- {
- if (!"".equals(check.value()))
- {
- return check.value();
- }
- else
- {
- return annotation.annotationType().getSimpleName().toLowerCase();
- }
- }
-
- public boolean isInterceptorEnabled()
- {
- return getComponent().isSecure() && !getComponent().beanClassHasAnnotation("javax.jws.WebService");
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/SimpleGroup.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SimpleGroup.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/SimpleGroup.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,93 +0,0 @@
-package org.jboss.seam.security;
-
-import java.io.Serializable;
-import java.security.Principal;
-import java.security.acl.Group;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * Implementation of the Group interface, used for holding roles etc.
- *
- * @author Shane Bryzak
- */
-public class SimpleGroup implements Group, Serializable
-{
- private static final long serialVersionUID = 5766373925836425908L;
-
- /**
- * The name of the group
- */
- private String name;
-
- /**
- * The members of this group
- */
- private Set<Principal> members = new HashSet<Principal>();
-
- public SimpleGroup(String name)
- {
- this.name = name;
- }
-
- public boolean addMember(Principal user)
- {
- return members.add(user);
- }
-
- public boolean isMember(Principal member)
- {
- if ( members.contains(member) )
- {
- return true;
- }
- else
- {
- for (Principal m : members)
- {
- if (m instanceof Group && ((Group) m).isMember(member))
- {
- return true;
- }
- }
- }
- return false;
- }
-
- public Enumeration<? extends Principal> members()
- {
- return Collections.enumeration(members);
- }
-
- public boolean removeMember(Principal user)
- {
- return members.remove(user);
- }
-
- public String getName()
- {
- return name;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (obj instanceof SimpleGroup)
- {
- SimpleGroup other = (SimpleGroup) obj;
- return other.name.equals(name);
- }
- else
- {
- return false;
- }
- }
-
- @Override
- public int hashCode()
- {
- return name.hashCode();
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/SimplePrincipal.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/SimplePrincipal.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/SimplePrincipal.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,54 +0,0 @@
-package org.jboss.seam.security;
-
-import java.io.Serializable;
-import java.security.Principal;
-
-/**
- * Simple implementation of the Principal interface, supporting a named user.
- *
- * @author Shane Bryzak
- */
-public class SimplePrincipal implements Principal, Serializable
-{
- private static final long serialVersionUID = 5609375932836425908L;
-
- private String name;
-
- public SimplePrincipal(String name)
- {
- this.name = name;
- }
-
- public String getName()
- {
- return name;
- }
-
- @Override
- public boolean equals(Object obj)
- {
- if (obj instanceof Principal)
- {
- Principal other = (Principal) obj;
- return name == null ?
- other.getName() == null :
- name.equals( other.getName() );
- }
- else
- {
- return false;
- }
- }
-
- @Override
- public int hashCode()
- {
- return name != null ? name.hashCode() : super.hashCode();
- }
-
- @Override
- public String toString()
- {
- return name;
- }
-}
Deleted: trunk/src/main/org/jboss/seam/security/TokenStore.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/TokenStore.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/TokenStore.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,15 +0,0 @@
-package org.jboss.seam.security;
-
-/**
- * A store containing user authentication tokens. Used in conjunction with the RememberMe
- * component to auto-login users that present a valid cookie-based token.
- *
- * @author Shane Bryzak
- */
-public interface TokenStore
-{
- void createToken(String username, String value);
- boolean validateToken(String username, String value);
- void invalidateToken(String username, String value);
- void invalidateAll(String username);
-}
Deleted: trunk/src/main/org/jboss/seam/security/package-info.java
===================================================================
--- trunk/src/main/org/jboss/seam/security/package-info.java 2009-04-19 09:32:07 UTC (rev 10475)
+++ trunk/src/main/org/jboss/seam/security/package-info.java 2009-04-19 09:44:29 UTC (rev 10476)
@@ -1,12 +0,0 @@
-/**
- * Seam Security
- *
- * @see org.jboss.seam.security.Identity
- * @see org.jboss.seam.annotations.security.Restrict
- */
- at Namespace(value="http://jboss.com/products/seam/security", prefix="org.jboss.seam.security")
- at AutoCreate
-package org.jboss.seam.security;
-
-import org.jboss.seam.annotations.AutoCreate;
-import org.jboss.seam.annotations.Namespace;
More information about the seam-commits
mailing list