From 143c6f99fb3f8535890ec69987de9bfc80018c35 Mon Sep 17 00:00:00 2001 From: weicw1996 Date: Fri, 9 Oct 2026 20:13:38 +0800 Subject: [PATCH] =?UTF-8?q?:bug:=20=E4=BF=AE=E5=A4=8D=E5=8F=B8=E6=9C=BA?= =?UTF-8?q?=E7=AB=AF=E6=A1=A3=E6=A1=88=E6=8C=89=E8=84=B1=E6=95=8F=E6=89=8B?= =?UTF-8?q?=E6=9C=BA=E5=8F=B7=E5=8C=B9=E9=85=8D=E5=AF=BC=E8=87=B4=E6=9C=AC?= =?UTF-8?q?=E4=BA=BA=E6=A1=A3=E6=A1=88=E6=9F=A5=E4=B8=8D=E5=88=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/DriverAppServiceImpl.java | 37 ++++++++---- .../impl/DriverAppServiceImplTest.java | 57 +++++++++++++++++++ 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java index ee8feb27..1d09822f 100644 --- a/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java +++ b/blade-service/blade-transport/src/main/java/org/springblade/transport/service/impl/DriverAppServiceImpl.java @@ -186,7 +186,13 @@ public class DriverAppServiceImpl implements IDriverAppService { String selfPhone = resolveSelfPhone(userId); String hint = Func.isEmpty(mobileHint) ? null : mobileHint.trim(); if (Func.isNotEmpty(hint)) { - if (Func.isNotEmpty(selfPhone) && !selfPhone.equals(hint)) { + if (Func.isEmpty(selfPhone)) { + // 解析不出本人号码时不能拿前端传的 mobile 去查: + // currentDriver 会直接按 mobile 等值查询,传入他人号码即可读到他人档案。 + // 这里返回空让它退回按 user_id 查,宁可查不到也不越权。 + return null; + } + if (!selfPhone.equals(hint)) { throw new ServiceException("只能查询本人司机档案"); } return hint; @@ -196,21 +202,30 @@ public class DriverAppServiceImpl implements IDriverAppService { private String resolveSelfPhone(Long userId) { String account = AuthUtil.getUserAccount(); - if (Func.isNotEmpty(account) && account.matches("^1\\d{10}$")) { + if (isMobileLike(account)) { return account.trim(); } + // 用户中心的 phone 带 @Sensitive(MOBILE),经 Feign 回来是「175****12082」这类脱敏串, + // 拿它去 eq(mobile) 永远查不到、拿它比对本人的真实号码又必然不等。 + // 因此这里只取未脱敏的 account;脱敏的 phone 一律不用。 R result = userClient.userInfoById(userId); - if (result == null || !R.isSuccess(result) || result.getData() == null) { - return Func.isEmpty(account) ? null : account.trim(); - } - User user = result.getData(); - if (Func.isNotEmpty(user.getPhone())) { - return user.getPhone().trim(); - } - if (Func.isNotEmpty(user.getAccount()) && user.getAccount().matches("^1\\d{10}$")) { - return user.getAccount().trim(); + if (result != null && R.isSuccess(result) && result.getData() != null) { + String userAccount = result.getData().getAccount(); + if (isMobileLike(userAccount)) { + return userAccount.trim(); + } } return Func.isEmpty(account) ? null : account.trim(); } + /** + * 是否是「可作为司机档案手机号使用」的号码串。 + *

+ * 只判 1 开头的 11~15 位纯数字:库里既有 11 位真实手机号,也有 12 位账号 + * (如 175874212082),写死 11 位会让这类账号的司机解析不出本人号码。 + */ + private boolean isMobileLike(String value) { + return Func.isNotEmpty(value) && value.trim().matches("^1\\d{10,14}$"); + } + } diff --git a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java index 0894e214..6d2c0607 100644 --- a/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java +++ b/blade-service/blade-transport/src/test/java/org/springblade/transport/service/impl/DriverAppServiceImplTest.java @@ -5,7 +5,10 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.mockito.MockedStatic; +import org.springblade.core.log.exception.ServiceException; import org.springblade.core.secure.utils.AuthUtil; +import org.springblade.core.tool.api.R; +import org.springblade.system.pojo.entity.User; import org.springblade.transport.pojo.entity.Driver; import org.springblade.transport.pojo.entity.TransportVehicle; import org.springblade.transport.pojo.vo.DriverVehicleCardVO; @@ -17,6 +20,7 @@ import java.time.LocalDate; import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; @@ -81,6 +85,31 @@ class DriverAppServiceImplTest { assertEquals("2028-12-04", card.getRoadTransportCertStartDate()); } + // ---------------------------------------------------------------- 手机号解析 + + @Test + @DisplayName("12 位手机号也能解析出本人号码——库里存在 12 位司机账号,写死 11 位会让他们查不到自己的档案") + void twelveDigitAccountIsUsableAsPhone() { + assertEquals("黄大富", currentByPhone("175874212082", "175874212082", null).getDriverName()); + } + + @Test + @DisplayName("用户中心 phone 是脱敏串时改用其 account——脱敏 phone 既查不到档案,也会把本人真实号码误判成越权") + void maskedUserPhoneFallsBackToAccount() { + User user = new User(); + user.setPhone("175****12082"); + user.setAccount("175874212082"); + + assertEquals("黄大富", currentByPhone(null, null, user).getDriverName()); + } + + @Test + @DisplayName("传他人手机号一律拒绝——不能因为解析不到本人号码就放行,那等于允许按手机号查任意档案") + void otherPeoplesMobileIsRejected() { + assertEquals("只能查询本人司机档案", assertThrows(ServiceException.class, + () -> currentByPhone("13900000001", "175874212082", null)).getMessage()); + } + // ---------------------------------------------------------------- 辅助 /** 造一辆只关心有效期三个字段的车 */ @@ -122,4 +151,32 @@ class DriverAppServiceImplTest { } } + /** + * 按给定的登录态跑一次 currentByPhone。 + * + * @param mobileHint 前端传入的 mobile,可为 null + * @param account JWT 里的账号,可为 null + * @param user 用户中心返回的用户,可为 null(表示走不到用户中心) + */ + private Driver currentByPhone(String mobileHint, String account, User user) { + IUserClient userClient = mock(IUserClient.class); + if (user != null) { + when(userClient.userInfoById(USER_ID)).thenReturn(R.data(user)); + } + DriverAppServiceImpl scoped = new DriverAppServiceImpl(driverService, transportVehicleService, userClient); + + Driver driver = new Driver(); + driver.setId(9002L); + driver.setUserId(USER_ID); + driver.setDriverName("黄大富"); + driver.setMobile("175874212082"); + when(driverService.getOne(any(LambdaQueryWrapper.class))).thenReturn(driver); + + try (MockedStatic authUtil = mockStatic(AuthUtil.class)) { + authUtil.when(AuthUtil::getUserId).thenReturn(USER_ID); + authUtil.when(AuthUtil::getUserAccount).thenReturn(account); + return scoped.currentByPhone(mobileHint); + } + } + }