You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by gh...@apache.org on 2020/09/22 00:09:32 UTC

[sling-org-apache-sling-auth-core] branch feature/SLING-9662-Introduce-SlingUri-Mapping-SPI-v3 created (now 64326ae)

This is an automated email from the ASF dual-hosted git repository.

ghenzler pushed a change to branch feature/SLING-9662-Introduce-SlingUri-Mapping-SPI-v3
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-core.git.


      at 64326ae  SLING-9662 Use PathToUriMappingService to pre-process path before authentication

This branch includes the following new commits:

     new 64326ae  SLING-9662 Use PathToUriMappingService to pre-process path before authentication

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[sling-org-apache-sling-auth-core] 01/01: SLING-9662 Use PathToUriMappingService to pre-process path before authentication

Posted by gh...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ghenzler pushed a commit to branch feature/SLING-9662-Introduce-SlingUri-Mapping-SPI-v3
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-auth-core.git

commit 64326aee30a3b904ffa21c8e67162df69575e31a
Author: georg.henzler <ge...@netcentric.biz>
AuthorDate: Mon Sep 21 10:44:56 2020 +0200

    SLING-9662 Use PathToUriMappingService to pre-process path before
    authentication
---
 pom.xml                                            |  2 +-
 .../sling/auth/core/AuthenticationSupport.java     |  8 +++
 .../sling/auth/core/impl/SlingAuthenticator.java   | 33 +++++-----
 .../org/apache/sling/auth/core/package-info.java   |  4 +-
 .../auth/core/impl/SlingAuthenticatorTest.java     | 77 ++++++++++------------
 5 files changed, 64 insertions(+), 60 deletions(-)

diff --git a/pom.xml b/pom.xml
index fb78d39..4b03116 100644
--- a/pom.xml
+++ b/pom.xml
@@ -71,7 +71,7 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.api</artifactId>
-            <version>2.20.0</version>
+            <version>2.23.0-SNAPSHOT</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
diff --git a/src/main/java/org/apache/sling/auth/core/AuthenticationSupport.java b/src/main/java/org/apache/sling/auth/core/AuthenticationSupport.java
index 7257110..0f2dd4d 100644
--- a/src/main/java/org/apache/sling/auth/core/AuthenticationSupport.java
+++ b/src/main/java/org/apache/sling/auth/core/AuthenticationSupport.java
@@ -85,6 +85,14 @@ public interface AuthenticationSupport {
     static final String REQUEST_ATTRIBUTE_RESOLVER = "org.apache.sling.auth.core.ResourceResolver";
 
     /**
+     * The name of the request attribute set by the {@link #handleSecurity(HttpServletRequest, HttpServletResponse)} method for the request
+     * URI that was resolved already.
+     * <p>
+     * The request attribute is set to a Sling <code>SlingUri</code> as provided by PathToUriMappingService.resolve().
+     */
+    static final String REQUEST_ATTRIBUTE_URI = "org.apache.sling.auth.core.SlingUri";
+
+    /**
      * The name of the request parameter indicating where to redirect to after
      * successful authentication (and optional impersonation). This parameter is
      * respected if either anonymous authentication or regular authentication
diff --git a/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java b/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
index 6e203cc..0f2054a 100644
--- a/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
+++ b/src/main/java/org/apache/sling/auth/core/impl/SlingAuthenticator.java
@@ -50,6 +50,8 @@ import org.apache.sling.api.auth.NoAuthenticationHandlerException;
 import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.mapping.PathToUriMappingService;
+import org.apache.sling.api.uri.SlingUri;
 import org.apache.sling.auth.core.AuthConstants;
 import org.apache.sling.auth.core.AuthUtil;
 import org.apache.sling.auth.core.AuthenticationSupport;
@@ -260,6 +262,9 @@ public class SlingAuthenticator implements Authenticator,
     @Reference
     private ResourceResolverFactory resourceResolverFactory;
 
+    @Reference
+    private PathToUriMappingService pathToUriMappingService;
+
     private PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authHandlerCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
 
     // package protected for access in inner class ...
@@ -506,7 +511,7 @@ public class SlingAuthenticator implements Authenticator,
 
     private boolean doHandleSecurity(HttpServletRequest request, HttpServletResponse response) {
 
-        // 0. Check for request attribute; set if not present
+        // 0 Check for request attribute; set if not present
         Object authUriSufficesAttr = request
                 .getAttribute(AuthConstants.ATTR_REQUEST_AUTH_URI_SUFFIX);
         if (authUriSufficesAttr == null && authUriSuffices != null) {
@@ -747,22 +752,18 @@ public class SlingAuthenticator implements Authenticator,
      * @return The path
      */
     private String getPath(final HttpServletRequest request) {
-        final StringBuilder sb = new StringBuilder();
-        if (request.getServletPath() != null) {
-            sb.append(request.getServletPath());
-        }
-        if (request.getPathInfo() != null) {
-            sb.append(request.getPathInfo());
-        }
-        String path = sb.toString();
-        // Get the path used to select the authenticator, if the SlingServlet
-        // itself has been requested without any more info, this will be empty
-        // and we assume the root (SLING-722)
-        if (path.length() == 0) {
-            path = "/";
-        }
 
-        return path;
+        // this method is safely called from all three public entry points (that is handleSecurity(), login(), logout())
+        // for all execution paths
+        // therefore Sling engine may rely on AuthenticationSupport.REQUEST_ATTRIBUTE_URI
+
+        SlingUri slingUri = (SlingUri) request.getAttribute(AuthenticationSupport.REQUEST_ATTRIBUTE_URI);
+        if (slingUri == null) {
+            slingUri = pathToUriMappingService.resolve(request, null).getUri();
+            request.setAttribute(AuthenticationSupport.REQUEST_ATTRIBUTE_URI, slingUri);
+        }
+        
+        return slingUri.getPath();
     }
 
     private AuthenticationInfo getAuthenticationInfo(HttpServletRequest request, HttpServletResponse response) {
diff --git a/src/main/java/org/apache/sling/auth/core/package-info.java b/src/main/java/org/apache/sling/auth/core/package-info.java
index 66dee4f..f8d608e 100755
--- a/src/main/java/org/apache/sling/auth/core/package-info.java
+++ b/src/main/java/org/apache/sling/auth/core/package-info.java
@@ -22,9 +22,9 @@
  * of utility functions in the {@link org.apache.sling.auth.core.AuthUtil}
  * class.
  *
- * @version 1.4.0
+ * @version 1.5.0
  */
-@org.osgi.annotation.versioning.Version("1.4.0")
+@org.osgi.annotation.versioning.Version("1.5.0")
 package org.apache.sling.auth.core;
 
 
diff --git a/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorTest.java b/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorTest.java
index d3654cf..97cfd51 100644
--- a/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorTest.java
+++ b/src/test/java/org/apache/sling/auth/core/impl/SlingAuthenticatorTest.java
@@ -18,22 +18,49 @@
  */
 package org.apache.sling.auth.core.impl;
 
+import static org.mockito.Mockito.when;
+
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.sling.api.resource.mapping.PathToUriMappingService;
+import org.apache.sling.api.uri.SlingUriBuilder;
 import org.apache.sling.auth.core.spi.AuthenticationFeedbackHandler;
 import org.apache.sling.auth.core.spi.AuthenticationInfo;
 import org.junit.Assert;
+import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
 
 import junitx.util.PrivateAccessor;
 
+@RunWith(MockitoJUnitRunner.class)
 public class SlingAuthenticatorTest {
 
+    @InjectMocks
+    SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
+
+    @Mock
+    PathToUriMappingService pathToUriMappingService;
+
+    @Mock
+    HttpServletRequest request;
+
+    @Mock
+    PathToUriMappingService.Result resolveResult;
+
+    @Before
+    public void setup() {
+        when(pathToUriMappingService.resolve(request, null)).thenReturn(resolveResult);
+    }
+
     @Test
     public void test_quoteCookieValue() throws UnsupportedEncodingException {
 
@@ -82,14 +109,13 @@ public class SlingAuthenticatorTest {
     //SLING-4864
     @Test
     public void  test_isAnonAllowed() throws Throwable {
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
-        PathBasedHolderCache<AuthenticationRequirementHolder> authRequiredCache = new PathBasedHolderCache<AuthenticationRequirementHolder>();
+        when(resolveResult.getUri()).thenReturn(SlingUriBuilder.parse("/", null).build());
 
+        PathBasedHolderCache<AuthenticationRequirementHolder> authRequiredCache = new PathBasedHolderCache<AuthenticationRequirementHolder>();
         authRequiredCache.addHolder(new AuthenticationRequirementHolder("/", false, null));
 
         PrivateAccessor.setField(slingAuthenticator, "authRequiredCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         Mockito.when(request.getServerName()).thenReturn("localhost");
         Mockito.when(request.getServerPort()).thenReturn(80);
         Mockito.when(request.getScheme()).thenReturn("http");
@@ -109,13 +135,10 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH = "/content/en/test";
         final String REQUEST_CHILD_NODE = "/content/en/test/childnodetest";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_CHILD_NODE);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
@@ -136,13 +159,10 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH = "/content/en/test";
         final String REQUEST_CHILD_NODE = "/content/en/test";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_CHILD_NODE);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
@@ -163,13 +183,10 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH = "/content/en/test";
         final String REQUEST_CHILD_NODE = "/content/en/test/";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_CHILD_NODE);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
@@ -190,13 +207,10 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH = "/content/en/test";
         final String REQUEST_CHILD_NODE = "/content/en/test.html";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_CHILD_NODE);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
@@ -213,13 +227,10 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH = "/";
         final String REQUEST_CHILD_NODE = "/content/en/test";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_CHILD_NODE);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
@@ -238,14 +249,11 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH_LONGER = "/resource1.test2";
         final String REQUEST_CHILD_NODE = "/resource1.test2";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE_LONGER, PROTECTED_PATH_LONGER));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_CHILD_NODE);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
@@ -279,19 +287,16 @@ public class SlingAuthenticatorTest {
         final String PROTECTED_PATH = "/content/en/test";
         final String REQUEST_NOT_PROTECTED_PATH = "/content/en/test2";
 
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
-
         PathBasedHolderCache<AbstractAuthenticationHandlerHolder> authRequiredCache = new PathBasedHolderCache<AbstractAuthenticationHandlerHolder>();
         authRequiredCache.addHolder(buildAuthHolderForAuthTypeAndPath(AUTH_TYPE, PROTECTED_PATH));
 
         PrivateAccessor.setField(slingAuthenticator, "authHandlerCache", authRequiredCache);
-        final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
         buildExpectationsForRequest(request, REQUEST_NOT_PROTECTED_PATH);
 
         AuthenticationInfo authInfo = (AuthenticationInfo) PrivateAccessor.invoke(slingAuthenticator, "getAuthenticationInfo",
                 new Class[]{HttpServletRequest.class, HttpServletResponse.class}, new Object[]{request, Mockito.mock(HttpServletResponse.class)});
         /**
-         * The AUTH TYPE defined aboved should not be used for the path /test2.
+         * The AUTH TYPE defined above should not be used for the path /test2.
          */
         Assert.assertFalse(AUTH_TYPE.equals(authInfo.getAuthType()));
     }
@@ -300,7 +305,6 @@ public class SlingAuthenticatorTest {
     public void test_childNodeAuthenticationHandlerPath() throws Throwable {
         final String requestPath = "/content/test/test2";
         final String handlerPath = "/content/test";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertTrue( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -309,7 +313,6 @@ public class SlingAuthenticatorTest {
     public void test_siblingNodeAuthenticationHandlerPath() throws Throwable {
         final String requestPath = "/content/test2.html/en/2016/09/19/test.html";
         final String handlerPath = "/content/test";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertFalse( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -318,7 +321,6 @@ public class SlingAuthenticatorTest {
     public void test_actualNodeAuthenticationHandlerPath() throws Throwable {
         final String requestPath = "/content/test";
         final String handlerPath = "/content/test";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertTrue( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -327,7 +329,6 @@ public class SlingAuthenticatorTest {
     public void test_rootNodeAuthenticationHandlerPath() throws Throwable {
         final String requestPath = "/content/test";
         final String handlerPath = "/";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertTrue( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -336,7 +337,6 @@ public class SlingAuthenticatorTest {
     public void test_requestPathSelectorsAreTakenInConsideration() throws Throwable {
         final String requestPath = "/content/test.selector1.selector2.html/en/2016/test.html";
         final String handlerPath = "/content/test";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertTrue( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -345,7 +345,6 @@ public class SlingAuthenticatorTest {
     public void test_requestPathSelectorsSiblingAreTakenInConsideration() throws Throwable {
         final String requestPath = "/content/test.selector1.selector2.html/en/2016/09/19/test.html";
         final String handlerPath = "/content/test2";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertFalse( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -354,7 +353,6 @@ public class SlingAuthenticatorTest {
     public void test_requestPathBackSlash() throws Throwable {
         final String requestPath = "/page1\\somesubepage";
         final String handlerPath = "/page";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertFalse( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -363,7 +361,6 @@ public class SlingAuthenticatorTest {
     public void test_emptyNodeAuthenticationHandlerPath() throws Throwable {
         final String requestPath = "/content/test";
         final String handlerPath = "";
-        SlingAuthenticator slingAuthenticator = new SlingAuthenticator();
 
         Assert.assertTrue( (boolean)PrivateAccessor.invoke(slingAuthenticator, "isNodeRequiresAuthHandler", new Class[] {String.class, String.class}, new Object[] {requestPath, handlerPath}));
     }
@@ -376,14 +373,12 @@ public class SlingAuthenticatorTest {
      * @param request http request
      * @param requestPath request path
      */
-    private void buildExpectationsForRequest(final HttpServletRequest request,
-            final String requestPath) {
-        {
-            Mockito.when(request.getServletPath()).thenReturn(requestPath);
-            Mockito.when(request.getServerName()).thenReturn("localhost");
-            Mockito.when(request.getServerPort()).thenReturn(80);
-            Mockito.when(request.getScheme()).thenReturn("http");
-        }
+    private void buildExpectationsForRequest(final HttpServletRequest request, final String requestPath) {
+        // path is not taken directly from request but from PathToUriMappingService
+        when(resolveResult.getUri()).thenReturn(SlingUriBuilder.parse(requestPath, null).build());
+        when(request.getServerName()).thenReturn("localhost");
+        when(request.getServerPort()).thenReturn(80);
+        when(request.getScheme()).thenReturn("http");
     }
 
     /**