🐛 修复司机端档案按脱敏手机号匹配导致本人档案查不到
This commit is contained in:
+26
-11
@@ -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<User> 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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是「可作为司机档案手机号使用」的号码串。
|
||||
* <p>
|
||||
* 只判 1 开头的 11~15 位纯数字:库里既有 11 位真实手机号,也有 12 位账号
|
||||
* (如 175874212082),写死 11 位会让这类账号的司机解析不出本人号码。
|
||||
*/
|
||||
private boolean isMobileLike(String value) {
|
||||
return Func.isNotEmpty(value) && value.trim().matches("^1\\d{10,14}$");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+57
@@ -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> authUtil = mockStatic(AuthUtil.class)) {
|
||||
authUtil.when(AuthUtil::getUserId).thenReturn(USER_ID);
|
||||
authUtil.when(AuthUtil::getUserAccount).thenReturn(account);
|
||||
return scoped.currentByPhone(mobileHint);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user