Skip to content

Commit 28e10e0

Browse files
committed
Allow for direct configuration of ShiroFilter through WebEnvironment
Adds new ShiroFilterConfiguration class exposed through the WebEnvironment This class allows for confiuration of the Shiro filter through various config mechanisms (Ini, Guice, Spring, etc) This makes it easer to enable a static security manager when using Shiro's Servlet fragment, as now a web.xml is not required
1 parent 43240d9 commit 28e10e0

File tree

23 files changed

+407
-45
lines changed

23 files changed

+407
-45
lines changed

pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@
419419
<onlyModified>true</onlyModified>
420420
<breakBuildOnBinaryIncompatibleModifications>true</breakBuildOnBinaryIncompatibleModifications>
421421
<breakBuildBasedOnSemanticVersioning>true</breakBuildBasedOnSemanticVersioning>
422+
<postAnalysisScript>${root.dir}/src/japicmp/postAnalysisScript.groovy</postAnalysisScript>
422423
</parameter>
423424
</configuration>
424425
</plugin>

samples/servlet-plugin/pom.xml

+2-7
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,8 @@
106106
<scope>runtime</scope>
107107
</dependency>
108108
<dependency>
109-
<groupId>org.apache.logging.log4j</groupId>
110-
<artifactId>log4j-slf4j-impl</artifactId>
111-
<scope>runtime</scope>
112-
</dependency>
113-
<dependency>
114-
<groupId>org.apache.logging.log4j</groupId>
115-
<artifactId>log4j-core</artifactId>
109+
<groupId>org.slf4j</groupId>
110+
<artifactId>slf4j-simple</artifactId>
116111
<scope>runtime</scope>
117112
</dependency>
118113
<dependency>

src/japicmp/postAnalysisScript.groovy

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
import static japicmp.model.JApiCompatibilityChange.*
21+
import static japicmp.model.JApiChangeStatus.*
22+
23+
def it = jApiClasses.iterator()
24+
while (it.hasNext()) {
25+
def jApiClass = it.next()
26+
// filter out interfaces changes that are default methods
27+
if (jApiClass.getChangeStatus() != UNCHANGED) {
28+
def methodIt = jApiClass.getMethods().iterator()
29+
while (methodIt.hasNext()) {
30+
def method = methodIt.next()
31+
def methodChanges = method.getCompatibilityChanges()
32+
methodChanges.remove(METHOD_NEW_DEFAULT)
33+
}
34+
}
35+
}
36+
return jApiClasses

support/guice/src/main/java/org/apache/shiro/guice/web/GuiceShiroFilter.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.shiro.guice.web;
2020

21+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
2122
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
2223
import org.apache.shiro.web.mgt.WebSecurityManager;
2324
import org.apache.shiro.web.servlet.AbstractShiroFilter;
@@ -31,8 +32,9 @@
3132
*/
3233
public class GuiceShiroFilter extends AbstractShiroFilter {
3334
@Inject
34-
GuiceShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver filterChainResolver) {
35+
GuiceShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver filterChainResolver, ShiroFilterConfiguration filterConfiguration) {
3536
this.setSecurityManager(webSecurityManager);
3637
this.setFilterChainResolver(filterChainResolver);
38+
this.setShiroFilterConfiguration(filterConfiguration);
3739
}
3840
}

support/guice/src/main/java/org/apache/shiro/guice/web/WebGuiceEnvironment.java

+9-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.inject.Inject;
2222
import com.google.inject.Singleton;
2323
import org.apache.shiro.mgt.SecurityManager;
24+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
2425
import org.apache.shiro.web.env.EnvironmentLoaderListener;
2526
import org.apache.shiro.web.env.WebEnvironment;
2627
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
@@ -35,11 +36,14 @@ class WebGuiceEnvironment implements WebEnvironment {
3536
private ServletContext servletContext;
3637
private WebSecurityManager securityManager;
3738

39+
private ShiroFilterConfiguration filterConfiguration;
40+
3841
@Inject
39-
WebGuiceEnvironment(FilterChainResolver filterChainResolver, @Named(ShiroWebModule.NAME) ServletContext servletContext, WebSecurityManager securityManager) {
42+
WebGuiceEnvironment(FilterChainResolver filterChainResolver, @Named(ShiroWebModule.NAME) ServletContext servletContext, WebSecurityManager securityManager, ShiroFilterConfiguration filterConfiguration) {
4043
this.filterChainResolver = filterChainResolver;
4144
this.servletContext = servletContext;
4245
this.securityManager = securityManager;
46+
this.filterConfiguration = filterConfiguration;
4347

4448
servletContext.setAttribute(EnvironmentLoaderListener.ENVIRONMENT_ATTRIBUTE_KEY, this);
4549
}
@@ -59,4 +63,8 @@ public WebSecurityManager getWebSecurityManager() {
5963
public SecurityManager getSecurityManager() {
6064
return securityManager;
6165
}
66+
67+
public ShiroFilterConfiguration getShiroFilterConfiguration() {
68+
return filterConfiguration;
69+
}
6270
}

support/guice/src/test/java/org/apache/shiro/guice/web/GuiceShiroFilterTest.java

+11-4
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,13 @@
1919
package org.apache.shiro.guice.web;
2020

2121
import com.google.inject.spi.InjectionPoint;
22+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
2223
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
2324
import org.apache.shiro.web.mgt.WebSecurityManager;
2425
import org.junit.Test;
2526

26-
import static org.easymock.EasyMock.createMock;
27-
import static org.junit.Assert.assertSame;
28-
import static org.junit.Assert.fail;
27+
import static org.easymock.EasyMock.*;
28+
import static org.junit.Assert.*;
2929

3030
public class GuiceShiroFilterTest {
3131

@@ -42,10 +42,17 @@ public void ensureInjectable() {
4242
public void testConstructor() {
4343
WebSecurityManager securityManager = createMock(WebSecurityManager.class);
4444
FilterChainResolver filterChainResolver = createMock(FilterChainResolver.class);
45+
ShiroFilterConfiguration filterConfiguration = createMock(ShiroFilterConfiguration.class);
46+
expect(filterConfiguration.isStaticSecurityManagerEnabled()).andReturn(true);
47+
expect(filterConfiguration.isFilterOncePerRequest()).andReturn(false);
4548

46-
GuiceShiroFilter underTest = new GuiceShiroFilter(securityManager, filterChainResolver);
49+
replay(securityManager, filterChainResolver, filterConfiguration);
50+
51+
GuiceShiroFilter underTest = new GuiceShiroFilter(securityManager, filterChainResolver, filterConfiguration);
4752

4853
assertSame(securityManager, underTest.getSecurityManager());
4954
assertSame(filterChainResolver, underTest.getFilterChainResolver());
55+
assertTrue(underTest.isStaticSecurityManagerEnabled());
56+
assertFalse(underTest.isFilterOncePerRequest());
5057
}
5158
}

support/guice/src/test/java/org/apache/shiro/guice/web/ShiroWebModuleTest.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.shiro.mgt.SecurityManager;
3131
import org.apache.shiro.realm.Realm;
3232
import org.apache.shiro.session.mgt.SessionManager;
33+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
3334
import org.apache.shiro.web.env.EnvironmentLoader;
3435
import org.apache.shiro.web.env.WebEnvironment;
3536
import org.apache.shiro.web.filter.InvalidRequestFilter;
@@ -487,8 +488,8 @@ public static class MyDefaultWebSessionManager extends DefaultWebSessionManager
487488

488489
public static class MyWebEnvironment extends WebGuiceEnvironment {
489490
@Inject
490-
MyWebEnvironment(FilterChainResolver filterChainResolver, @Named(ShiroWebModule.NAME) ServletContext servletContext, WebSecurityManager securityManager) {
491-
super(filterChainResolver, servletContext, securityManager);
491+
MyWebEnvironment(FilterChainResolver filterChainResolver, @Named(ShiroWebModule.NAME) ServletContext servletContext, WebSecurityManager securityManager, ShiroFilterConfiguration filterConfiguration) {
492+
super(filterChainResolver, servletContext, securityManager, filterConfiguration);
492493
}
493494
}
494495

support/guice/src/test/java/org/apache/shiro/guice/web/WebGuiceEnvironmentTest.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
package org.apache.shiro.guice.web;
2020

2121
import com.google.inject.spi.InjectionPoint;
22+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
2223
import org.apache.shiro.web.env.EnvironmentLoaderListener;
2324
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
2425
import org.apache.shiro.web.mgt.WebSecurityManager;
@@ -47,13 +48,14 @@ public void testConstructor() {
4748
WebSecurityManager securityManager = createMock(WebSecurityManager.class);
4849
FilterChainResolver filterChainResolver = createMock(FilterChainResolver.class);
4950
ServletContext servletContext = createMock(ServletContext.class);
51+
ShiroFilterConfiguration filterConfiguration = createMock(ShiroFilterConfiguration.class);
5052

5153
Capture<WebGuiceEnvironment> capture = Capture.newInstance();
5254
servletContext.setAttribute(eq(EnvironmentLoaderListener.ENVIRONMENT_ATTRIBUTE_KEY), and(anyObject(WebGuiceEnvironment.class), capture(capture)));
5355

5456
replay(servletContext, securityManager, filterChainResolver);
5557

56-
WebGuiceEnvironment underTest = new WebGuiceEnvironment(filterChainResolver, servletContext, securityManager);
58+
WebGuiceEnvironment underTest = new WebGuiceEnvironment(filterChainResolver, servletContext, securityManager, filterConfiguration);
5759

5860
assertSame(securityManager, underTest.getSecurityManager());
5961
assertSame(filterChainResolver, underTest.getFilterChainResolver());

support/spring/src/main/java/org/apache/shiro/spring/web/ShiroFilterFactoryBean.java

+31-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.shiro.util.Nameable;
2525
import org.apache.shiro.util.StringUtils;
2626
import org.apache.shiro.web.config.IniFilterChainResolverFactory;
27+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
2728
import org.apache.shiro.web.filter.AccessControlFilter;
2829
import org.apache.shiro.web.filter.InvalidRequestFilter;
2930
import org.apache.shiro.web.filter.authc.AuthenticationFilter;
@@ -35,6 +36,7 @@
3536
import org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver;
3637
import org.apache.shiro.web.mgt.WebSecurityManager;
3738
import org.apache.shiro.web.servlet.AbstractShiroFilter;
39+
import org.apache.shiro.web.servlet.OncePerRequestFilter;
3840
import org.slf4j.Logger;
3941
import org.slf4j.LoggerFactory;
4042
import org.springframework.beans.BeansException;
@@ -135,15 +137,18 @@ public class ShiroFilterFactoryBean implements FactoryBean<AbstractShiroFilter>,
135137

136138
private AbstractShiroFilter instance;
137139

140+
private ShiroFilterConfiguration filterConfiguration;
141+
138142
public ShiroFilterFactoryBean() {
139143
this.filters = new LinkedHashMap<String, Filter>();
140144
this.globalFilters = new ArrayList<>();
141145
this.globalFilters.add(DefaultFilter.invalidRequest.name());
142146
this.filterChainDefinitionMap = new LinkedHashMap<String, String>(); //order matters!
147+
this.filterConfiguration = new ShiroFilterConfiguration();
143148
}
144149

145150
/**
146-
* Sets the application {@code SecurityManager} instance to be used by the constructed Shiro Filter. This is a
151+
* Gets the application {@code SecurityManager} instance to be used by the constructed Shiro Filter. This is a
147152
* required property - failure to set it will throw an initialization exception.
148153
*
149154
* @return the application {@code SecurityManager} instance to be used by the constructed Shiro Filter.
@@ -162,6 +167,24 @@ public void setSecurityManager(SecurityManager securityManager) {
162167
this.securityManager = securityManager;
163168
}
164169

170+
/**
171+
* Gets the application {@code ShiroFilterConfiguration} instance to be used by the constructed Shiro Filter.
172+
*
173+
* @return the application {@code ShiroFilterConfiguration} instance to be used by the constructed Shiro Filter.
174+
*/
175+
public ShiroFilterConfiguration getShiroFilterConfiguration() {
176+
return filterConfiguration;
177+
}
178+
179+
/**
180+
* Sets the application {@code ShiroFilterConfiguration} instance to be used by the constructed Shiro Filter.
181+
*
182+
* @param filterConfiguration the application {@code SecurityManager} instance to be used by the constructed Shiro Filter.
183+
*/
184+
public void setShiroFilterConfiguration(ShiroFilterConfiguration filterConfiguration) {
185+
this.filterConfiguration = filterConfiguration;
186+
}
187+
165188
/**
166189
* Returns the application's login URL to be assigned to all acquired Filters that subclass
167190
* {@link AccessControlFilter} or {@code null} if no value should be assigned globally. The default value
@@ -468,7 +491,7 @@ protected AbstractShiroFilter createInstance() throws Exception {
468491
//FilterChainResolver. It doesn't matter that the instance is an anonymous inner class
469492
//here - we're just using it because it is a concrete AbstractShiroFilter instance that accepts
470493
//injection of the SecurityManager and FilterChainResolver:
471-
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver);
494+
return new SpringShiroFilter((WebSecurityManager) securityManager, chainResolver, getShiroFilterConfiguration());
472495
}
473496

474497
private void applyLoginUrlIfNecessary(Filter filter) {
@@ -511,6 +534,10 @@ private void applyGlobalPropertiesIfNecessary(Filter filter) {
511534
applyLoginUrlIfNecessary(filter);
512535
applySuccessUrlIfNecessary(filter);
513536
applyUnauthorizedUrlIfNecessary(filter);
537+
538+
if (filter instanceof OncePerRequestFilter) {
539+
((OncePerRequestFilter) filter).setFilterOncePerRequest(filterConfiguration.isFilterOncePerRequest());
540+
}
514541
}
515542

516543
/**
@@ -549,12 +576,13 @@ public Object postProcessAfterInitialization(Object bean, String beanName) throw
549576
*/
550577
private static final class SpringShiroFilter extends AbstractShiroFilter {
551578

552-
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver) {
579+
protected SpringShiroFilter(WebSecurityManager webSecurityManager, FilterChainResolver resolver, ShiroFilterConfiguration filterConfiguration) {
553580
super();
554581
if (webSecurityManager == null) {
555582
throw new IllegalArgumentException("WebSecurityManager property cannot be null.");
556583
}
557584
setSecurityManager(webSecurityManager);
585+
setShiroFilterConfiguration(filterConfiguration);
558586

559587
if (resolver != null) {
560588
setFilterChainResolver(resolver);

support/spring/src/main/java/org/apache/shiro/spring/web/config/AbstractShiroWebFilterConfiguration.java

+11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import org.apache.shiro.mgt.SecurityManager;
2222
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
23+
import org.apache.shiro.web.config.ShiroFilterConfiguration;
2324
import org.apache.shiro.web.filter.mgt.DefaultFilter;
2425
import org.springframework.beans.factory.annotation.Autowired;
2526
import org.springframework.beans.factory.annotation.Value;
@@ -40,6 +41,9 @@ public class AbstractShiroWebFilterConfiguration {
4041
@Autowired
4142
protected ShiroFilterChainDefinition shiroFilterChainDefinition;
4243

44+
@Autowired(required = false)
45+
protected ShiroFilterConfiguration shiroFilterConfiguration;
46+
4347
@Autowired(required = false)
4448
protected Map<String, Filter> filterMap;
4549

@@ -56,6 +60,12 @@ protected List<String> globalFilters() {
5660
return Collections.singletonList(DefaultFilter.invalidRequest.name());
5761
}
5862

63+
protected ShiroFilterConfiguration shiroFilterConfiguration() {
64+
return shiroFilterConfiguration != null
65+
? shiroFilterConfiguration
66+
: new ShiroFilterConfiguration();
67+
}
68+
5969
protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
6070
ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();
6171

@@ -64,6 +74,7 @@ protected ShiroFilterFactoryBean shiroFilterFactoryBean() {
6474
filterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);
6575

6676
filterFactoryBean.setSecurityManager(securityManager);
77+
filterFactoryBean.setShiroFilterConfiguration(shiroFilterConfiguration());
6778
filterFactoryBean.setGlobalFilters(globalFilters());
6879
filterFactoryBean.setFilterChainDefinitionMap(shiroFilterChainDefinition.getFilterChainMap());
6980
filterFactoryBean.setFilters(filterMap);

0 commit comments

Comments
 (0)