问题:当我尝试测试需要验证的方法(使用MockUser)时,它返回403错误,我错过了一些东西,尝试了几种方法,但它们不起作用。我不明白为什么会发生这种情况,有人可以解释一下吗?
例如,我创建了一个简单的应用程序来演示这个。
Spring-security配置类
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity
public class SpringConfigure extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
configureAuthorization(http);
configureAuthentication(http);
}
private void configureAuthorization(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/**").authenticated();
}
private void configureAuthentication(HttpSecurity http) throws Exception {
AuthenticationEntryPoint authenticationEntryPoint = (request, response, e) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
}
}
控制器类
@RestController
@RequestMapping("api/hello")
public class HelloController {
@RequestMapping(method = RequestMethod.GET)
public String hello(){
return "Hello";
}
}
和我的测试类
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {DemoApplication.class},webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class DemoApplicationTests {
RestTemplate restTemplate;
@Before
public void setUp(){
restTemplate = new RestTemplate();
}
@Test
@WithMockUser(username = "user")
public void helloTest() {
System.out.println(SecurityContextHolder.getContext().getAuthentication());
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8080/api/hello",String.class);
}
}
由 @WithMockUser 创建的用户
Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER
答案 0 :(得分:0)
我运行你的测试代码,似乎没问题。
@Test
@WithMockUser(username = "user")
public void helloTest() {
System.out.println(SecurityContextHolder.getContext().getAuthentication());
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8080/api/hello",String.class);
}
}
System.out.println(responseEntity);
结果:
org.springframework.security.authentication.UsernamePasswordAuthenticationToken@ca25360: Principal: org.springframework.security.core.userdetails.User@36ebcb: Username: user; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_USER
<200,Hello
答案 1 :(得分:0)
经过很长一段时间后,我在这里找到了答案https://stackoverflow.com/a/15203488/8664578(很多),并重复这个答案(https://stackoverflow.com/a/23658269/8664578) - 这是测试身份验证所需方法的最简单方法。 S:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {DemoApplication.class},webEnvironment =
SpringBootTest.WebEnvironment.DEFINED_PORT)
@Autowired
private WebApplicationContext context;
@Before
public void setup() {
mvc = MockMvcBuilders
.webAppContextSetup(context)
.apply(springSecurity())
.build();
}
public class DemoApplicationTests {
@Test
@WithMockUser
public void helloTest() {
mockMvc.perform(MockMvcRequestBuilders.get("http://localhost:8080/api/hello")).andExpect(status().isOk());
}
}
但是在开始时我的问题是如何使用RestTemplate,并且我使用在帖子中提出的解决方案,只是稍微改变了它(确实是最好的,但解决方案)。根据上面的链接:
&#34; HttpSessionSecurityContextRepository检查给定的HttpRequest并尝试访问相应的HttpSession。如果它存在,它将尝试从HttpSession读取SecurityContext。如果失败,则存储库会生成一个空的SecurityContext&#34;
我们可以为filterChain添加一个过滤器,它将使用我们想要的Spring上下文添加会话属性,如下例所示:
public class CustomFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken("user","password",
Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")));
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
HttpSession session = httpServletRequest.getSession();
session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY,
SecurityContextHolder.getContext());
chain.doFilter(request,response);
}
@Override
public void destroy() {
}
}
我们还需要在@Configuration类中添加过滤器,如下所示:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity
public class SpringConfigure extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
configureAuthorization(http);
configureAuthentication(http);
}
private void configureAuthorization(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/api/**").authenticated().and().addFilterBefore(new CustomFilter(), SecurityContextPersistenceFilter.class);
}
private void configureAuthentication(HttpSecurity http) throws Exception {
AuthenticationEntryPoint authenticationEntryPoint = (request, response, e) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED, e.getMessage());
}
}
最后测试课程:
@Test
public void helloTest() {
ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://localhost:8080/api/hello",String.class);
}
}
希望它对某人有所帮助。