You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MockMvc模拟OAuth2 Token失效,请求Token触发access_denied错误

解决Spring OAuth2 API测试中MockMvc调用出现access_denied的问题

从你描述的问题来看,你已经搞定了OAuth2RestTemplate的Bean注入问题,但现在用MockMvc调用受OAuth2保护的接口时触发了access_denied错误——核心原因是测试环境里没正确模拟OAuth2的认证流程,导致请求尝试获取访问令牌时直接失败。下面给你几个针对性的解决方案:

方案1:用Spring Security Test模拟已认证的OAuth2用户

Spring Security Test自带了MockMvc的扩展能力,可以直接模拟OAuth2登录状态,完全不用实际去请求令牌。

首先给测试类加上必要的注解:

@SpringBootTest
@AutoConfigureMockMvc
public class TokenControllerTest {

    @Autowired
    private MockMvc mockMvc;

    // 测试方法写在这里
}

然后在测试方法里用oauth2Login()处理器模拟登录状态:

@Test
void getAuthenticationInfo_Success() throws Exception {
    mockMvc.perform(get("/getAuthenticationInfo")
            // 一键模拟OAuth2登录后的状态
            .with(SecurityMockMvcRequestPostProcessors.oauth2Login()))
            .andExpect(status().isOk());
}

如果需要自定义用户信息(比如用户ID、权限、个人属性),可以手动构建认证令牌:

@Test
void getAuthenticationInfo_CustomUser() throws Exception {
    // 自定义用户属性
    Map<String, Object> userAttributes = Map.of(
            "sub", "test-user-123",
            "name", "Miguel Costa",
            "email", "test@example.com"
    );
    DefaultOAuth2User oauth2User = new DefaultOAuth2User(
            Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")),
            userAttributes,
            "sub" // 指定用户标识字段
    );

    // 构建完整的OAuth2认证令牌
    OAuth2AuthenticationToken authToken = new OAuth2AuthenticationToken(
            oauth2User,
            Collections.singletonList(new SimpleGrantedAuthority("ROLE_USER")),
            "your-registration-id" // 对应你配置的客户端注册ID
    );

    mockMvc.perform(get("/getAuthenticationInfo")
            .with(SecurityMockMvcRequestPostProcessors.authentication(authToken)))
            .andExpect(status().isOk());
}

方案2:模拟OAuth2RestTemplate的行为(如果接口依赖它调用外部服务)

如果你的getAuthenticationInfo接口内部会通过OAuth2RestTemplate调用其他OAuth2保护的服务,那测试时就得模拟这个模板的返回值,避免它真的去请求令牌:

@SpringBootTest
@AutoConfigureMockMvc
public class TokenControllerTest {

    @Autowired
    private MockMvc mockMvc;

    // 用@MockBean替换真实的OAuth2RestTemplate
    @MockBean
    private OAuth2RestTemplate oauthRestTemplate;

    @Test
    void getAuthenticationInfo_Success() throws Exception {
        // 模拟RestTemplate的调用返回结果
        when(oauthRestTemplate.getForObject(
                anyString(), // 匹配任意请求URL
                eq(YourResponseClass.class) // 匹配返回的对象类型
        )).thenReturn(new YourResponseClass("mock-data"));

        mockMvc.perform(get("/getAuthenticationInfo")
                .with(oauth2Login()))
                .andExpect(status().isOk());
    }
}

方案3:配置测试环境的OAuth2模拟参数(可选)

如果你的测试需要更贴近真实环境的配置,可以在src/test/resources/application.yml里加一套模拟的OAuth2客户端配置:

spring:
  security:
    oauth2:
      client:
        registration:
          test-client:
            client-id: test-client-id
            client-secret: test-client-secret
            authorization-grant-type: authorization_code
            redirect-uri: "{baseUrl}/login/oauth2/code/test-client"
        provider:
          test-provider:
            authorization-uri: https://mock-auth-server.com/oauth/authorize
            token-uri: https://mock-auth-server.com/oauth/token
            user-info-uri: https://mock-auth-server.com/userinfo
            user-name-attribute: sub

额外注意事项

  • 确保你的测试依赖里包含Spring Security Test:
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-test</artifactId>
    <scope>test</scope>
</dependency>
  • 检查控制器上的权限注解(比如@PreAuthorize),确保模拟的用户拥有对应的权限。

内容的提问来源于stack exchange,提问作者Miguel Costa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:20:38