2015-10-05 20 views
8

"1.3.0.M5" önyükleme sürümünü kullanıyorum ("1.2.5.RELEASE" sürümünü de denedim). org.springframework.web.client.HttpClientErrorException:/API/sampleentity erişim olduğunda başarısızYay önyükleme, güvenlik testleri için güvenliği devre dışı bırak

@SpringBootApplication 
public class SpringBootMainApplication { 
    public static void main(String[] args) { 
    SpringApplication.run(SpringBootMainApplication.class, args); 
    } 
} 

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 
    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); 
    } 
    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
    http.authorizeRequests() 
    .antMatchers("/api/sampleentity").authenticated() 
    .and().authorizeRequests() 
    .and().formLogin().permitAll() 
    .and().logout().permitAll().logoutUrl("/logout") 
    .logoutSuccessUrl("/"); 
    } 
    @Override 
    @Bean 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
    return super.authenticationManagerBean(); 
    } 
} 

@RestController 
@RequestMapping("/api/sampleentity") 
public class SampleEntityController { 
    @RequestMapping(method= RequestMethod.GET) 
    public Iterable<SampleEntity> getAll() { 
    return ImmutableSet.of(); 
    } 
    @RequestMapping(method=RequestMethod.POST) 
    @ResponseStatus(value= HttpStatus.CREATED) 
    public SampleEntity create(@RequestBody SampleEntity sampleEntity) { 
    return sampleEntity; 
    } 
} 

ve testi:

<dependency> 
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-web</artifactId> 
</dependency> 
<dependency> 
    <groupId>org.springframework.security</groupId> 
    <artifactId>spring-security-test</artifactId> 
    <scope>test</scope> 
</dependency> 

ve kodu: Bahar ek güvenlik 403 Forbidden (.. .)

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = SpringBootMainApplication.class) 
@WebAppConfiguration 
@IntegrationTest({"server.port=0"}) 
public class SampleEntityTest { 
    @Value("${local.server.port}") 
    private int port; 
    private String url; 
    private RestTemplate restTemplate; 
    @Autowired 
    private ApplicationContext context; 
    @BeforeClass 
    public static void authenticate(){ 
//ONE TRY 
//  Authentication authentication = 
//    new UsernamePasswordAuthenticationToken("user", "password", 
//              AuthorityUtils.createAuthorityList("USER")); //tried "ROLE_USER" 
//  SecurityContextHolder.getContext().setAuthentication(authentication); 
    } 
    @Before 
    public void setUp() { 
    url = String.format("http://localhost:%s/api/sampleentity", port); 
    restTemplate = new RestTemplate(); 
//ANOTHER TRY 
//  AuthenticationManager authenticationManager = context.getBean(AuthenticationManager.class); 
//  Authentication authentication = authenticationManager 
//    .authenticate(new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("USER"))); //tried "ROLE_USER" 
//  SecurityContextHolder.getContext().setAuthentication(authentication); 
    } 
    //THIS METHOD SHOULD WORK ! 
    @Test 
//ANOTHER TRY 
//@WithMockUser(username="user",password = "password", roles={"USER"})//tried "ROLE_USER" 
    public void testEntity_create() throws Exception { 
    SampleEntity sampleEntity = create("name", 1); 
    ResponseEntity<SampleEntity> response = restTemplate.postForEntity(url, sampleEntity, SampleEntity.class); 
    assertEquals(HttpStatus.CREATED, response.getStatusCode()); 
    } 
    private SampleEntity create(String name, int id) { 
    SampleEntity entity = new SampleEntity(); 
    entity.setName(name); 
    entity.setId(id); 
    return entity; 
    } 
} 

Ben ana uygulamayı çalıştırmak () ve erişim url: http://localhost:8080/api/sampleentity Ben giriş sayfasına yönlendirilir ediyorum.

Sınamayı nasıl yürütebilirim ve güvenliği nasıl devre dışı bırakabilirim veya yalnızca oturum açabilir miyim?

--my çözüm: profiller kullanılarak testinden güvenliğini dışlamak:

@SpringBootApplication 
@EnableAutoConfiguration(exclude = { SecurityAutoConfiguration.class}) 
public class SpringBootMainApplication {body the same} 

@EnableWebSecurity 
@Import(SecurityAutoConfiguration.class) 
@Profile("!test") 
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {body the same} 

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = SpringBootMainApplication.class) 
@WebAppConfiguration 
@IntegrationTest({"server.port=0"}) 
@ActiveProfiles("test") 
public class SampleEntityTest {body the same} 

cevap

2

Sen sorununuzu (ler) çözmek için yapılandırma ve test bazı değişiklikler yapmak zorundayız. Çözümünüz neden çalışmadığını

Önce açıklayacağız:

  1. Bahar RestTemplate sınıf REST hizmete erişmek için olası bir yoldur ancak (kokan hangi bazı başlık bilgileri kendisinin imal edilmiş şekilde yoksun RestTemplate ile imkansız olduğu anlamına gelir). Bu yüzden kimlik doğrulaması çalışmadı.
  2. İlk çözüm girişimi, RestTemplate sınıfının kullanımı nedeniyle çalışmadığından, RestTemplate isteğinin yeni bir oturum oluşturması olasıdır. Tamamen farklı bir ortam oluşturuyor. Kodum, @PreAuthorize no'lu ek açıklama ile güvenceye alınmış yöntemleri test etmek istiyorsanız, ancak bu tür bir yöntemi doğrudan testinizde yürütmek istiyorsanız ve geçerli bir kimlik doğrulamasına ihtiyacınız varsa çalışır.
  3. Geçerli yay güvenlik yapılandırmanızdan dolayı herhangi bir kullanıcıyı otomatik olarak yetkilendiremezsiniz.

İkincisi, burada kod için gerekli değişiklikler şunlardır:

I (http başlık özelliğiyle kimlik doğrulamasını etkinleştirmek için) ve ben httpBasic Doğrulama desteği eklemek zorunda

@Configuration 
@EnableWebSecurity 
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { 

@Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth.inMemoryAuthentication().withUser("user").password("password").roles("USER"); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
    http.httpBasic().and().csrf().disable() 
    .authorizeRequests().antMatchers("/api/sampleentity").authenticated() 
    .and().authorizeRequests().antMatchers("/users").hasRole("ADMIN") 
    .and().formLogin().permitAll() 
    .and().logout().permitAll().logoutUrl("/logout") 
    .logoutSuccessUrl("/"); 
    } 

    @Override 
    @Bean 
    public AuthenticationManager authenticationManagerBean() throws Exception { 
    return super.authenticationManagerBean(); 
    } 
} 

Birinci yapılandırma sınıfı Devre dışı bırakılmış csrf tokenleri (ikincisi sadece kolaylık sağlamak için, uygulamanızın kritikliğine göre bunları yeniden etkinleştirmeniz gerekir).

İkincisi TestClass

:

import java.io.IOException; 
import java.nio.charset.Charset; 
import java.util.Arrays; 

import javax.servlet.Filter; 

import org.junit.Assert; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.test.IntegrationTest; 
import org.springframework.boot.test.SpringApplicationConfiguration; 
import org.springframework.http.MediaType; 
import org.springframework.http.converter.HttpMessageConverter; 
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; 
import org.springframework.mock.http.MockHttpOutputMessage; 
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; 
import org.springframework.test.context.web.WebAppConfiguration; 
import org.springframework.test.web.servlet.MockMvc; 
import org.springframework.test.web.servlet.setup.MockMvcBuilders; 
import org.springframework.web.context.WebApplicationContext; 

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; 
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; 
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; 
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.*; 

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = SpringBootMainApplication.class) 
@WebAppConfiguration 
@IntegrationTest({ "server.port=0" }) 
public class SampleEntityTest { 

private String url; 
private MockMvc mockMvc; 
private HttpMessageConverter mappingJackson2HttpMessageConverter; 

private MediaType contentType = new MediaType(
     MediaType.APPLICATION_JSON.getType(), 
     MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8")); 

@Autowired 
private WebApplicationContext webApplicationContext; 

@Autowired 
private Filter springSecurityFilterChain; 

@Autowired 
void setConverters(HttpMessageConverter<?>[] converters) { 
    for (HttpMessageConverter hmc : Arrays.asList(converters)) { 
     if (hmc instanceof MappingJackson2HttpMessageConverter) { 
      this.mappingJackson2HttpMessageConverter = hmc; 
     } 
    } 

    Assert.assertNotNull("the JSON message converter must not be null", 
      this.mappingJackson2HttpMessageConverter); 
} 

@Before 
public void setUp() { 
    url = "/api/sampleentity"; 
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext) 
      .addFilters(springSecurityFilterChain).build(); 
} 

@Test 
public void testEntityGet() throws Exception { 
    mockMvc.perform(
      get(url) 
      .with(httpBasic("user", "password"))) 
      .andExpect(status().isOk()); 
} 

@Test 
public void testEntityPost() throws Exception { 
    SampleEntity sampleEntity = new SampleEntity(); 
    sampleEntity.setName("name"); 
    sampleEntity.setId(1); 
    String json = json(sampleEntity); 
    mockMvc.perform(
      post(url) 
      .contentType(contentType) 
      .content(json) 
      .with(httpBasic("user", "password"))) 
      .andExpect(status().isCreated()); 
} 

protected String json(Object o) throws IOException { 
    MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage(); 
    this.mappingJackson2HttpMessageConverter.write(o, 
      MediaType.APPLICATION_JSON, mockHttpOutputMessage); 
    return mockHttpOutputMessage.getBodyAsString(); 
} 

}

Burada makas/makas güvenlik testi yaklaşımını kullanmışlardır

.kullanılan

sürümleri: Eğer dinlenme api test etmek isterseniz

<parent> 
     <groupId>org.springframework.boot</groupId> 
     <artifactId>spring-boot-starter-parent</artifactId> 
     <version>1.2.5.RELEASE</version> 
    </parent> 

    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-core</artifactId> 
     <version>4.0.2.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-web</artifactId> 
     <version>4.0.2.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-config</artifactId> 
     <version>4.0.2.RELEASE</version> 
    </dependency> 
    <dependency> 
     <groupId>org.springframework.security</groupId> 
     <artifactId>spring-security-test</artifactId> 
     <version>4.0.2.RELEASE</version> 
     <scope>test</scope> 
    </dependency> 

seni Chrome için Postacı eklentisi tavsiye edebilir. Bu, sorunu daha hızlı tanımlamanıza yardımcı olabilir.

Bu sorunun nihayetinde çözülmesini sağlar.

+0

Gönderiyi güncelledim. Tavsiyeni denedim, ama hala 403 Yasakım var. Neyi yanlış yapıyorum? –

+0

@WithMockUser olmadan deneyebilir misiniz? Özel bir uygulamanız varsa, AuthenticationProvider'ınızı sağlayabilir misiniz? – BeWu

+0

Merhaba, bu 3 bağ ayrı ayrı yapıldı (@WithMockUser'e yorum yaptım). Herhangi bir özel AuthenticationProvider kullanmıyorum. –

İlgili konular