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