Spring security 授权和TestRestTemplate

Spring security 授权和TestRestTemplate,spring-security,spring-test,Spring Security,Spring Test,我对其他数据使用默认的Spring登录表单和RESTAPI。已启用并使用会话 所有URL(除了/login表单)都受保护 那么,如何使用testrestemplate测试受保护的@RestController方法呢?(我可以向/api/login发出额外的请求,以获取Cookie,然后生成并添加头文件,但没有用于登录的REST端点,只有一个基于表单的身份验证) 另外,@WithMockUser注释是否仅用于MockMvc(并且不能与TestRestTemplate)一起使用?步骤 克隆sprin

我对其他数据使用默认的Spring登录表单和RESTAPI。已启用并使用会话

所有URL(除了
/login
表单)都受保护

那么,如何使用
testrestemplate
测试受保护的
@RestController
方法呢?(我可以向
/api/login
发出额外的请求,以获取
Cookie
,然后生成并添加
头文件
,但没有用于登录的REST端点,只有一个基于表单的身份验证)

另外,
@WithMockUser
注释是否仅用于
MockMvc
(并且不能与
TestRestTemplate
)一起使用?

步骤

  • 克隆spring安全示例repo
    git克隆https://github.com/spring-guides/gs-securing-web.git
  • 添加了RestControllerIT
  • csrf().disable()
    添加到
    WebSecurityConfig
    。如果启用csrf,此测试将无法通过
  • @RunWith(SpringRunner.class)
    @SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
    public class RestControllerIT {
    
        @Autowired
        TestRestTemplate testRestTemplate;
    
        @LocalServerPort
        int localPort;
    
        @Test
        public void test(){
            String securedUrl = "http://localhost:" + localPort + "/hello";
            String loginUrl = "http://localhost:" + localPort + "/login";
            String username = "user";
            String password = "password";
    
            MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
            form.set("username", username);
            form.set("password", password);
            ResponseEntity<String> loginResponse = testRestTemplate.postForEntity(
                    loginUrl,
                    new HttpEntity<>(form, new HttpHeaders()),
                    String.class);
            String cookie = loginResponse.getHeaders().get("Set-Cookie").get(0);
    
            HttpHeaders headers = new HttpHeaders();
            headers.add("Cookie", cookie);
            ResponseEntity<String> responseFromSecuredEndPoint = testRestTemplate.exchange(securedUrl, HttpMethod.GET, new HttpEntity<>(headers), String.class);
    
            assertEquals(responseFromSecuredEndPoint.getStatusCode(), HttpStatus.OK);
            assertTrue(responseFromSecuredEndPoint.getBody().contains("Hello World!"));
        }
    }
    
    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.csrf().disable()
                .authorizeRequests()
                    .antMatchers("/", "/home").permitAll()
                    .anyRequest().authenticated()
                    .and()
                .formLogin()
                    .loginPage("/login")
                    .permitAll()
                    .and()
                .logout()
                    .permitAll();
        }
    
        @Bean
        @Override
        public UserDetailsService userDetailsService() {
            UserDetails user =
                 User.withDefaultPasswordEncoder()
                    .username("user")
                    .password("password")
                    .roles("USER")
                    .build();
    
            return new InMemoryUserDetailsManager(user);
        }
    }