diff --git a/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/ApplicationConfig.java b/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/ApplicationConfig.java
index 67a5cca985..9c06eae78e 100644
--- a/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/ApplicationConfig.java
+++ b/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/ApplicationConfig.java
@@ -30,6 +30,7 @@
import org.apache.shiro.spring.remoting.SecureRemoteInvocationExecutor;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
+import org.apache.shiro.spring.web.config.ShiroRequestMappingConfig;
import org.apache.shiro.spring.web.config.ShiroWebConfiguration;
import org.apache.shiro.spring.web.config.ShiroWebFilterConfiguration;
import org.springframework.context.annotation.Bean;
@@ -53,7 +54,8 @@
ShiroWebConfiguration.class,
ShiroWebFilterConfiguration.class,
JspViewsConfig.class,
- RemotingServletConfig.class})
+ RemotingServletConfig.class,
+ ShiroRequestMappingConfig.class})
@ComponentScan("org.apache.shiro.samples.spring")
public class ApplicationConfig {
diff --git a/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/JspViewsConfig.java b/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/JspViewsConfig.java
index 551089cbb7..34f9912af8 100644
--- a/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/JspViewsConfig.java
+++ b/samples/spring-mvc/src/main/java/org/apache/shiro/samples/spring/config/JspViewsConfig.java
@@ -25,7 +25,7 @@
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;
@@ -35,7 +35,7 @@
@Configuration
@ComponentScan("org.apache.shiro.samples.spring")
@EnableWebMvc
-public class JspViewsConfig extends WebMvcConfigurerAdapter {
+public class JspViewsConfig implements WebMvcConfigurer {
@Bean
@Order(1)
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java
index 4ab440cb19..3b89b63334 100644
--- a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java
+++ b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebAutoConfiguration.java
@@ -33,9 +33,11 @@
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.spring.boot.autoconfigure.ShiroAutoConfiguration;
+import org.apache.shiro.spring.web.ShiroUrlPathHelper;
import org.apache.shiro.spring.web.config.AbstractShiroWebConfiguration;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.servlet.Cookie;
+import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
@@ -47,6 +49,7 @@
*/
@Configuration
@AutoConfigureBefore(ShiroAutoConfiguration.class)
+@AutoConfigureAfter(ShiroWebMvcAutoConfiguration.class)
@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
public class ShiroWebAutoConfiguration extends AbstractShiroWebConfiguration {
@@ -147,4 +150,11 @@ protected Cookie rememberMeCookieTemplate() {
protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
return super.shiroFilterChainDefinition();
}
+
+ @Bean
+ @ConditionalOnMissingBean
+ @Override
+ protected ShiroUrlPathHelper shiroUrlPathHelper() {
+ return super.shiroUrlPathHelper();
+ }
}
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebMvcAutoConfiguration.java b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebMvcAutoConfiguration.java
new file mode 100644
index 0000000000..26fdeb775d
--- /dev/null
+++ b/support/spring-boot/spring-boot-web-starter/src/main/java/org/apache/shiro/spring/config/web/autoconfigure/ShiroWebMvcAutoConfiguration.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.config.web.autoconfigure;
+
+import org.apache.shiro.spring.web.config.ShiroRequestMappingConfig;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+@Configuration
+@ConditionalOnClass(RequestMappingHandlerMapping.class)
+@Import(ShiroRequestMappingConfig.class)
+@ConditionalOnProperty(name = "shiro.web.enabled", matchIfMissing = true)
+public class ShiroWebMvcAutoConfiguration { }
diff --git a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories
index b69324a4f3..328062d5f2 100644
--- a/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories
+++ b/support/spring-boot/spring-boot-web-starter/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration = \
org.apache.shiro.spring.config.web.autoconfigure.ShiroWebAutoConfiguration,\
- org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration
+ org.apache.shiro.spring.config.web.autoconfigure.ShiroWebFilterConfiguration, \
+ org.apache.shiro.spring.config.web.autoconfigure.ShiroWebMvcAutoConfiguration
diff --git a/support/spring/pom.xml b/support/spring/pom.xml
index 943249efbc..40b3195912 100644
--- a/support/spring/pom.xml
+++ b/support/spring/pom.xml
@@ -50,6 +50,16 @@
spring-context
provided
+
+ org.springframework
+ spring-web
+ true
+
+
+ org.springframework
+ spring-webmvc
+ true
+
org.slf4j
@@ -71,11 +81,6 @@
spring-test
test
-
- org.springframework
- spring-web
- test
-
org.apache.shiro
shiro-aspectj
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroUrlPathHelper.java b/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroUrlPathHelper.java
new file mode 100644
index 0000000000..4b5ddbd59b
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/ShiroUrlPathHelper.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web;
+
+import org.apache.shiro.web.util.WebUtils;
+import org.springframework.web.util.UrlPathHelper;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * A Spring UrlPathHelper that uses Shiro's path resolution logic.
+ * @since 1.7.0
+ */
+public class ShiroUrlPathHelper extends UrlPathHelper {
+
+ @Override
+ public String getPathWithinApplication(HttpServletRequest request) {
+ return WebUtils.getPathWithinApplication(request);
+ }
+
+ @Override
+ public String getPathWithinServletMapping(HttpServletRequest request) {
+ return WebUtils.getPathWithinApplication(request);
+ }
+}
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
index ae2afb5f4c..5ed98d8b67 100644
--- a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebConfiguration.java
@@ -24,6 +24,7 @@
import org.apache.shiro.mgt.SubjectFactory;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.config.AbstractShiroConfiguration;
+import org.apache.shiro.spring.web.ShiroUrlPathHelper;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.mgt.DefaultWebSessionStorageEvaluator;
@@ -181,4 +182,8 @@ protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
chainDefinition.addPathDefinition("/**", "authc");
return chainDefinition;
}
+
+ protected ShiroUrlPathHelper shiroUrlPathHelper() {
+ return new ShiroUrlPathHelper();
+ }
}
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
index 11b961ede5..685d63dfbc 100644
--- a/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java
@@ -40,7 +40,7 @@ public class AbstractShiroWebFilterConfiguration {
@Autowired
protected ShiroFilterChainDefinition shiroFilterChainDefinition;
- @Autowired
+ @Autowired(required = false)
protected Map filterMap;
@Value("#{ @environment['shiro.loginUrl'] ?: '/login.jsp' }")
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroRequestMappingConfig.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroRequestMappingConfig.java
new file mode 100644
index 0000000000..317cb4de2a
--- /dev/null
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroRequestMappingConfig.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web.config;
+
+import org.apache.shiro.spring.web.ShiroUrlPathHelper;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+
+@Configuration
+public class ShiroRequestMappingConfig {
+
+ public ShiroRequestMappingConfig(RequestMappingHandlerMapping requestMappingHandlerMapping) {
+ requestMappingHandlerMapping.setUrlPathHelper(new ShiroUrlPathHelper());
+ }
+}
diff --git a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java
index dc57b224b4..952a26a12f 100644
--- a/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java
+++ b/support/spring/src/main/java/org/apache/shiro/spring/web/config/ShiroWebConfiguration.java
@@ -26,6 +26,7 @@
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.SessionDAO;
+import org.apache.shiro.spring.web.ShiroUrlPathHelper;
import org.apache.shiro.web.servlet.Cookie;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@@ -122,4 +123,10 @@ protected SessionsSecurityManager securityManager(List realms) {
protected ShiroFilterChainDefinition shiroFilterChainDefinition() {
return super.shiroFilterChainDefinition();
}
+
+ @Bean
+ @Override
+ protected ShiroUrlPathHelper shiroUrlPathHelper() {
+ return super.shiroUrlPathHelper();
+ }
}
diff --git a/support/spring/src/test/groovy/org/apache/shiro/spring/web/ShiroUrlPathHelperTest.groovy b/support/spring/src/test/groovy/org/apache/shiro/spring/web/ShiroUrlPathHelperTest.groovy
new file mode 100644
index 0000000000..08eeb79307
--- /dev/null
+++ b/support/spring/src/test/groovy/org/apache/shiro/spring/web/ShiroUrlPathHelperTest.groovy
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shiro.spring.web
+
+import org.junit.Test
+import org.springframework.mock.web.MockHttpServletRequest
+import org.springframework.web.util.UrlPathHelper
+
+import static org.hamcrest.MatcherAssert.assertThat
+import static org.hamcrest.Matchers.equalTo
+
+/**
+ * Tests a couple known differences between the stock and the ShiroUrlPathHelper
+ */
+class ShiroUrlPathHelperTest {
+
+ @Test
+ void testGetPathWithinApplication() {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/%2e%2e")
+ assertThat new UrlPathHelper().getPathWithinApplication(request), equalTo("/foo/..")
+ assertThat new ShiroUrlPathHelper().getPathWithinApplication(request), equalTo("/")
+ }
+
+ @Test
+ void testGetPathWithinServletMapping() {
+ MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo/%2e%2e")
+ assertThat new UrlPathHelper().getPathWithinServletMapping(request), equalTo("/foo/..")
+ assertThat new ShiroUrlPathHelper().getPathWithinServletMapping(request), equalTo("/")
+ }
+}
\ No newline at end of file