View Javadoc
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  package org.apache.shiro.guice.web;
20  
21  import com.google.inject.Guice;
22  import com.google.inject.Inject;
23  import com.google.inject.Injector;
24  import com.google.inject.Key;
25  import com.google.inject.Provides;
26  import com.google.inject.binder.AnnotatedBindingBuilder;
27  import org.apache.shiro.guice.ShiroModuleTest;
28  import org.apache.shiro.env.Environment;
29  import org.apache.shiro.mgt.SecurityManager;
30  import org.apache.shiro.realm.Realm;
31  import org.apache.shiro.session.mgt.SessionManager;
32  import org.apache.shiro.web.env.EnvironmentLoader;
33  import org.apache.shiro.web.env.WebEnvironment;
34  import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
35  import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
36  import org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter;
37  import org.apache.shiro.web.filter.authz.RolesAuthorizationFilter;
38  import org.apache.shiro.web.filter.mgt.FilterChainResolver;
39  import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
40  import org.apache.shiro.web.mgt.WebSecurityManager;
41  import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
42  import org.apache.shiro.web.session.mgt.ServletContainerSessionManager;
43  import org.easymock.EasyMock;
44  import org.junit.Assume;
45  import org.junit.Test;
46  
47  import javax.inject.Named;
48  import javax.servlet.Filter;
49  import javax.servlet.FilterChain;
50  import javax.servlet.FilterConfig;
51  import javax.servlet.ServletContext;
52  import javax.servlet.ServletException;
53  import javax.servlet.ServletRequest;
54  import javax.servlet.ServletResponse;
55  import javax.servlet.http.HttpServletRequest;
56  import java.io.IOException;
57  import java.util.Collection;
58  import java.util.Iterator;
59  
60  import static org.easymock.EasyMock.*;
61  import static org.junit.Assert.*;
62  import static org.hamcrest.Matchers.*;
63  
64  
65  public class ShiroWebModuleTest {
66  
67  
68      @Test
69      public void basicInstantiation() {
70          final ShiroModuleTest.MockRealm mockRealm = createMock(ShiroModuleTest.MockRealm.class);
71          ServletContext servletContext = createMock(ServletContext.class);
72  
73          Injector injector = Guice.createInjector(new ShiroWebModule(servletContext) {
74              @Override
75              protected void configureShiroWeb() {
76                  bindRealm().to(ShiroModuleTest.MockRealm.class);
77                  expose(SessionManager.class);
78              }
79  
80              @Provides
81              public ShiroModuleTest.MockRealm createRealm() {
82                  return mockRealm;
83              }
84  
85          });
86          // we're not getting a WebSecurityManager here b/c it's not exposed.  There didn't seem to be a good reason to
87          // expose it outside of the Shiro module.
88          SecurityManager securityManager = injector.getInstance(SecurityManager.class);
89          assertNotNull(securityManager);
90          assertTrue(securityManager instanceof WebSecurityManager);
91          SessionManager sessionManager = injector.getInstance(SessionManager.class);
92          assertNotNull(sessionManager);
93          assertTrue(sessionManager instanceof ServletContainerSessionManager);
94          assertTrue(((DefaultWebSecurityManager)securityManager).getSessionManager() instanceof ServletContainerSessionManager);
95      }
96  
97      @Test
98      public void testBindGuiceFilter() throws Exception {
99  
100     }
101 
102     @Test
103     public void testBindWebSecurityManager() throws Exception {
104         final ShiroModuleTest.MockRealm mockRealm = createMock(ShiroModuleTest.MockRealm.class);
105         ServletContext servletContext = createMock(ServletContext.class);
106 
107         Injector injector = Guice.createInjector(new ShiroWebModule(servletContext) {
108             @Override
109             protected void configureShiroWeb() {
110                 bindRealm().to(ShiroModuleTest.MockRealm.class);
111                 expose(WebSecurityManager.class);
112             }
113 
114             @Provides
115             public ShiroModuleTest.MockRealm createRealm() {
116                 return mockRealm;
117             }
118 
119             @Override
120             protected void bindWebSecurityManager(AnnotatedBindingBuilder<? super WebSecurityManager> bind) {
121                 bind.to(MyDefaultWebSecurityManager.class).asEagerSingleton();
122             }
123         });
124         SecurityManager securityManager = injector.getInstance(SecurityManager.class);
125         assertNotNull(securityManager);
126         assertTrue(securityManager instanceof MyDefaultWebSecurityManager);
127         WebSecurityManager webSecurityManager = injector.getInstance(WebSecurityManager.class);
128         assertNotNull(webSecurityManager);
129         assertTrue(webSecurityManager instanceof MyDefaultWebSecurityManager);
130         // SHIRO-435: Check both keys SecurityManager and WebSecurityManager are bound to the same instance
131         assertTrue( securityManager == webSecurityManager );
132     }
133 
134     @Test
135     public void testBindWebEnvironment() throws Exception {
136         final ShiroModuleTest.MockRealm mockRealm = createMock(ShiroModuleTest.MockRealm.class);
137         ServletContext servletContext = createMock(ServletContext.class);
138 
139         Injector injector = Guice.createInjector(new ShiroWebModule(servletContext) {
140             @Override
141             protected void configureShiroWeb() {
142                 bindRealm().to(ShiroModuleTest.MockRealm.class);
143                 expose(WebEnvironment.class);
144                 expose(Environment.class);
145             }
146 
147             @Provides
148             public ShiroModuleTest.MockRealm createRealm() {
149                 return mockRealm;
150             }
151 
152             @Override
153             protected void bindWebEnvironment(AnnotatedBindingBuilder<? super WebEnvironment> bind) {
154                 bind.to(MyWebEnvironment.class).asEagerSingleton();
155             }
156         });
157         Environment environment = injector.getInstance(Environment.class);
158         assertNotNull(environment);
159         assertTrue(environment instanceof MyWebEnvironment);
160         WebEnvironment webEnvironment = injector.getInstance(WebEnvironment.class);
161         assertNotNull(webEnvironment);
162         assertTrue(webEnvironment instanceof MyWebEnvironment);
163         // SHIRO-435: Check both keys Environment and WebEnvironment are bound to the same instance
164         assertTrue( environment == webEnvironment );
165     }
166 
167     /**
168      * @since 1.4
169      */
170     @Test
171     public void testAddFilterChainGuice3and4() {
172 
173         final ShiroModuleTest.MockRealm mockRealm = createMock(ShiroModuleTest.MockRealm.class);
174         ServletContext servletContext = createMock(ServletContext.class);
175         HttpServletRequest request = createMock(HttpServletRequest.class);
176 
177         servletContext.setAttribute(eq(EnvironmentLoader.ENVIRONMENT_ATTRIBUTE_KEY), EasyMock.anyObject());
178         expect(request.getAttribute("javax.servlet.include.context_path")).andReturn("").anyTimes();
179         expect(request.getCharacterEncoding()).andReturn("UTF-8").anyTimes();
180         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_authc");
181         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_custom_filter");
182         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_authc_basic");
183         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_perms");
184         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/multiple_configs");
185         replay(servletContext, request);
186 
187         Injector injector = Guice.createInjector(new ShiroWebModule(servletContext) {
188             @Override
189             protected void configureShiroWeb() {
190                 bindRealm().to(ShiroModuleTest.MockRealm.class);
191                 expose(FilterChainResolver.class);
192                 this.addFilterChain("/test_authc/**", filterConfig(AUTHC));
193                 this.addFilterChain("/test_custom_filter/**", Key.get(CustomFilter.class));
194                 this.addFilterChain("/test_authc_basic/**", AUTHC_BASIC);
195                 this.addFilterChain("/test_perms/**", filterConfig(PERMS, "remote:invoke:lan,wan"));
196                 this.addFilterChain("/multiple_configs/**", filterConfig(AUTHC), filterConfig(ROLES, "b2bClient"), filterConfig(PERMS, "remote:invoke:lan,wan"));
197             }
198 
199             @Provides
200             public ShiroModuleTest.MockRealm createRealm() {
201                 return mockRealm;
202             }
203         });
204 
205         FilterChainResolver resolver = injector.getInstance(FilterChainResolver.class);
206         assertThat(resolver, instanceOf(SimpleFilterChainResolver.class));
207         SimpleFilterChainResolver simpleFilterChainResolver = (SimpleFilterChainResolver) resolver;
208 
209         // test the /test_authc resource
210         FilterChain filterChain = simpleFilterChainResolver.getChain(request, null, null);
211         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
212         Filter nextFilter = getNextFilter((SimpleFilterChain) filterChain);
213         assertThat(nextFilter, instanceOf(FormAuthenticationFilter.class));
214 
215         // test the /test_custom_filter resource
216         filterChain = simpleFilterChainResolver.getChain(request, null, null);
217         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
218         nextFilter = getNextFilter((SimpleFilterChain) filterChain);
219         assertThat(nextFilter, instanceOf(CustomFilter.class));
220 
221         // test the /test_authc_basic resource
222         filterChain = simpleFilterChainResolver.getChain(request, null, null);
223         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
224         nextFilter = getNextFilter((SimpleFilterChain) filterChain);
225         assertThat(nextFilter, instanceOf(BasicHttpAuthenticationFilter.class));
226 
227         // test the /test_perms resource
228         filterChain = simpleFilterChainResolver.getChain(request, null, null);
229         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
230         nextFilter = getNextFilter((SimpleFilterChain) filterChain);
231         assertThat(nextFilter, instanceOf(PermissionsAuthorizationFilter.class));
232 
233         // test the /multiple_configs resource
234         filterChain = simpleFilterChainResolver.getChain(request, null, null);
235         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
236         assertThat(getNextFilter((SimpleFilterChain) filterChain), instanceOf(FormAuthenticationFilter.class));
237         assertThat(getNextFilter((SimpleFilterChain) filterChain), instanceOf(RolesAuthorizationFilter.class));
238         assertThat(getNextFilter((SimpleFilterChain) filterChain), instanceOf(PermissionsAuthorizationFilter.class));
239 
240         verify(servletContext, request);
241     }
242 
243     /**
244      * @since 1.4
245      */
246     @Test
247     public void testAddFilterChainGuice3Only() {
248 
249         Assume.assumeTrue("This test only runs agains Guice 3.x", ShiroWebModule.isGuiceVersion3());
250 
251         final ShiroModuleTest.MockRealm mockRealm = createMock(ShiroModuleTest.MockRealm.class);
252         ServletContext servletContext = createMock(ServletContext.class);
253         HttpServletRequest request = createMock(HttpServletRequest.class);
254 
255         servletContext.setAttribute(eq(EnvironmentLoader.ENVIRONMENT_ATTRIBUTE_KEY), EasyMock.anyObject());
256         expect(request.getAttribute("javax.servlet.include.context_path")).andReturn("").anyTimes();
257         expect(request.getCharacterEncoding()).andReturn("UTF-8").anyTimes();
258         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_authc");
259         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_custom_filter");
260         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/test_perms");
261         expect(request.getAttribute("javax.servlet.include.request_uri")).andReturn("/multiple_configs");
262         replay(servletContext, request);
263 
264         Injector injector = Guice.createInjector(new ShiroWebModule(servletContext) {
265             @Override
266             protected void configureShiroWeb() {
267                 bindRealm().to(ShiroModuleTest.MockRealm.class);
268                 expose(FilterChainResolver.class);
269                 this.addFilterChain("/test_authc/**", AUTHC);
270                 this.addFilterChain("/test_custom_filter/**", Key.get(CustomFilter.class));
271                 this.addFilterChain("/test_perms/**", config(PERMS, "remote:invoke:lan,wan"));
272                 this.addFilterChain("/multiple_configs/**", AUTHC, config(ROLES, "b2bClient"), config(PERMS, "remote:invoke:lan,wan"));
273             }
274 
275             @Provides
276             public ShiroModuleTest.MockRealm createRealm() {
277                 return mockRealm;
278             }
279         });
280 
281         FilterChainResolver resolver = injector.getInstance(FilterChainResolver.class);
282         assertThat(resolver, instanceOf(SimpleFilterChainResolver.class));
283         SimpleFilterChainResolver simpleFilterChainResolver = (SimpleFilterChainResolver) resolver;
284 
285         // test the /test_authc resource
286         FilterChain filterChain = simpleFilterChainResolver.getChain(request, null, null);
287         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
288         Filter nextFilter = getNextFilter((SimpleFilterChain) filterChain);
289         assertThat(nextFilter, instanceOf(FormAuthenticationFilter.class));
290 
291         // test the /test_custom_filter resource
292         filterChain = simpleFilterChainResolver.getChain(request, null, null);
293         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
294         nextFilter = getNextFilter((SimpleFilterChain) filterChain);
295         assertThat(nextFilter, instanceOf(CustomFilter.class));
296 
297         // test the /test_perms resource
298         filterChain = simpleFilterChainResolver.getChain(request, null, null);
299         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
300         nextFilter = getNextFilter((SimpleFilterChain) filterChain);
301         assertThat(nextFilter, instanceOf(PermissionsAuthorizationFilter.class));
302 
303         // test the /multiple_configs resource
304         filterChain = simpleFilterChainResolver.getChain(request, null, null);
305         assertThat(filterChain, instanceOf(SimpleFilterChain.class));
306         assertThat(getNextFilter((SimpleFilterChain) filterChain), instanceOf(FormAuthenticationFilter.class));
307         assertThat(getNextFilter((SimpleFilterChain) filterChain), instanceOf(RolesAuthorizationFilter.class));
308         assertThat(getNextFilter((SimpleFilterChain) filterChain), instanceOf(PermissionsAuthorizationFilter.class));
309 
310         verify(servletContext, request);
311     }
312 
313     private Filter getNextFilter(SimpleFilterChain filterChain) {
314 
315         Iterator<? extends Filter> filters = filterChain.getFilters();
316         if (filters.hasNext()) {
317             return filters.next();
318         }
319 
320         return null;
321     }
322 
323     public static class MyDefaultWebSecurityManager extends DefaultWebSecurityManager {
324         @Inject
325         public MyDefaultWebSecurityManager(Collection<Realm> realms) {
326             super(realms);
327         }
328     }
329 
330     public static class MyDefaultWebSessionManager extends DefaultWebSessionManager {
331     }
332 
333     public static class MyWebEnvironment extends WebGuiceEnvironment {
334         @Inject
335         MyWebEnvironment(FilterChainResolver filterChainResolver, @Named(ShiroWebModule.NAME) ServletContext servletContext, WebSecurityManager securityManager) {
336             super(filterChainResolver, servletContext, securityManager);
337         }
338     }
339 
340     public static class CustomFilter implements Filter {
341 
342         @Override
343         public void init(FilterConfig filterConfig) throws ServletException {}
344 
345         @Override
346         public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {}
347 
348         @Override
349         public void destroy() {}
350     }
351 }