forked from baskbuddy/zhangshun
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
88 lines
3.8 KiB
88 lines
3.8 KiB
package com.mydreamjob.auth;
|
|
|
|
import com.mydreamjob.config.AppJwtProperties;
|
|
import org.junit.jupiter.api.Test;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.boot.test.context.SpringBootTest;
|
|
import org.springframework.boot.test.mock.mockito.MockBean;
|
|
import org.springframework.context.ApplicationContext;
|
|
import org.springframework.data.redis.core.RedisTemplate;
|
|
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.time.Instant;
|
|
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
/**
|
|
* S02 复核项:只配置三个新密钥、**不配置旧 JWT_SECRET** 时应用仍可启动(任务书 §五)。
|
|
*
|
|
* <p>旧 {@code app.jwt.secret} 对 S02 的 Token 已无任何作用,但仍被
|
|
* {@code talentdiscovery.CandidateKeyGenerator} 使用(该组件在密钥为空时自行失败关闭),
|
|
* 因此保留属性但改为非强制解析。本测试证明:
|
|
* 1) 旧密钥为空时全量上下文仍能启动;2) 三项 S02 密钥正确绑定;
|
|
* 3) {@code application.yml} 中的旧密钥占位符带默认值,不再阻塞启动。</p>
|
|
*/
|
|
@SpringBootTest(properties = {
|
|
"app.jwt.secret=",
|
|
"app.jwt.access-secret=test-access-secret-key-for-integration-tests-only-not-for-production",
|
|
"app.jwt.refresh-secret=test-refresh-secret-key-for-integration-tests-only-not-for-production",
|
|
"app.jwt.token-hash-secret=test-token-hash-secret-key-for-integration-tests-only-not-for-production",
|
|
})
|
|
@org.springframework.test.context.ActiveProfiles("integration-test")
|
|
class JwtSecretOptionalStartupIntegrationTest {
|
|
|
|
@MockBean
|
|
private RedisTemplate<String, Object> redisTemplate;
|
|
|
|
@Autowired
|
|
private ApplicationContext applicationContext;
|
|
|
|
@Autowired
|
|
private AppJwtProperties jwtProperties;
|
|
|
|
@Autowired
|
|
private JwtTokenProvider jwtTokenProvider;
|
|
|
|
@Autowired
|
|
private AuthSessionService authSessionService;
|
|
|
|
@Test
|
|
void contextStartsWithOnlyTheThreeNewSecrets() {
|
|
assertThat(applicationContext).isNotNull();
|
|
assertThat(jwtTokenProvider).isNotNull();
|
|
assertThat(authSessionService).isNotNull();
|
|
|
|
assertThat(jwtProperties.getSecret())
|
|
.as("旧密钥为空也必须能启动").isNullOrEmpty();
|
|
assertThat(jwtProperties.getAccessSecret()).isNotBlank();
|
|
assertThat(jwtProperties.getRefreshSecret()).isNotBlank();
|
|
assertThat(jwtProperties.getTokenHashSecret()).isNotBlank();
|
|
assertThat(jwtProperties.getAccessSecret())
|
|
.isNotEqualTo(jwtProperties.getRefreshSecret());
|
|
}
|
|
|
|
@Test
|
|
void accessAndRefreshNeverFallBackToLegacySecret() throws Exception {
|
|
// 旧密钥为空时,S02 的两类 Token 仍必须能正常签发与校验 —— 证明没有回退到它。
|
|
Instant now = Instant.now();
|
|
String sid = java.util.UUID.randomUUID().toString();
|
|
IssuedToken access = jwtTokenProvider.generateAccessToken(
|
|
1L, "STUDENT", sid, java.util.UUID.randomUUID().toString(), now);
|
|
IssuedToken refresh = jwtTokenProvider.generateRefreshToken(
|
|
1L, sid, java.util.UUID.randomUUID().toString(), now);
|
|
|
|
assertThat(jwtTokenProvider.parseAndValidateAccessToken(access.token(), now).userId()).isEqualTo(1L);
|
|
assertThat(jwtTokenProvider.parseAndValidateRefreshToken(refresh.token(), now).userId()).isEqualTo(1L);
|
|
}
|
|
|
|
@Test
|
|
void applicationYmlNoLongerForcesLegacySecret() throws Exception {
|
|
Path yml = Path.of("src/main/resources/application.yml");
|
|
String content = Files.readString(yml);
|
|
assertThat(content)
|
|
.as("旧密钥占位符必须带默认值,否则未配置 JWT_SECRET 的环境无法启动")
|
|
.contains("secret: ${JWT_SECRET:}");
|
|
assertThat(content).doesNotContain("secret: ${JWT_SECRET}\n");
|
|
}
|
|
}
|
|
|