|
@@ -0,0 +1,230 @@
|
|
|
+package org.springblade.system.user.thirdparty;
|
|
|
+
|
|
|
+
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
+import com.alibaba.fastjson.JSONObject;
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
+import org.apache.commons.lang.StringUtils;
|
|
|
+import org.apache.http.Consts;
|
|
|
+import org.apache.http.HttpResponse;
|
|
|
+import org.apache.http.NameValuePair;
|
|
|
+import org.apache.http.client.HttpClient;
|
|
|
+import org.apache.http.client.entity.UrlEncodedFormEntity;
|
|
|
+import org.apache.http.client.methods.HttpPost;
|
|
|
+import org.apache.http.impl.client.HttpClientBuilder;
|
|
|
+import org.apache.http.message.BasicNameValuePair;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
+import org.springblade.common.utils.SnowFlakeUtil;
|
|
|
+import org.springblade.core.log.exception.ServiceException;
|
|
|
+import org.springblade.core.tool.api.R;
|
|
|
+import org.springblade.core.tool.utils.DigestUtil;
|
|
|
+import org.springblade.system.entity.AuthClient;
|
|
|
+import org.springblade.system.user.bean.GetTokenDTO;
|
|
|
+import org.springblade.system.user.bean.TripartiteSecretKeyBean;
|
|
|
+import org.springblade.system.user.entity.User;
|
|
|
+import org.springblade.system.user.util.RsaUtils;
|
|
|
+import org.springblade.system.user.util.TokenBucket;
|
|
|
+import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
|
|
+import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.util.*;
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * 白马三方接口相关
|
|
|
+ *
|
|
|
+ * @author liuyc
|
|
|
+ * @date 2023年11月14日15:15:42
|
|
|
+ */
|
|
|
+@RestController
|
|
|
+@AllArgsConstructor
|
|
|
+@RequestMapping("/bm")
|
|
|
+public class ThirdPartySystemApi {
|
|
|
+
|
|
|
+ private final JdbcTemplate jdbcTemplate;
|
|
|
+ private static final Logger logger = LoggerFactory.getLogger(ThirdPartySystemApi.class);
|
|
|
+ private final TokenBucket tokenBucket = new TokenBucket(5, 5, 60000); /*令牌桶=60秒5次*/
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取公钥信息
|
|
|
+ */
|
|
|
+ @GetMapping("/getPublicKeyAndUUIDByAppKey")
|
|
|
+ public Map<String, Object> getPublicKeyAndUUID(@RequestParam String appKey) {
|
|
|
+ if (!tokenBucket.tryConsume()) {
|
|
|
+ throw new ServiceException("请求频率超过限制,请稍后再试");
|
|
|
+ }
|
|
|
+ if (StringUtils.isEmpty(appKey)) {
|
|
|
+ throw new ServiceException("appKey不能为空");
|
|
|
+ }
|
|
|
+ if (!isValidAppKey(appKey)) {
|
|
|
+ throw new ServiceException("appKey验证失败");
|
|
|
+ }
|
|
|
+
|
|
|
+ /*创建秘钥对*/
|
|
|
+ Map<String, String> keyPair = RsaUtils.createKeyPair();
|
|
|
+ String pk = keyPair.get("pk");
|
|
|
+ String sk = keyPair.get("sk");
|
|
|
+ Long uuid = SnowFlakeUtil.getId();
|
|
|
+
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
+ try {
|
|
|
+ insertKeyPairIntoDatabase(uuid, pk, sk, appKey);
|
|
|
+ } catch (Exception e) {
|
|
|
+ resultMap.put("uuid", null);
|
|
|
+ resultMap.put("pk", null);
|
|
|
+ resultMap.put("code", 400);
|
|
|
+ resultMap.put("msg", e.getMessage());
|
|
|
+ return resultMap;
|
|
|
+ }
|
|
|
+ resultMap.put("uuid", uuid);
|
|
|
+ resultMap.put("pk", pk);
|
|
|
+ resultMap.put("code", 200);
|
|
|
+ resultMap.put("msg", "操作成功");
|
|
|
+ return resultMap;
|
|
|
+ }
|
|
|
+
|
|
|
+ private boolean isValidAppKey(String appKey) {
|
|
|
+ List<AuthClient> bladeClients = jdbcTemplate.query(
|
|
|
+ "SELECT (1) FROM blade_client WHERE client_id = ?",
|
|
|
+ new Object[]{appKey},
|
|
|
+ new BeanPropertyRowMapper<>(AuthClient.class)
|
|
|
+ );
|
|
|
+ return !bladeClients.isEmpty();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void insertKeyPairIntoDatabase(Long uuid, String pk, String sk, String appKey) {
|
|
|
+ jdbcTemplate.update(
|
|
|
+ "INSERT INTO a_tripartite_secret_key (uuid, public_key, private_key, create_time, app_key) VALUES (?, ?, ?, ?, ?)",
|
|
|
+ uuid, pk, sk, new Date(), appKey
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取token
|
|
|
+ */
|
|
|
+ @PostMapping("/getTokenByCondition")
|
|
|
+ public R<Object> getToken(@RequestBody GetTokenDTO dto) {
|
|
|
+ if (dto.getUuid().isEmpty() || dto.getIdcard().isEmpty()) {
|
|
|
+ throw new ServiceException("入参不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ /*根据uuid获取私钥*/
|
|
|
+ TripartiteSecretKeyBean tripartiteSecretKey = jdbcTemplate.query(
|
|
|
+ "SELECT private_key FROM a_tripartite_secret_key WHERE uuid = ?",
|
|
|
+ new Object[]{dto.getUuid()},
|
|
|
+ new BeanPropertyRowMapper<>(TripartiteSecretKeyBean.class))
|
|
|
+ .stream().findAny().orElse(null);
|
|
|
+
|
|
|
+ if (tripartiteSecretKey != null && StringUtils.isNotEmpty(tripartiteSecretKey.getPrivateKey())) {
|
|
|
+ /*解密密钥对获取身份证信息*/
|
|
|
+ String privateKey = tripartiteSecretKey.getPrivateKey();
|
|
|
+ String decryptedIdCard = RsaUtils.decryptWithSk(dto.getIdcard(), privateKey);
|
|
|
+
|
|
|
+ /*根据身份证获取用户token*/
|
|
|
+ if (StringUtils.isNotEmpty(decryptedIdCard)) {
|
|
|
+ List<User> users = jdbcTemplate.query(
|
|
|
+ "SELECT account, plaintext_password FROM blade_user WHERE is_deleted = 0 AND status = 1 AND id_number = ?",
|
|
|
+ new Object[]{decryptedIdCard},
|
|
|
+ new BeanPropertyRowMapper<>(User.class)
|
|
|
+ );
|
|
|
+
|
|
|
+ if (users.size() > 0 && users.size() != 1) {
|
|
|
+ throw new ServiceException("获取用户信息异常");
|
|
|
+ } else if (users.size() == 1) {
|
|
|
+ User user = users.get(0);
|
|
|
+ HttpClient httpClient = HttpClientBuilder.create().build();
|
|
|
+ HttpPost httpPost = new HttpPost("http://127.0.0.1:8090/blade-auth/oauth/token");
|
|
|
+ httpPost.setHeader("Authorization", "Basic Y2xpZW50OmNsaWVudF9zZWNyZXQ=");
|
|
|
+ httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
|
|
|
+ httpPost.setHeader("Tenant-Id", "000000");
|
|
|
+ List<NameValuePair> params = new ArrayList<NameValuePair>();
|
|
|
+ params.add(new BasicNameValuePair("grant_type", "password"));
|
|
|
+ params.add(new BasicNameValuePair("username", user.getAccount()));
|
|
|
+
|
|
|
+ /*密码加密*/
|
|
|
+ String plaintextPassword = user.getPlaintextPassword();
|
|
|
+ String hex = DigestUtil.md5Hex(plaintextPassword);
|
|
|
+
|
|
|
+ params.add(new BasicNameValuePair("password", hex));
|
|
|
+ params.add(new BasicNameValuePair("scope", "all"));
|
|
|
+ params.add(new BasicNameValuePair("tenantId", "000000"));
|
|
|
+ httpPost.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
|
|
|
+
|
|
|
+ try {
|
|
|
+ HttpResponse httpResponse = httpClient.execute(httpPost);
|
|
|
+ InputStream inputStream = httpResponse.getEntity().getContent();
|
|
|
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
|
+ byte[] buffer = new byte[1024];
|
|
|
+ int index;
|
|
|
+ while ((index = inputStream.read(buffer)) != -1) {
|
|
|
+ outputStream.write(buffer, 0, index);
|
|
|
+ }
|
|
|
+
|
|
|
+ JSONObject jsonObject = JSON.parseObject(outputStream.toString());
|
|
|
+ Object accessToken = jsonObject.get("access_token");
|
|
|
+ if (accessToken != null) {
|
|
|
+ Object expiresIn = jsonObject.get("expires_in");
|
|
|
+ int minutes = 0;
|
|
|
+ if (expiresIn instanceof Integer) {
|
|
|
+ int seconds = (Integer) expiresIn;
|
|
|
+ minutes = seconds / 60;
|
|
|
+ }
|
|
|
+ Map<String, Object> resultMap = new HashMap<>();
|
|
|
+ resultMap.put("access_token", accessToken);
|
|
|
+ resultMap.put("expires_in", minutes);
|
|
|
+ return R.data(200, resultMap, "操作成功");
|
|
|
+
|
|
|
+ } else {
|
|
|
+ return R.data(400, null, "解析异常,token为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ return R.data(500, null, e.getMessage());
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ return R.data(400, null, "未获取到对应的用户信息");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return R.data(451, null, "未获取到对应的私钥信息");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 定时删除昨天及之前的密钥对信息
|
|
|
+ */
|
|
|
+ @Scheduled(cron = "0 0 1 * * ?") //每天凌晨1点执行
|
|
|
+ public void delTripartiteSecretKeyInfos() {
|
|
|
+ //获取昨天及之前的日期
|
|
|
+ Calendar calendar = Calendar.getInstance();
|
|
|
+ calendar.add(Calendar.DAY_OF_MONTH, -1);
|
|
|
+ Date yesterday = calendar.getTime();
|
|
|
+
|
|
|
+ //执行删除操作
|
|
|
+ String sql = "DELETE FROM a_tripartite_secret_key WHERE create_time <= ?";
|
|
|
+ int deletedRows = jdbcTemplate.update(sql, yesterday);
|
|
|
+
|
|
|
+ logger.info("执行方法【delTripartiteSecretKeyInfos】,删除 " + deletedRows + " 条密钥对信息成功...");
|
|
|
+ }
|
|
|
+
|
|
|
+ /*public static void main(String[] args) {
|
|
|
+ //公钥
|
|
|
+ String pk = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKHbUex3gTpQsaGgMtfWWDwE6LrCETLr8c588diQYHSdVEYbU6A1RnKioGIxGer6G6Cb/81wn6s9Zx833uNf6VkCAwEAAQ==";
|
|
|
+
|
|
|
+ //字符串
|
|
|
+ String idcard = "100136199809011400";
|
|
|
+
|
|
|
+ //使用公钥加密
|
|
|
+ String encryptedIdCard = RsaUtils.encryptWithPk(idcard, pk);
|
|
|
+
|
|
|
+ System.out.println("Encrypted Id Card: " + encryptedIdCard);
|
|
|
+ }*/
|
|
|
+
|
|
|
+}
|
|
|
+
|