当前位置: 首页 > 知识库问答 >
问题:

使用MockMvc测试spring安全性时未调用自定义身份验证提供程序

方季同
2023-03-14

我正在尝试使用spring的MockMvc类在我的spring boot应用程序中测试我的spring OAuth2授权和身份验证。我面临的根本问题是,我的自定义身份验证提供程序从未被调用,即使我已将其注册为spring安全使用的身份验证提供程序之一。我遵循了在这里和这里找到的spring安全教程。

代码段:Security Configureer类-这是添加自定义身份验证提供程序的地方。

@Configuration
@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {

    @Autowired
    private AuthenticationProvider authenticationProvider;


    @Override
    public void configure(AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .httpBasic();
    }
}

自定义身份验证提供程序-这将执行实际身份验证

@Component
public class UsernamePasswordAuthProvider implements AuthenticationProvider {

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        String username = authentication.getName();
        String password = authentication.getCredentials()
                .toString();

        if ("test".equals(username) && "test".equals(password)) {
            Collection<? extends GrantedAuthority> grantedAuthorityList = authentication
                    .getAuthorities();
            return new UsernamePasswordAuthenticationToken
                    (username, password, grantedAuthorityList);
        } else {
            throw new
                    BadCredentialsException("External system authentication failed");
        }
    }

    @Override
    public boolean supports(Class<?> auth) {
        return true;
    }
}

spring boot集成测试-这是使用web应用程序上下文实例化MockMvc的地方

@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConfigurationServiceApplication.class)
public class SettingsAPITest {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext wac;

    @Autowired
    private FilterChainProxy springSecurityFilterChain;


    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
                .addFilter(springSecurityFilterChain).build();
    }


    @Test 
    public void testGetStatus() throws Exception {
        //execute test
        mockMvc.perform(get("/status")
                .with(httpBasic("test","test")))
                .andDo(print())
                .andExpect(status().isOk());
    }
}

这是控制器

@RestController
public class StatusController{

    @RequestMapping(method = RequestMethod.GET)
    public ResponseEntity<String> getStatus(){

        return new ResponseEntity<>("I'm Ok", HttpStatus.OK);

    }
}

运行测试返回401,通过它放置一个断点并进行调试,就会发现自定义认证提供程序从未被使用过。

MockHttpServletRequest:
      HTTP Method = GET
      Request URI = /status
       Parameters = {}
          Headers = {Authorization=[Basic dGVzdDp0ZXN0]}

Handler:
             Type = null

Async:
    Async started = false
     Async result = null

Resolved Exception:
             Type = null

ModelAndView:
        View name = null
             View = null
            Model = null

FlashMap:
       Attributes = null

MockHttpServletResponse:
           Status = 401
    Error message = null
          Headers = {X-Content-Type-Options=[nosniff], X-XSS-Protection=[1; mode=block], Cache-Control=[no-cache, no-store, max-age=0, must-revalidate, no-store], Pragma=[no-cache, no-cache], Expires=[0], X-Frame-Options=[DENY], WWW-Authenticate=[Bearer realm="oauth2-resource", error="unauthorized", error_description="Full authentication is required to access this resource"], Content-Type=[application/json;charset=UTF-8]}
     Content type = application/json;charset=UTF-8
             Body = {"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
    Forwarded URL = null    Redirected URL = null
          Cookies = []

java.lang.AssertionError: Status  Expected :200 Actual   :401

我有一种感觉,我的webapp上下文配置正在某个地方被spring boot覆盖(因为这里的大部分东西是由spring boot自动配置的),但我不能真的证明这是合理的。任何帮助都是非常感谢的!!谢谢

顺便说一句,我看过相关的帖子

  • 未调用自定义身份验证提供程序
  • 未调用自定义AuthenticationProvider

共有1个答案

连德水
2023-03-14

我使用本教程设置身份验证提供程序。对于测试,这是我的设置:

import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.context.annotation.Bean;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.client.RestTemplate;

@RunWith(SpringRunner.class)
@WebMvcTest(MyController.class)
public class MyControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private RestTemplate restTemplate;


    @TestConfiguration
    static class AdditionalConfig {

        @Bean
        public MyAuthenticationProvider productValidator() {
            return new MyAuthenticationProvider();
        }

    }

    @Test
    public void shouldGetDocuments() throws Exception {
        this.mockMvc.perform(post("/partners/links/")
            .with(httpBasic("user", "password")))
                    .andExpect(status().isOk())
                    .andReturn();
    }
}

请记住,如果您忘记在测试中提供凭据(在我的例子中是基本身份验证),则不会调用您的自定义身份验证提供程序。

 类似资料:
  • 我想为Spring Security配置L 我配置spring-security.xml指出m 如何设置为 Spring,使用我的自定义类而不是他的 deafaul LDAP 身份验证提供程序?

  • 我正在尝试为正在进行的 spring-boot 项目实现身份验证和授权服务。我已经实现了一个基于 JPA 的身份验证提供程序,它工作正常。如何将 LDAP 身份验证提供程序添加到同一项目并根据用户身份验证类型在身份验证方法之间切换? 下面是我的代码 虽然我的LDAP证书是正确的,但它没有达到那个方法。如何从DB ex(LDAP、JPA、SSO)获取我的应用程序的身份验证方法,并执行相应的身份验证提

  • 我的问题是,我希望有两个身份验证提供商 之前:我有我的UserDetailServiceImpl,我根据数据库中的数据验证了用户的身份(不确定是哪个提供者) 现在:我使用了ActiveDirectoryLdapAuthentiation提供程序,如下所示 我成功了,所以我可以认证。 问题是: 我现在无法再使用数据库用户登录,现在只有LDAP。 未使用UserDetailsService,因此用户具

  • 在 spring security 中有几个对多个身份验证提供程序的引用,但在 Java config 中找不到示例。 以下链接给出了XML符号:Spring Security中的多个身份验证提供者 我们需要使用LDAP或DB进行身份验证 下面是我们的示例代码:

  • 我正在将应用程序的安全性迁移到Spring Security4.0。我的要求是身份验证应该是JAAS身份验证,自动化数据将从数据库中提取。所以我已经编写和自定义了身份验证提供程序。但我的问题是Spring没有将身份验证请求委托给我的自定义身份验证提供程序。 代码如下 web.xml条目 调用堆栈

  • 我正在尝试通过连接到LDAP使用Spring Security进行我的第一个演示。 我使用的Sping版本是:3.1.0.RELEASE 以下是我的security-integration.xml: 然而,每当我部署我的战争时,我都会遇到这个例外: HTTP状态500 - 类型异常报告 消息 描述服务器遇到一个内部错误(),该错误阻止它完成此请求。 例外情况 javax.servlet。Servl