You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2019/08/03 09:56:51 UTC
[isis] branch v2 updated: ISIS-2156 bump shiro version 1.3.2 ->
1.4.1
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch v2
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/v2 by this push:
new 780d73e ISIS-2156 bump shiro version 1.3.2 -> 1.4.1
780d73e is described below
commit 780d73e9de7289d9edd877f2b763250c96e77344
Author: Andi Huber <ah...@apache.org>
AuthorDate: Sat Aug 3 11:56:35 2019 +0200
ISIS-2156 bump shiro version 1.3.2 -> 1.4.1
- despite the unresolved shiro issue [1], however the mentioned
workaround appears to work:
filterChainResolver =
org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver
[1] https://issues.apache.org/jira/browse/SHIRO-610
---
.../commons/internal/memento/MementosTest.java | 2 +-
.../apache/isis/commons/internal/base/_Casts.java | 48 ++++++++++++++-----
.../apache/isis/security/shiro/WebModuleShiro.java | 11 +++++
core/pom.xml | 4 +-
.../secman/shiro/AuthInfoForApplicationUser.java | 21 +++++++--
.../secman/shiro/IsisModuleSecurityRealm.java | 55 ++++++++++++++++------
.../isis/extensions/secman/shiro/ShiroUtils.java | 5 ++
7 files changed, 111 insertions(+), 35 deletions(-)
diff --git a/core/applib/src/test/java/org/apache/isis/commons/internal/memento/MementosTest.java b/core/applib/src/test/java/org/apache/isis/commons/internal/memento/MementosTest.java
index 537336a..5a121ef 100644
--- a/core/applib/src/test/java/org/apache/isis/commons/internal/memento/MementosTest.java
+++ b/core/applib/src/test/java/org/apache/isis/commons/internal/memento/MementosTest.java
@@ -64,7 +64,7 @@ public class MementosTest {
@Override
public <T> T read(Class<T> cls, Serializable value) {
- return _Casts.castToOrElseGet(value, cls, ()->null);
+ return _Casts.castToOrElseNull(value, cls);
}
};
diff --git a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Casts.java b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Casts.java
index 2631251..cd433c1 100644
--- a/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Casts.java
+++ b/core/commons/src/main/java/org/apache/isis/commons/internal/base/_Casts.java
@@ -19,8 +19,8 @@
package org.apache.isis.commons.internal.base;
+import java.util.Optional;
import java.util.function.BiFunction;
-import java.util.function.Supplier;
import javax.annotation.Nullable;
@@ -48,22 +48,44 @@ public final class _Casts {
}
/**
- * Returns the casts of {@code value} to {@code cls}, or if this fails returns the result of {@code orElse}
+ * Casts an object to the class or interface represented by given {@code cls} Class object,
+ * then wraps the result in an {@link Optional}. The {@link Optional} is empty if the cast
+ * fails or provided {@code value} is {@code null}.
+ * @param <T>
* @param value
* @param cls
- * @param orElse
- * @return
+ * @return non-null
*/
- public static <T> T castToOrElseGet(@Nullable Object value, Class<T> cls, Supplier<T> orElse) {
-
- try {
- return requires(cls, "cls").cast(value);
- } catch (Exception e) {
- return requires(orElse, "orElse").get();
+ public static <T> Optional<T> castTo(@Nullable Object value, Class<T> cls) {
+ if(value==null) {
+ return Optional.empty();
}
-
+ requires(cls, "cls");
+ if(cls.isAssignableFrom(value.getClass())) {
+ return Optional.of(cls.cast(value));
+ }
+ return Optional.empty();
}
-
+
+ /**
+ * Casts an object to the class or interface represented by given {@code cls} Class object.
+ * Returns {@code null}, if the cast fails or provided {@code value} is {@code null}.
+ * @param <T>
+ * @param value
+ * @param cls
+ * @return casted value, or null
+ */
+ public static @Nullable <T> T castToOrElseNull(@Nullable Object value, Class<T> cls) {
+ if(value==null) {
+ return null;
+ }
+ requires(cls, "cls");
+ if(cls.isAssignableFrom(value.getClass())) {
+ return cls.cast(value);
+ }
+ return null;
+ }
+
/**
* Dependent on whether left or right can be cast to {@code cls}, the appropriate functional
* interface is chosen to produce the result.
@@ -123,4 +145,6 @@ public final class _Casts {
}
+
+
}
diff --git a/core/plugins/security-shiro/src/main/java/org/apache/isis/security/shiro/WebModuleShiro.java b/core/plugins/security-shiro/src/main/java/org/apache/isis/security/shiro/WebModuleShiro.java
index cce7902..ba560a4 100644
--- a/core/plugins/security-shiro/src/main/java/org/apache/isis/security/shiro/WebModuleShiro.java
+++ b/core/plugins/security-shiro/src/main/java/org/apache/isis/security/shiro/WebModuleShiro.java
@@ -18,6 +18,9 @@
*/
package org.apache.isis.security.shiro;
+import java.util.HashMap;
+import java.util.Map;
+
import javax.inject.Singleton;
import javax.servlet.FilterRegistration.Dynamic;
import javax.servlet.ServletContext;
@@ -27,6 +30,7 @@ import javax.servlet.ServletException;
import org.apache.shiro.config.Ini;
import org.apache.shiro.web.env.IniWebEnvironment;
import org.apache.shiro.web.env.WebEnvironment;
+import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
@@ -78,6 +82,13 @@ public final class WebModuleShiro implements WebModule {
}
return null;
}
+ // see https://issues.apache.org/jira/browse/SHIRO-610
+ @Override
+ protected Map<String, Object> getDefaults() {
+ Map<String, Object> defaults = new HashMap<String, Object>();
+ defaults.put(FILTER_CHAIN_RESOLVER_NAME, new PathMatchingFilterChainResolver());
+ return defaults;
+ }
}
public static void setShiroIniResource(String resourcePath) {
diff --git a/core/pom.xml b/core/pom.xml
index 8eba16c..00e9fc5 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -111,14 +111,12 @@
<resteasy4-jaxrs.version>4.0.0.Beta5</resteasy4-jaxrs.version>
<!-- failing to update to Shiro 1.4.0, running into unresolved issue: https://issues.apache.org/jira/browse/SHIRO-610 -->
- <shiro.version>1.3.2</shiro.version>
+ <shiro.version>1.4.1</shiro.version>
<lombok.version>[1.18.,)</lombok.version>
<joda-time.version>2.9.4</joda-time.version>
- <!-- wicket-guice 8.2.0 requires guice 4.2.2, which requires guava 25.1-android -->
- <guice.version>4.1.0</guice.version>
<guava.version>19.0</guava.version>
<hamcrest.version>1.3</hamcrest.version>
diff --git a/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/AuthInfoForApplicationUser.java b/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/AuthInfoForApplicationUser.java
index a496670..81b7f8b 100644
--- a/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/AuthInfoForApplicationUser.java
+++ b/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/AuthInfoForApplicationUser.java
@@ -26,7 +26,10 @@ import org.apache.shiro.authz.Permission;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
+import org.apache.isis.commons.internal.base._Lazy;
+
import lombok.Getter;
+import lombok.NonNull;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@@ -34,13 +37,13 @@ class AuthInfoForApplicationUser implements AuthenticationInfo, AuthorizationInf
private static final long serialVersionUID = 1L;
- private final PrincipalForApplicationUser principal;
- private final String realmName;
- @Getter private final Object credentials;
+ @NonNull private final PrincipalForApplicationUser principal;
+ @NonNull private final String realmName;
+ @NonNull @Getter private final Object credentials;
@Override
public PrincipalCollection getPrincipals() {
- return new SimplePrincipalCollection(principal, realmName);
+ return principalCollection.get();
}
@Override
@@ -57,4 +60,14 @@ class AuthInfoForApplicationUser implements AuthenticationInfo, AuthorizationInf
public Collection<Permission> getObjectPermissions() {
return principal.getObjectPermissions();
}
+
+ // -- HELPER
+
+ private final transient _Lazy<PrincipalCollection> principalCollection =
+ _Lazy.threadSafe(this::createPrincipalCollection);
+
+ private PrincipalCollection createPrincipalCollection() {
+ return new SimplePrincipalCollection(principal, realmName);
+ }
+
}
diff --git a/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleSecurityRealm.java b/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleSecurityRealm.java
index 8ba458e..245faf2 100644
--- a/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleSecurityRealm.java
+++ b/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/IsisModuleSecurityRealm.java
@@ -83,24 +83,16 @@ public class IsisModuleSecurityRealm extends AuthorizingRealm implements Securit
// this code block is just an optimization, entirely optional
- // we reuse principal information on subjects that are already authenticated
{
- val currentSubject = SecurityUtils.getSubject();
- if(currentSubject!=null && currentSubject.isAuthenticated()) {
- val authenticatedPrincipalObject = currentSubject.getPrincipal();
- if(authenticatedPrincipalObject instanceof PrincipalForApplicationUser) {
- val authenticatedPrincipal = (PrincipalForApplicationUser) authenticatedPrincipalObject;
- val authenticatedUsername = authenticatedPrincipal.getUsername();
- val isAuthenticatedWithThisRealm = username.equals(authenticatedUsername);
- if(isAuthenticatedWithThisRealm) {
- val credentials = token.getCredentials();
- val realmName = getName();
- return new AuthInfoForApplicationUser(authenticatedPrincipal, realmName, credentials);
- }
- }
+ val alreadyAuthenticatedPrincipal =
+ getPrincipal_fromAlreadyAuthenticatedSubjectIfApplicable(token);
+ if(alreadyAuthenticatedPrincipal!=null) {
+ val credentials = token.getCredentials();
+ val realmName = getName();
+ return new AuthInfoForApplicationUser(alreadyAuthenticatedPrincipal, realmName, credentials);
}
}
-
+
// lookup from database, for roles/perms
val principal = lookupPrincipal_inApplicationUserRepository(username);
@@ -165,6 +157,39 @@ public class IsisModuleSecurityRealm extends AuthorizingRealm implements Securit
}
// -- HELPER
+
+ /**
+ * This is just an optimization, entirely optional.
+ * <p>
+ * We reuse principal information on subjects that are already authenticated,
+ * provided we are in a single realm authentication scenario.
+ * @param token
+ * @return {@code null} if not applicable
+ */
+ private PrincipalForApplicationUser getPrincipal_fromAlreadyAuthenticatedSubjectIfApplicable(
+ AuthenticationToken token) {
+
+ // this optimization is only implemented for the simple case of a single realm setup
+ if(!ShiroUtils.isSingleRealm()) {
+ return null;
+ }
+
+ val currentSubject = SecurityUtils.getSubject();
+ if(currentSubject!=null && currentSubject.isAuthenticated()) {
+ val authenticatedPrincipalObject = currentSubject.getPrincipal();
+ if(authenticatedPrincipalObject instanceof PrincipalForApplicationUser) {
+ val authenticatedPrincipal = (PrincipalForApplicationUser) authenticatedPrincipalObject;
+ val authenticatedUsername = authenticatedPrincipal.getUsername();
+ val usernamePasswordToken = (UsernamePasswordToken) token;
+ val username = usernamePasswordToken.getUsername();
+ val isAuthenticatedWithThisRealm = username.equals(authenticatedUsername);
+ if(isAuthenticatedWithThisRealm) {
+ return authenticatedPrincipal;
+ }
+ }
+ }
+ return null;
+ }
private DisabledAccountException disabledAccountException(String username) {
return new DisabledAccountException(String.format("username='%s'", username));
diff --git a/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/ShiroUtils.java b/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/ShiroUtils.java
index add72a8..fe1669d 100644
--- a/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/ShiroUtils.java
+++ b/extensions/secman/realm-shiro/src/main/java/org/apache/isis/extensions/secman/shiro/ShiroUtils.java
@@ -56,4 +56,9 @@ final class ShiroUtils {
return null;
}
+ public static boolean isSingleRealm() {
+ final RealmSecurityManager securityManager = getSecurityManager();
+ return securityManager.getRealms().size() == 1;
+ }
+
}