gpt4 book ai didi

spring-security - 使用 Spring 安全测试来测试安全的 Spring MVC Controller

转载 作者:行者123 更新时间:2023-12-04 07:01:07 24 4
gpt4 key购买 nike

documentation 之后关于使用 Spring Security Test 为连接在 Spring Security 后面的 Spring MVC 应用程序编写测试。

这是一个普通的 spring-boot 应用程序,采用了典型的 spring-security 连接。这是主要的 Application.java

@SpringBootApplication
public class Application {

private static final Logger log = LoggerFactory.getLogger(Application.class);

public static void main(String[] args) {
SpringApplication.run(Application.class);
}
}

这是 spring-security 的接线:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

@Autowired
@Qualifier("customUserDetailsService")
UserDetailsService userDetailsService;

@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/","/sign_up").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf()
.and()
.exceptionHandling()
.accessDeniedPage("/access_denied")
.and()
.logout()
.permitAll();
}
}

如您所见,除了“/”和“/sign_up”之外的所有请求都需要进行身份验证。我已通过部署应用程序验证身份验证方案工作正常。


现在到了有趣的部分:编写 spring mvc 测试。 link我提供了一些很好的方法来编写此类测试,其中 spring-security-test 框架允许插入模拟用户/安全上下文。我采取的方法是

  1. 定义一个模拟的 UserDetails 接口(interface),以及
  2. 使用 SecurityContextFactory 创建一个 SecurityContext,它
  3. 应在测试启动期间插入到应用程序上下文中。

1.的代码如下:

@WithSecurityContext(factory=WithMockUserDetailsSecurityContextFactory.class)
public @interface WithMockUserDetails {
String firstName() default "apil";
String lastName() default "tamang";
String password() default "test";
long id() default 999;
String email() default "apil@test.com";


}

2.的代码如下:

final class WithMockUserDetailsSecurityContextFactory
implements WithSecurityContextFactory<WithMockUserDetails>{


@Override
public SecurityContext createSecurityContext(WithMockUserDetails mockUserDetails) {


/*
* Use an anonymous implementation for 'UserDetails' to return a
* mock authentication object, which is then set to the SecurityContext
* for the test runs.
*/
UserDetails principal=new UserDetails() {
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {

//another anonmyous interface implementation.
GrantedAuthority auth=new GrantedAuthority() {
@Override
public String getAuthority() {
return "ROLE_USER";
}
};
List<GrantedAuthority> authorities=new ArrayList<>();
authorities.add(auth);
return authorities;
}

@Override
public String getPassword() {
return mockUserDetails.password();
}

@Override
public String getUsername() {
return mockUserDetails.email();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}
};
Authentication authentication=new
UsernamePasswordAuthenticationToken(principal,principal.getPassword(),principal.getAuthorities());
SecurityContext context= SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
return context;
}
}

最后是测试类:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {Application.class})
@WebAppConfiguration
public class UserControllerTest {

@Autowired
private WebApplicationContext context;

@Autowired
private Filter springSecurityFilterChain;

private MockMvc mvc;

@Before
public void setup(){
mvc= MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}

@Test
public void testRootIsOk() throws Exception {
mvc.perform(get("/"))
.andExpect(status().isOk());
}

@Test
public void expectRedirectToLogin() throws Exception {
mvc.perform(get("/testConnect"))
.andExpect(redirectedUrl("http://localhost/login"));

}

@Test
@WithMockUserDetails
public void testAuthenticationOkay() throws Exception {
mvc.perform(get("/testConnect"))
.andExpect(content().string("good request."));
}

}

测试运行的输出:

  1. 测试 1 次通过。
  2. 测试 2 次通过。
  3. 测试 3 失败。预期输出但得到 <>。

测试 3 很可能失败,因为“SecurityContext”从未得到适当填充。根据文档,它应该有效。不知道我错过了什么。非常感谢任何帮助。

最佳答案

你需要添加

@Retention(RetentionPolicy.RUNTIME)

您的自定义注解,以便在运行时保留注解信息。否则WithSecurityContextTestExecutionListener无法检测到您的注释。

关于spring-security - 使用 Spring 安全测试来测试安全的 Spring MVC Controller ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35446391/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com