merge: 合并 K85 评论数匿名放行补修
This commit is contained in:
commit
a674865538
3 files changed
+117
No files matched your search
@@ -22958,3 +22958,13 @@ $ flutter test
|
|||||||
```
|
```
|
||||||
|
|
||||||
解读:客户端静态检查零告警;494 条测试通过,2 条需要本机联调服务的用例按既有保护跳过。K85 A/B 均已完成合并与推送,真机验收由用户执行。
|
解读:客户端静态检查零告警;494 条测试通过,2 条需要本机联调服务的用例按既有保护跳过。K85 A/B 均已完成合并与推送,真机验收由用户执行。
|
||||||
|
|
||||||
|
## 2026-10-21 K85 补修:评论数接口匿名放行
|
||||||
|
|
||||||
|
- 验收问题:`GET /app/comments/count` 未登录调用返回业务码 401。
|
||||||
|
- 根因:`SecurityConfig` 只放行评论列表 `GET /app/comments`,新增的 `/app/comments/count` 落入默认登录校验。
|
||||||
|
- 修复:增加 `GET /app/comments/count` 的 `permitAll()`,保持评论列表与评论总数一致的匿名只读语义;发布、删除等写接口仍要求登录。
|
||||||
|
- 新增 `AppCommentCountAnonymousSecurityTest`,装配真实 `SecurityConfig` 安全过滤链,未登录请求必须进入控制器并返回 `code=0`,避免仅测控制器时漏掉路由放行问题。
|
||||||
|
- 定向安全链测试通过:`Tests run: 1, Failures: 0, Errors: 0`。
|
||||||
|
- 功能提交:`7579d31 fix(security): 放行评论数接口匿名访问`。
|
||||||
|
- 完整门禁通过:JDK 21 下 14 个模块 `BUILD SUCCESS`,app-api `Tests run: 69, Failures: 0, Errors: 0`;全仓仅保留既有 ffmpeg smoke 用例 1 条环境跳过。
|
||||||
+106
@@ -0,0 +1,106 @@
|
|||||||
|
// Author: fruit.com.cn
|
||||||
|
|
||||||
|
package com.fruitshorts.app.controller;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fruitshorts.framework.log.AccessDeniedRecorder;
|
||||||
|
import com.fruitshorts.framework.security.JwtAuthenticationFilter;
|
||||||
|
import com.fruitshorts.framework.security.JwtTokenProvider;
|
||||||
|
import com.fruitshorts.framework.security.RestAuthEntryPoint;
|
||||||
|
import com.fruitshorts.framework.security.SecurityConfig;
|
||||||
|
import com.fruitshorts.interaction.service.CommentService;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mockito;
|
||||||
|
import org.springframework.beans.factory.ObjectProvider;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
|
import org.springframework.security.web.FilterChainProxy;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||||
|
import org.springframework.test.context.web.WebAppConfiguration;
|
||||||
|
import org.springframework.test.web.servlet.MockMvc;
|
||||||
|
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||||
|
import org.springframework.web.context.WebApplicationContext;
|
||||||
|
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
|
||||||
|
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||||
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||||
|
|
||||||
|
/** 评论总数接口的安全链契约:匿名只读请求必须直接进入控制器。 */
|
||||||
|
@ExtendWith(SpringExtension.class)
|
||||||
|
@WebAppConfiguration
|
||||||
|
@ContextConfiguration(classes = AppCommentCountAnonymousSecurityTest.TestConfig.class)
|
||||||
|
class AppCommentCountAnonymousSecurityTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MockMvc mockMvc;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private CommentService commentService;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void setUp() {
|
||||||
|
given(commentService.countByDrama(7L)).willReturn(9L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void should_allow_anonymous_count_request_through_security_chain() throws Exception {
|
||||||
|
mockMvc.perform(get("/app/comments/count").param("dramaId", "7"))
|
||||||
|
.andExpect(status().isOk())
|
||||||
|
.andExpect(jsonPath("$.code").value(0))
|
||||||
|
.andExpect(jsonPath("$.data").value(9));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@EnableWebMvc
|
||||||
|
@EnableWebSecurity
|
||||||
|
@Import(SecurityConfig.class)
|
||||||
|
static class TestConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
CommentService commentService() {
|
||||||
|
return mock(CommentService.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
AppCommentController appCommentController(CommentService commentService) {
|
||||||
|
return new AppCommentController(commentService);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
JwtAuthenticationFilter jwtAuthenticationFilter() {
|
||||||
|
return new JwtAuthenticationFilter(
|
||||||
|
mock(JwtTokenProvider.class),
|
||||||
|
mock(ObjectProvider.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
RestAuthEntryPoint restAuthEntryPoint(ObjectMapper objectMapper) {
|
||||||
|
return new RestAuthEntryPoint(
|
||||||
|
objectMapper,
|
||||||
|
new AccessDeniedRecorder(mock(ObjectProvider.class)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
ObjectMapper objectMapper() {
|
||||||
|
return new ObjectMapper();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
MockMvc mockMvc(WebApplicationContext context) {
|
||||||
|
FilterChainProxy securityFilter =
|
||||||
|
context.getBean("springSecurityFilterChain", FilterChainProxy.class);
|
||||||
|
return MockMvcBuilders.webAppContextSetup(context)
|
||||||
|
.addFilters(securityFilter)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -74,6 +74,7 @@ public class SecurityConfig {
|
|||||||
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
.requestMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||||
/* 评论列表允许匿名浏览;发布/删除仍需登录(未列入白名单即需鉴权) */
|
/* 评论列表允许匿名浏览;发布/删除仍需登录(未列入白名单即需鉴权) */
|
||||||
.requestMatchers(HttpMethod.GET, "/app/comments").permitAll()
|
.requestMatchers(HttpMethod.GET, "/app/comments").permitAll()
|
||||||
|
.requestMatchers(HttpMethod.GET, "/app/comments/count").permitAll()
|
||||||
.requestMatchers(PUBLIC_PATHS).permitAll()
|
.requestMatchers(PUBLIC_PATHS).permitAll()
|
||||||
.anyRequest().authenticated())
|
.anyRequest().authenticated())
|
||||||
.exceptionHandling(handling -> handling
|
.exceptionHandling(handling -> handling
|
||||||
|
|||||||
Reference in new issue
Block a user