init: UserBaseService (backend + deploy + scripts)
ci-userbase-service / build-and-push (push) Successful in 40s
ci-userbase-service / build-and-push (push) Successful in 40s
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
package com.yunhai.userbase.controller.oapi;
|
||||
|
||||
import com.yunhai.platform.utils.model.BoaUser;
|
||||
import com.yunhai.userbase.service.UserCenterService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* 用户中心开放接口:供其他业务服务经 yh-app-auth 签名调用({@code /open/api/user/...})。<br><br>
|
||||
* 路径与基础平台 {@code DefaultUserCenterClient} 硬编码的契约严格一致:
|
||||
* {@code GET /open/api/user/byId?id=}、{@code /byLoginName?loginName=}、{@code /byPhone?phone=}。<br>
|
||||
* 接口本身不做验签——签名由 {@code OpenApiAuthEnforceConfiguration} 在过滤器层强制要求,
|
||||
* 未带 {@code X-App-Key/X-Timestamp/X-Signature} 的请求直接 401。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/open/api/user/")
|
||||
public class OpenBaseController {
|
||||
|
||||
@Autowired
|
||||
private UserCenterService userCenterService;
|
||||
|
||||
@GetMapping("byId")
|
||||
public BoaUser byId(@RequestParam("id") Integer id) {
|
||||
return userCenterService.getUserInfoWithDeptById(id);
|
||||
}
|
||||
|
||||
@GetMapping("byLoginName")
|
||||
public BoaUser byLoginName(@RequestParam("loginName") String loginName) {
|
||||
if (loginName == null || loginName.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return userCenterService.getUserInfoWithDeptByAccount(loginName);
|
||||
}
|
||||
|
||||
@GetMapping("byPhone")
|
||||
public BoaUser byPhone(@RequestParam("phone") String phone) {
|
||||
if (phone == null || phone.trim().isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return userCenterService.getUserInfoWithDeptByPhone(phone);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.yunhai.userbase.controller.oapi;
|
||||
|
||||
import com.yunhai.platform.appauth.AppAuthProperties;
|
||||
import com.yunhai.userbase.config.Config;
|
||||
import com.yunhai.userbase.entity.ApplicationInfo;
|
||||
import com.yunhai.userbase.repository.ApplicationInfoRepository;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 验签兜底端点:供其他业务服务在「共享 Redis 宕机且本地缓存也未命中」时直连获取某应用的密钥。<br><br>
|
||||
* 直接从 MySQL 读(绕过可能同宕的共享 Redis),是密钥的权威源;写入侧仍由
|
||||
* {@code SignKeyCacheService} 同步到 Redis。返回形状与 BasePlatform 读侧解析契约一致:<br>
|
||||
* {@code {"appKey":"100616","secret":"...","enabled":true}}。<br><br>
|
||||
* 解析优先级:<br>
|
||||
* 1) 本库 application_info(覆盖全部「已颁发」应用的实时密钥);<br>
|
||||
* 2) 配置式受信应用 {@code yh.app-auth.trusted-apps}(平台自身默认密钥,如 应用中心 100616,
|
||||
* 即便尚未落库也可解析,避免「默认 appKey 未建行」时此处返回 404 导致验签链路失败);<br>
|
||||
* 两者皆无 → 404。<br><br>
|
||||
* 注意:此端点返回的是应用密钥,必须仅内网可达(由部署网络隔离保障),切勿暴露到公网。
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping(Config.OPEN_API_PATH + "internal")
|
||||
public class SignKeyInternalController {
|
||||
|
||||
private final ApplicationInfoRepository applicationInfoRepository;
|
||||
private final AppAuthProperties appAuthProperties;
|
||||
|
||||
public SignKeyInternalController(ApplicationInfoRepository applicationInfoRepository,
|
||||
AppAuthProperties appAuthProperties) {
|
||||
this.applicationInfoRepository = applicationInfoRepository;
|
||||
this.appAuthProperties = appAuthProperties;
|
||||
}
|
||||
|
||||
@GetMapping("sign-key/{appId}")
|
||||
public ResponseEntity<Map<String, Object>> signKey(@PathVariable String appId) {
|
||||
Integer key;
|
||||
try {
|
||||
key = Integer.parseInt(appId.trim());
|
||||
} catch (NumberFormatException e) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
ApplicationInfo info = applicationInfoRepository.findByAppKey(key);
|
||||
if (info != null && info.getAppSecret() != null && !info.getAppSecret().trim().isEmpty()) {
|
||||
return ok(info.getAppKey() == null ? appId : String.valueOf(info.getAppKey()),
|
||||
info.getAppSecret());
|
||||
}
|
||||
// 库内无此应用密钥:回退到配置式受信应用(平台自身默认密钥 100616 等),
|
||||
// 避免「应用中心默认 appKey 未落库」时兜底查询返回 404。
|
||||
String cfgSecret = appAuthProperties.getTrustedApps().get(appId);
|
||||
if (cfgSecret != null && !cfgSecret.trim().isEmpty()) {
|
||||
return ok(appId, cfgSecret);
|
||||
}
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
|
||||
private static ResponseEntity<Map<String, Object>> ok(String appKey, String secret) {
|
||||
Map<String, Object> body = new LinkedHashMap<>();
|
||||
body.put("appKey", appKey);
|
||||
body.put("secret", secret);
|
||||
body.put("enabled", true);
|
||||
return ResponseEntity.ok(body);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user