View Javadoc

1   /**
2    * Copyright 2013 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   */
16  package org.kuali.student.security.spring;
17  
18  import org.junit.Before;
19  import org.junit.Test;
20  import org.junit.runner.RunWith;
21  import org.springframework.beans.factory.annotation.Autowired;
22  import org.springframework.security.core.context.SecurityContext;
23  import org.springframework.security.web.FilterChainProxy;
24  import org.springframework.test.context.ContextConfiguration;
25  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
26  import org.springframework.test.context.web.WebAppConfiguration;
27  import org.springframework.test.web.servlet.MockMvc;
28  import org.springframework.test.web.servlet.MvcResult;
29  import org.springframework.test.web.servlet.ResultMatcher;
30  import org.springframework.test.web.servlet.setup.MockMvcBuilders;
31  import org.springframework.web.context.WebApplicationContext;
32  
33  import javax.servlet.http.HttpSession;
34  import java.util.Arrays;
35  import java.util.List;
36  
37  import static org.junit.Assert.assertEquals;
38  import static org.junit.Assert.assertNull;
39  import static org.kuali.student.security.spring.SecurityRequestPostProcessors.user;
40  import static org.springframework.security.web.context.HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY;
41  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
42  import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
43  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
44  import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
45  
46  /**
47   * This class provides tests for Spring Security Configuration
48   *
49   * @author Kuali Student Team
50   */
51  @RunWith(SpringJUnit4ClassRunner.class)
52  @WebAppConfiguration
53  @ContextConfiguration(
54          locations = {
55                  "classpath:ks-spring-security.xml",
56                  "classpath:test-spring-security-config.xml"
57          }
58  )
59  public class SpringSecurityTest {
60      @Autowired
61      private FilterChainProxy springSecurityFilterChain;
62  
63      @Autowired
64      private WebApplicationContext wac;
65  
66      private MockMvc mockMvc;
67  
68      @Before
69      public void setup() {
70          // setup a web application context while adding spring security to the filter chain
71          this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
72                  .addFilters(this.springSecurityFilterChain).build();
73      }
74  
75      @Test
76      public void testDeepUrlRequiresAuthentication() throws Exception {
77          // for any deep content, we expect a redirect because of spring security
78          mockMvc.perform(get("/some_deep_content"))
79                  .andExpect(redirectedUrl("http://localhost/login.jsp"));
80  
81      }
82  
83      @Test
84      public void testNoSecurityForNonAuthenticatedContent() throws Exception {
85          List<String> pathsToTest = Arrays.asList("/logout.html",
86                  "/services/A",
87                  "/favicon.ico",
88                  "/login.jsp",
89                  "/index.jsp",
90                  "/a.css",
91                  "/b.js",
92                  "/c.png",
93                  "/d.gif",
94                  "/e.jpg",
95                  "/themes/ksboot/theme-derived.properties");
96  
97          // for each of the tested paths, we expect no security at all.
98          // Content will be 404 Not Found as we are only testing Spring Security and not
99          // the MVC layer
100         for (String path : pathsToTest) {
101             mockMvc.perform(get(path))
102                     .andExpect(status().isNotFound());
103         }
104     }
105 
106     @Test
107     public void testUserAuthenticatesSuccessfully() throws Exception {
108         final String username = "user";
109 
110         // when supplying a username (with any password), we expect a redirect to /
111         // furthermore, after authentication, principal should now be present in session
112         mockMvc.perform(post("/j_spring_security_check").param("j_username", username).param("j_password", "anything"))
113                 .andExpect(redirectedUrl("/"))
114                 .andExpect(new ResultMatcher() {
115                     @Override
116                     public void match(MvcResult result) throws Exception {
117                         HttpSession session = result.getRequest().getSession();
118                         SecurityContext securityContext = (SecurityContext) session.getAttribute(SPRING_SECURITY_CONTEXT_KEY);
119                         assertEquals(securityContext.getAuthentication().getName(), username);
120                     }
121                 });
122     }
123 
124     @Test
125     public void testLogout() throws Exception {
126         // after logging out
127         mockMvc.perform(get("/j_spring_security_logout"))
128                 // should be redirected to /
129                 .andExpect(redirectedUrl("/"))
130                 .andExpect(new ResultMatcher() {
131                     @Override
132                     public void match(MvcResult result) throws Exception {
133                         HttpSession session = result.getRequest().getSession();
134                         SecurityContext securityContext = (SecurityContext) session.getAttribute(SPRING_SECURITY_CONTEXT_KEY);
135                         // security context should be wiped out
136                         assertNull("Spring Security context should be null", securityContext);
137                     }
138                 });
139     }
140 
141     @Test
142     public void testAccessToAdminArea() throws Exception {
143         final String adminUrl = "/admin/index.html";
144 
145         // user fred is not allowed to access admin URLs
146         mockMvc.perform(get(adminUrl).with(user("fred").roles("ROLE_KS_USER")))
147                 .andExpect(status().isForbidden());
148 
149         // only user with "admin" role is allowed access to admin URLs
150         mockMvc.perform(get(adminUrl).with(user("admin").roles("ROLE_KS_ADMIN")))
151                 .andExpect(status().isNotFound());
152     }
153 }