2015-10-05 20 views
8

Tôi sử dụng phiên bản khởi động mùa xuân "1.3.0.M5" (Tôi cũng đã thử phiên bản "1.2.5.RELEASE"). Tôi thêm an ninh mùa xuân:Khởi động mùa xuân, tắt bảo mật cho các thử nghiệm

<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> 

và mã:

@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; 
    } 
} 

và bài kiểm tra đó là không khi/api/sampleentity là truy cập: org.springframework.web.client.HttpClientErrorException: 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; 
    } 
} 

Khi tôi chạy ứng dụng từ main() và truy cập url: http://localhost:8080/api/sampleentity tôi đang chuyển hướng đến trang đăng nhập.

Làm cách nào để chạy thử nghiệm và tắt bảo mật hoặc chỉ đăng nhập người dùng?

giải pháp --my: loại trừ bảo mật từ các thử nghiệm sử dụng hồ sơ:

@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} 

Trả lời

2

Bạn phải làm một số thay đổi cấu hình và thử nghiệm của bạn để giải quyết vấn đề của bạn (s).

Trước tiên tôi sẽ giải thích lý do tại sao giải pháp của bạn không hoạt động:

  1. Lớp xuân RestTemplate là một cách tốt để truy cập dịch vụ REST của bạn nhưng lại thiếu một số thông tin tiêu đề cách thức mà nó được xây dựng (nào doesn' t có nghĩa là không thể với RestTemplate). Đó là lý do tại sao xác thực không hoạt động.
  2. Nỗ lực giải pháp đầu tiên của tôi không hoạt động do việc sử dụng lớp RestTemplate, vì yêu cầu RestTemplate có khả năng tạo một phiên mới. Nó thiết lập một môi trường hoàn toàn khác. Mã của tôi hoạt động nếu bạn muốn kiểm tra Phương thức được bảo mật bằng chú thích @PreAuthorize nhưng chỉ khi bạn muốn thực thi phương thức đó trực tiếp trong thử nghiệm của mình và bạn cần xác thực hợp lệ.
  3. Bạn không thể tự động cho phép bất kỳ người dùng nào làm cấu hình bảo mật mùa xuân hiện tại của bạn.

Thứ hai, đây là những thay đổi cần thiết để mã của bạn:

First class cấu hình

@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(); 
    } 
} 

tôi đã có thêm hỗ trợ httpBasic Authentication (để cho phép xác thực thông qua thuộc tính tiêu đề http) và tôi mã thông báo csrf bị vô hiệu hóa (sau này chỉ để thuận tiện, bạn nên bật lại chúng theo mức độ nghiêm trọng của ứng dụng của bạn).

Và thứ hai 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(); 
} 

}

Tôi đã sử dụng các phương pháp kiểm tra an ninh mùa xuân/mùa xuân ở đây.

phiên bản sử dụng:

<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> 

Nếu bạn muốn kiểm tra api phần còn lại của bạn tôi có thể khuyên bạn nên plugin Postman dành cho Chrome. Vì điều đó có thể giúp bạn xác định vấn đề nhanh hơn nhiều.

Tôi hy vọng điều này sẽ giúp bạn cuối cùng giải quyết vấn đề của mình.

+0

Tôi đã cập nhật bài đăng của mình. Tôi đã cố gắng lời khuyên của bạn, nhưng tôi vẫn có 403 Cấm. Tôi làm gì sai? –

+0

Bạn có thể thử nó mà không có @WithMockUser không? Và bạn có thể cung cấp AuthenticationProvider của mình nếu bạn có triển khai tùy chỉnh không? – BeWu

+0

Xin chào, 3 mối quan hệ này đã được thực hiện riêng biệt (vì vậy tôi đã nhận xét @WithMockUser). Tôi không sử dụng bất kỳ AuthenticationProvider tùy chỉnh nào. –

Các vấn đề liên quan