blob: 8733588400ce74e0e7e44e79e14a2dcd6e3dd377 [file] [log] [blame]
/*
* 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.web.filter.mgt
import org.apache.shiro.config.ConfigurationException
import org.apache.shiro.web.filter.authz.SslFilter
import org.apache.shiro.web.servlet.ShiroFilter
import org.hamcrest.Matchers
import javax.servlet.Filter
import javax.servlet.FilterChain
import javax.servlet.FilterConfig
import javax.servlet.ServletContext
import org.junit.Before
import org.junit.Test
import static org.easymock.EasyMock.*
import static org.junit.Assert.*
import static org.hamcrest.MatcherAssert.assertThat
/**
* Unit tests for the {@link DefaultFilterChainManager} implementation.
*/
class DefaultFilterChainManagerTest {
DefaultFilterChainManager manager;
@Before
void setUp() {
this.manager = new DefaultFilterChainManager();
}
//SHIRO-205
@Test
void testToNameConfigPairNoBrackets() {
def token = "foo"
String[] pair = manager.toNameConfigPair(token);
assertNotNull pair
assertEquals 2, pair.length
assertEquals "foo", pair[0]
assertNull pair[1]
}
//SHIRO-205
@Test
void testToNameConfigPairWithEmptyBrackets() {
def token = "foo[]"
String[] pair = manager.toNameConfigPair(token);
assertNotNull pair
assertEquals 2, pair.length
assertEquals "foo", pair[0]
assertNull pair[1]
}
//SHIRO-205
@Test
void testToNameConfigPairWithPopulatedBrackets() {
def token = "foo[bar, baz]"
String[] pair = manager.toNameConfigPair(token);
assertNotNull pair
assertEquals 2, pair.length
assertEquals "foo", pair[0]
assertEquals "bar, baz", pair[1]
}
//SHIRO-205 - asserts backwards compatibility before SHIRO-205 was implemented:
@Test
void testToNameConfigPairWithNestedQuotesInBrackets() {
def token = 'roles["guest, admin"]'
String[] pair = manager.toNameConfigPair(token);
assertNotNull pair
assertEquals 2, pair.length
assertEquals "roles", pair[0]
assertEquals "guest, admin", pair[1]
}
//SHIRO-205 - asserts backwards compatibility before SHIRO-205 was implemented:
//@since 1.2.2
@Test
void testToNameConfigPairWithIndividualNestedQuotesInBrackets() {
def token = 'roles["guest", "admin"]'
String[] pair = manager.toNameConfigPair(token);
assertNotNull pair
assertEquals 2, pair.length
assertEquals "roles", pair[0]
assertEquals '"guest", "admin"', pair[1]
}
//SHIRO-205
@Test
void testFilterChainConfigWithNestedCommas() {
def chain = "a, b[c], d[e, f], g[h, i, j], k"
String[] tokens = manager.splitChainDefinition(chain);
assertNotNull tokens
assertEquals 5, tokens.length
assertEquals "a", tokens[0]
assertEquals "b[c]", tokens[1]
assertEquals "d[e, f]", tokens[2]
assertEquals "g[h, i, j]", tokens[3]
assertEquals "k", tokens[4]
}
//SHIRO-205
@Test
void testFilterChainConfigWithNestedQuotedCommas() {
def chain = "a, b[c], d[e, f], g[h, i, j], k"
String[] tokens = manager.splitChainDefinition(chain);
assertNotNull tokens
assertEquals 5, tokens.length
assertEquals "a", tokens[0]
assertEquals "b[c]", tokens[1]
assertEquals "d[e, f]", tokens[2]
assertEquals "g[h, i, j]", tokens[3]
assertEquals "k", tokens[4]
}
@Test
void testNewInstanceDefaultFilters() {
for (DefaultFilter defaultFilter : DefaultFilter.values()) {
assertNotNull(manager.getFilter(defaultFilter.name()));
}
assertFalse(manager.hasChains());
}
protected FilterConfig createNiceMockFilterConfig() {
FilterConfig mock = createNiceMock(FilterConfig.class);
ServletContext mockServletContext = createNiceMock(ServletContext.class);
expect(mock.getServletContext()).andReturn(mockServletContext);
return mock;
}
@Test
void testNewInstanceWithFilterConfig() {
FilterConfig mock = createNiceMockFilterConfig();
replay(mock);
this.manager = new DefaultFilterChainManager(mock);
for (DefaultFilter defaultFilter : DefaultFilter.values()) {
assertNotNull(manager.getFilter(defaultFilter.name()));
}
assertFalse(manager.hasChains());
verify(mock);
}
@Test
void testCreateChain() {
try {
manager.createChain(null, null);
} catch (NullPointerException expected) {
}
try {
manager.createChain("test", null);
} catch (NullPointerException expected) {
}
manager.createChain("test", "authc, roles[manager], perms[\"user:read,write:12345\"");
assertTrue(manager.hasChains());
Set<String> chainNames = manager.getChainNames();
assertNotNull(chainNames);
assertEquals(1, chainNames.size());
assertTrue(chainNames.contains("test"));
Map<String, NamedFilterList> chains = manager.getFilterChains();
assertEquals(1, chains.size());
assertTrue(chains.containsKey("test"));
manager.setFilterChains(chains);
NamedFilterList chain = manager.getChain("test");
assertNotNull(chain);
Filter filter = chain.get(0);
assertNotNull(filter);
assertEquals(DefaultFilter.authc.getFilterClass(), filter.getClass());
filter = chain.get(1);
assertNotNull(filter);
assertEquals(DefaultFilter.roles.getFilterClass(), filter.getClass());
filter = chain.get(2);
assertNotNull(filter);
assertEquals(DefaultFilter.perms.getFilterClass(), filter.getClass());
}
@Test
void testWithGlobalFilters() {
DefaultFilterChainManager manager = new DefaultFilterChainManager()
manager.setGlobalFilters(["invalidRequest", "port"])
assertThat(manager.filterChains, Matchers.anEmptyMap())
// add a chain
manager.createChain("test", "authc, roles[manager], perms[\"user:read,write:12345\"")
assertThat(manager.getChain("test"), Matchers.contains(
Matchers.instanceOf(DefaultFilter.invalidRequest.getFilterClass()),
Matchers.instanceOf(DefaultFilter.port.getFilterClass()),
Matchers.instanceOf(DefaultFilter.authc.getFilterClass()),
Matchers.instanceOf(DefaultFilter.roles.getFilterClass()),
Matchers.instanceOf(DefaultFilter.perms.getFilterClass())
))
// the "default" chain doesn't exist until it is created
assertThat(manager.getChain("/**"), Matchers.nullValue())
// create it
manager.createDefaultChain("/**")
// verify it
assertThat(manager.getChain("/**"), Matchers.contains(
Matchers.instanceOf(DefaultFilter.invalidRequest.getFilterClass()),
Matchers.instanceOf(DefaultFilter.port.getFilterClass())
))
}
@Test
void addDefaultChainWithSameName() {
DefaultFilterChainManager manager = new DefaultFilterChainManager()
manager.setGlobalFilters(["invalidRequest", "port"])
// create a chain
manager.createChain("test", "authc")
// create the default chain with the same name
manager.createDefaultChain("test")
// since the "default" chain was created with the same name as an existing chain, we could end up adding the
// global filters to the chain twice, test to verify it is only once
assertThat(manager.getChain("test"), Matchers.contains(
Matchers.instanceOf(DefaultFilter.invalidRequest.getFilterClass()),
Matchers.instanceOf(DefaultFilter.port.getFilterClass()),
Matchers.instanceOf(DefaultFilter.authc.getFilterClass())
))
}
/**
* Helps assert <a href="https://issues.apache.org/jira/browse/SHIRO-429">SHIRO-429</a>
* @since 1.2.2
*/
@Test
void testCreateChainWithQuotedInstanceConfig() {
manager.createChain("test", 'authc, perms["perm1", "perm2"]');
assertTrue(manager.hasChains());
Set<String> chainNames = manager.getChainNames();
assertNotNull(chainNames);
assertEquals(1, chainNames.size());
assertTrue(chainNames.contains("test"));
Map<String, NamedFilterList> chains = manager.getFilterChains();
assertEquals(1, chains.size());
assertTrue(chains.containsKey("test"));
manager.setFilterChains(chains);
NamedFilterList chain = manager.getChain("test");
assertNotNull(chain);
Filter filter = chain.get(0);
assertNotNull(filter);
assertEquals(DefaultFilter.authc.getFilterClass(), filter.getClass());
filter = chain.get(1);
assertNotNull(filter);
assertEquals(DefaultFilter.perms.getFilterClass(), filter.getClass());
}
@Test
void testBeanMethods() {
Map<String, Filter> filters = manager.getFilters();
assertEquals(filters.size(), DefaultFilter.values().length);
manager.setFilters(filters);
}
@Test
void testAddFilter() {
FilterConfig mockFilterConfig = createNiceMockFilterConfig();
replay(mockFilterConfig);
this.manager = new DefaultFilterChainManager(mockFilterConfig);
manager.addFilter("test", new SslFilter());
Filter filter = manager.getFilter("test");
assertNotNull(filter);
assertEquals(SslFilter.class, filter.getClass());
verify(mockFilterConfig);
}
@Test
void testAddFilterNoInit() {
FilterConfig mockFilterConfig = createNiceMockFilterConfig();
Filter mockFilter = createNiceMock(Filter.class);
replay mockFilterConfig, mockFilter
this.manager = new DefaultFilterChainManager(mockFilterConfig);
this.manager.addFilter("blah", mockFilter);
assertNotNull this.manager.filters['blah']
assertSame this.manager.filters['blah'], mockFilter
verify mockFilterConfig, mockFilter
}
@Test
void testAddFilterNoFilterConfig() {
SslFilter filter = new SslFilter();
manager.addFilter("test", filter);
assertNotNull manager.filters['test']
assertSame manager.filters['test'], filter
}
@Test
void testAddToChain() {
FilterConfig mockFilterConfig = createNiceMockFilterConfig();
replay(mockFilterConfig);
this.manager = new DefaultFilterChainManager(mockFilterConfig);
manager.addFilter("testSsl", new SslFilter());
manager.createChain("test", "anon");
try {
manager.addToChain("test", null);
fail "Should have thrown an IllegalArgumentException"
} catch (IllegalArgumentException expected) {
}
try {
manager.addToChain(null, "testSsl");
fail "Should have thrown an IllegalArgumentException"
} catch (IllegalArgumentException expected) {
}
}
@Test
void testAddToChainNotPathProcessor() {
FilterConfig mockFilterConfig = createNiceMockFilterConfig();
replay(mockFilterConfig);
this.manager = new DefaultFilterChainManager(mockFilterConfig);
manager.addFilter("nonPathProcessor", new ShiroFilter());
manager.createChain("test", "nonPathProcessor");
try {
manager.addToChain("test", "nonPathProcessor", "dummyConfig");
fail "Should have thrown a ConfigurationException"
} catch (ConfigurationException expected) {
}
}
@Test
void testProxy() {
FilterChain mock = createNiceMock(FilterChain.class);
replay(mock);
manager.createChain("test", "anon");
this.manager.proxy(mock, "test");
verify(mock);
}
@Test
void testProxyNoChain() {
FilterChain mock = createNiceMock(FilterChain.class);
replay(mock);
try {
this.manager.proxy(mock, "blah");
fail "Should have thrown an IllegalArgumentException"
} catch (IllegalArgumentException expected) {
}
verify(mock);
}
}