JAVA/SPRING
[spring security] TEST방법.
gracelove91
2019. 10. 11. 17:37
SPRING SECURITY.
준비
먼저 maven을 통해 spring-security-test 모듈을 받아오자.
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
SecurityConfig.java
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/", "/info", "/account/**").permitAll()
.mvcMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
}
...
}
- 웹루트이하 "/", "/info", "/account/**" 에는 인증안된 사용자포함 모든 사용자가 접근 가능하다.
- "/admin" 페이지는 "ADMIN" 권한을 가진 사용자만 접근이 가능하다.
- 그 외 페이지는 인증된 사용자만 접근이 가능하다.
- formLogin()을 사용할 것이고, httpBasic()을 사용할 것이다.
SecurityTest(1).java
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class SecurityTest {
@Autowired
MockMvc mockMvc;
@Test
public void index_anonymous() throws Exception {
mockMvc.perform(get("/").with(anonymous()))
.andDo(print())
.andExpect(status().isOk());
}
@Test
public void index_user() throws Exception {
mockMvc.perform(get("/").with(user("grace").roles("USER")))
.andDo(print())
.andExpect(status().isOk());
}
- mockMvc.perform(get("/").with(anonymous()))
- annonymous(), 그러니까 인증이 안된 사용자가 접근할 때의 테스트다.
- mockMvc.perform(get("/").with(user("grace").roles("USER")))
- username = "grace", roles = "USER" 를 가진 계정이 '/'에 접근할 때의 테스트다.
SecurityTest(2).java
@Test
@WithAnonymousUser
public void index_anonymous_annotatedAnonymousUser() throws Exception {
mockMvc.perform(get("/"))
.andDo(print())
.andExpect(status().isOk());
}
@Test
@WithMockUser(username = "grace", roles = "ADMIN")
public void index_user_annotatedMockUser() throws Exception {
mockMvc.perform(get("/"))
.andDo(print())
.andExpect(status().isOk());
}
- 위의 SecyrityTest(1).java 와 같다. 'with(...)'를 어노테이션으로 대체한 것.
- 그런데 @WithMockUser 어노테이션을 보면 알다시피 너무 길다. 따라서 @WithMockUser를 메타에노테이션으로 활용해서 더 짧게 바꿔보자.
WithAdmin.java
@WithMockUser(username = "grace", roles = "ADMIN")
@Retention(RetentionPolicy.RUNTIME)
public @interface WithAdmin {
}
SecurityTest(3).java
@Test
@WithAdmin
public void admin_admin_customAnnotated() throws Exception {
mockMvc.perform(get("/admin"))
.andDo(print())
.andExpect(status().isOk());
}
- @WithAdmin 어노테이션을 붙이면 @WithMockUser(username = "grace", roles = "ADMIN") 을 사용하는 거나 마찬가지.
폼로그인에 대한 테스트.
SecurityTest(4).java
@Autowired
AccountService accountService;
@Test
@Transactional
public void login_success() throws Exception{
String username = "grace";
String password = "123";
Account user = this.createUser(username, password);
// mockMvc.perform(formLogin().user(user.getUsername()).password(user.getPassword())) //안된다! bycrypt로 암호화된 비밀번호가 들어오기 때문에.
mockMvc.perform(formLogin().user(user.getUsername()).password(password))
.andExpect(authenticated());
}
@Test
@Transactional
public void login_fail() throws Exception{
String username = "grace";
String password = "123";
Account user = this.createUser(username, password);
mockMvc.perform(formLogin().user(user.getUsername()).password("1234"))
.andExpect(unauthenticated());
}
private Account createUser(String username, String password) {
Account account = new Account();
account.setUsername(username);
account.setPassword(password);
account.setRole("USER");
return accountService.createNew(account);
}
- @Transactinal 어노테이션을 붙여서 DB에 영향이 없도록 하자.