Commit 92552f1ba4933c4b2049f8df99fb30ac01328d5a

Authored by 谭毅彬
1 parent 1e6b8a96

分布式环境激活码问题解决

Signed-off-by: TanYibin <5491541@qq.com>
ant-design-vue-jeecg/src/views/user/modules/SystemActivationModal.vue
... ... @@ -2,12 +2,7 @@
2 2 <div class="main">
3 3 <a-form-model class="user-layout-login" @keyup.enter.native="handleSubmit" :model="model" :rules="validatorRules">
4 4 <a-tabs :activeKey="customActiveKey" :tabBarStyle="{ textAlign: 'center', borderBottom: 'unset' }" @change="handleTabClick">
5   - <a-tab-pane key="tab1" tab="激活码授权">
6   - <!-- <login-account ref="alogin" @validateFail="validateFail" @success="requestSuccess" @fail="requestFailed"></login-account> -->
7   - </a-tab-pane>
8   - <!-- <a-tab-pane key="tab2" tab="手机号登录">
9   - <login-phone ref="plogin" @validateFail="validateFail" @success="requestSuccess" @fail="requestFailed"></login-phone>
10   - </a-tab-pane> -->
  5 + <a-tab-pane key="tab1" tab="激活码授权"/>
11 6 </a-tabs>
12 7 <a-form-model-item>
13 8 <a-input size="large" v-model="model.activationCode" autocomplete="false" placeholder="请输入激活码"/>
... ... @@ -18,12 +13,9 @@
18 13 </a-form-item>
19 14 </a-form-model>
20 15 <two-step-captcha v-if="requiredTwoStepCaptcha" :visible="stepCaptchaVisible" @success="stepCaptchaSuccess" @cancel="stepCaptchaCancel"></two-step-captcha>
21   - <!-- <login-select-tenant ref="loginSelect" @success="loginSelectOk"></login-select-tenant> -->
22   - <!-- <third-login ref="thirdLogin"></third-login>-->
23 16 </div>
24 17 </template>
25 18  
26   -
27 19 <script>
28 20 import Vue from 'vue'
29 21 import {ACCESS_TOKEN, ENCRYPTED_STRING} from '@/store/mutation-types'
... ... @@ -51,11 +43,6 @@ export default {
51 43 model: {
52 44 activationCode: ''
53 45 },
54   - validatorRules: {
55   - activationCode: [{
56   - required: true, message: '请输入激活码', validator: 'click'
57   - }],
58   - }
59 46 }
60 47 },
61 48 created() {
... ... @@ -79,27 +66,6 @@ export default {
79 66 }
80 67 })
81 68 },
82   - // 验证字段
83   - validateFields(arr, callback) {
84   - let promiseArray = []
85   - for (let item of arr) {
86   - let p = new Promise((resolve, reject) => {
87   - this.$refs['form'].validateField(item, (err) => {
88   - if (!err) {
89   - resolve();
90   - } else {
91   - reject(err);
92   - }
93   - })
94   - });
95   - promiseArray.push(p)
96   - }
97   - Promise.all(promiseArray).then(() => {
98   - callback()
99   - }).catch(err => {
100   - callback(err)
101   - })
102   - },
103 69 //验证激活码
104 70 handleSubmit() {
105 71 this.loginBtn = true;
... ... @@ -110,13 +76,11 @@ export default {
110 76 this.$router.push({path: "/user/login"});
111 77 this.$notification.success({
112 78 message: '激活成功,请重新登录',
113   - // description: `${timeFix()},欢迎回来`,
114 79 });
115 80 },
116 81 systemActivationSuccessError(message) {
117 82 this.$notification.error({
118 83 message: message,
119   - // description: `${timeFix()},欢迎回来`,
120 84 });
121 85 this.loginBtn = false;
122 86 },
... ...
huaheng-wms-core/src/main/java/org/jeecg/modules/system/controller/LoginController.java
1 1 package org.jeecg.modules.system.controller;
2 2  
3 3 import java.io.File;
  4 +import java.io.FileInputStream;
4 5 import java.io.FileOutputStream;
5 6 import java.io.IOException;
6 7 import java.util.ArrayList;
... ... @@ -14,6 +15,7 @@ import java.util.Map;
14 15 import javax.servlet.http.HttpServletRequest;
15 16 import javax.servlet.http.HttpServletResponse;
16 17  
  18 +import org.apache.commons.io.IOUtils;
17 19 import org.apache.shiro.SecurityUtils;
18 20 import org.jeecg.common.api.vo.Result;
19 21 import org.jeecg.common.constant.CacheConstant;
... ... @@ -41,8 +43,8 @@ import org.jeecg.modules.system.service.ISysTenantService;
41 43 import org.jeecg.modules.system.service.ISysUserService;
42 44 import org.jeecg.modules.system.util.RandImageUtil;
43 45 import org.jeecg.utils.HuahengJwtUtil;
  46 +import org.jeecg.utils.HuahengRedisUtil;
44 47 import org.jeecg.utils.StringUtils;
45   -import org.jeecg.utils.support.ApiAuthentication;
46 48 import org.jeecg.utils.support.SystemRSA256Key;
47 49 import org.springframework.beans.BeanUtils;
48 50 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -67,6 +69,7 @@ import com.auth0.jwt.JWT;
67 69 import com.auth0.jwt.JWTVerifier;
68 70 import com.auth0.jwt.algorithms.Algorithm;
69 71 import com.auth0.jwt.exceptions.JWTVerificationException;
  72 +import com.auth0.jwt.exceptions.TokenExpiredException;
70 73 import com.auth0.jwt.interfaces.DecodedJWT;
71 74 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
72 75 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
... ... @@ -111,6 +114,9 @@ public class LoginController {
111 114  
112 115 @Autowired
113 116 private BaseCommonService baseCommonService;
  117 +
  118 + @Autowired
  119 + private HuahengRedisUtil huahengRedisUtil;
114 120  
115 121 @ApiOperation("登录接口")
116 122 @RequestMapping(value = "/login", method = RequestMethod.POST)
... ... @@ -163,10 +169,10 @@ public class LoginController {
163 169 return result;
164 170 }
165 171 // 激活信息认证
166   -// result = HuahengJwtUtil.checkSystemActivationCode();
167   -// if (!result.isSuccess()) {
168   -// return result;
169   -// }
  172 + result = this.checkSystemActivationCode();
  173 + if (!result.isSuccess()) {
  174 + return result;
  175 + }
170 176 // 用户登录信息
171 177 result = userInfo(sysUser, warehouseCode);
172 178 // update-begin--Author:liusq Date:20210126 for:登录成功,删除redis中的验证码
... ... @@ -193,16 +199,15 @@ public class LoginController {
193 199 JWTVerifier verifier =
194 200 JWT.require(algorithm).withClaim("operator", HuahengJwtUtil.HUAHENG_SYSTEM_ID).withIssuer(HuahengJwtUtil.HUAHENG_SYSTEM_ID).build();
195 201 DecodedJWT jwt = verifier.verify(systemActivationModel.getActivationCode());
196   - new ApiAuthentication.ApiAuthenticationBuild().operator(jwt.getClaim("operator").asString()).audience(jwt.getAudience().get(0)).issuer(jwt.getIssuer())
197   - .issuedAt(jwt.getIssuedAt()).expireDateTime(jwt.getExpiresAt()).bulid();
198   -
199 202 // 验证通过写入文件
200 203 File file = new File(System.getProperties().getProperty("user.dir") + File.separatorChar + HuahengJwtUtil.SYSTEM_ACTIVATION_CODE_FILE_NAME);
201 204 outputStream = new FileOutputStream(file, false);
202 205 FileCopyUtils.copy(systemActivationModel.getActivationCode().getBytes(), outputStream);
  206 + // 验证通过写入Redis
  207 + huahengRedisUtil.setWithNoExpirationTime(HuahengJwtUtil.SYSTEM_ACTIVATION_CODE_KEY, systemActivationModel.getActivationCode());
203 208 } catch (JWTVerificationException e) {
204 209 log.error(e.getMessage());
205   - result.error500("激活失败");
  210 + result.error500("系统激活码无效");
206 211 return result;
207 212 } finally {
208 213 if (outputStream != null) {
... ... @@ -212,6 +217,58 @@ public class LoginController {
212 217 result.setMessage("激活成功");
213 218 return result;
214 219 }
  220 +
  221 + private Result<JSONObject> checkSystemActivationCode() throws IOException {
  222 + Result<JSONObject> result = new Result<JSONObject>();
  223 + FileInputStream inputStream = null;
  224 + FileOutputStream outputStream = null;
  225 + try {
  226 + String activationCode = null;
  227 + File file = new File(System.getProperties().getProperty("user.dir") + File.separatorChar + HuahengJwtUtil.SYSTEM_ACTIVATION_CODE_FILE_NAME);
  228 + if (file.exists()) {
  229 + inputStream = new FileInputStream(file);
  230 + activationCode = IOUtils.toString(inputStream, "utf-8");
  231 + }
  232 + String redisActivationCode = huahengRedisUtil.get(HuahengJwtUtil.SYSTEM_ACTIVATION_CODE_KEY, String.class);
  233 + // 文件激活码为空或redis中的激活码与文件中的激活码不一致,更新文件激活码
  234 + if (!StringUtils.isEmpty(redisActivationCode) && (StringUtils.isEmpty(activationCode) || !activationCode.equals(redisActivationCode))) {
  235 + activationCode = redisActivationCode;
  236 + outputStream = new FileOutputStream(file, false);
  237 + FileCopyUtils.copy(activationCode.getBytes(), outputStream);
  238 + }
  239 + if (StringUtils.isEmpty(activationCode)) {
  240 + result.setSuccess(false);
  241 + result.setCode(499);
  242 + result.setMessage("系统激活码无效");
  243 + return result;
  244 + }
  245 + // 验证激活码
  246 + Algorithm algorithm = Algorithm.RSA256(new SystemRSA256Key().getPublicKey(), new SystemRSA256Key().getPrivateKey());
  247 + JWTVerifier verifier =
  248 + JWT.require(algorithm).withClaim("operator", HuahengJwtUtil.HUAHENG_SYSTEM_ID).withIssuer(HuahengJwtUtil.HUAHENG_SYSTEM_ID).build();
  249 + DecodedJWT jwt = verifier.verify(activationCode);
  250 + // 如果redis中不存在激活码 则写入redis
  251 + if (StringUtils.isEmpty(redisActivationCode) || !redisActivationCode.equals(activationCode)) {
  252 + huahengRedisUtil.setWithNoExpirationTime(HuahengJwtUtil.SYSTEM_ACTIVATION_CODE_KEY, activationCode);
  253 + }
  254 + } catch (TokenExpiredException e) {
  255 + result.setSuccess(false);
  256 + result.setCode(499);
  257 + result.setMessage("系统激活码使用期限已到期");
  258 + } catch (Exception e) {
  259 + result.setSuccess(false);
  260 + result.setCode(499);
  261 + result.setMessage("系统激活码无效");
  262 + } finally {
  263 + if (inputStream != null) {
  264 + inputStream.close();
  265 + }
  266 + if (outputStream != null) {
  267 + outputStream.close();
  268 + }
  269 + }
  270 + return result;
  271 + }
215 272  
216 273 @Bean
217 274 public ResourceLoader createResourceLoader() {
... ...
huaheng-wms-core/src/main/java/org/jeecg/utils/HuahengJwtUtil.java
1 1 package org.jeecg.utils;
2 2  
3   -import java.io.File;
4   -import java.io.FileInputStream;
5   -import java.io.IOException;
6   -import java.io.InputStream;
7 3 import java.lang.reflect.Field;
8 4 import java.util.Arrays;
9 5 import java.util.Date;
... ... @@ -12,9 +8,7 @@ import java.util.UUID;
12 8  
13 9 import javax.servlet.http.HttpServletRequest;
14 10  
15   -import org.apache.commons.io.IOUtils;
16 11 import org.apache.shiro.SecurityUtils;
17   -import org.jeecg.common.api.vo.Result;
18 12 import org.jeecg.common.exception.JeecgBootException;
19 13 import org.jeecg.common.system.vo.LoginUser;
20 14 import org.jeecg.common.util.oConvertUtils;
... ... @@ -25,12 +19,10 @@ import org.jeecg.utils.support.SystemRSA256Key;
25 19 import org.springframework.stereotype.Component;
26 20 import org.springframework.util.CollectionUtils;
27 21  
28   -import com.alibaba.fastjson.JSONObject;
29 22 import com.auth0.jwt.JWT;
30 23 import com.auth0.jwt.JWTVerifier;
31 24 import com.auth0.jwt.algorithms.Algorithm;
32 25 import com.auth0.jwt.exceptions.JWTDecodeException;
33   -import com.auth0.jwt.exceptions.TokenExpiredException;
34 26 import com.auth0.jwt.interfaces.DecodedJWT;
35 27 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
36 28 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
... ... @@ -57,6 +49,8 @@ public class HuahengJwtUtil {
57 49 public static final String ALL_WAREHOUSE_CODE = "ALL_WAREHOUSE";
58 50  
59 51 public static final String SYSTEM_ACTIVATION_CODE_FILE_NAME = "ActivationCode.txt";
  52 +
  53 + public static final String SYSTEM_ACTIVATION_CODE_KEY = "ActivationCode";
60 54  
61 55 /**
62 56 * 根据request中的token获取用户账号
... ... @@ -266,36 +260,6 @@ public class HuahengJwtUtil {
266 260 }
267 261 }
268 262  
269   - public static Result<JSONObject> checkSystemActivationCode() throws IOException {
270   - Result<JSONObject> result = new Result<JSONObject>();
271   - InputStream inputStream = null;
272   - try {
273   - File file = new File(System.getProperties().getProperty("user.dir") + File.separatorChar + SYSTEM_ACTIVATION_CODE_FILE_NAME);
274   - inputStream = new FileInputStream(file);
275   - // 获得激活码
276   - String activationCode = IOUtils.toString(inputStream, "utf-8");
277   - Algorithm algorithm = Algorithm.RSA256(new SystemRSA256Key().getPublicKey(), new SystemRSA256Key().getPrivateKey());
278   - JWTVerifier verifier =
279   - JWT.require(algorithm).withClaim("operator", HuahengJwtUtil.HUAHENG_SYSTEM_ID).withIssuer(HuahengJwtUtil.HUAHENG_SYSTEM_ID).build();
280   - DecodedJWT jwt = verifier.verify(activationCode);
281   - new ApiAuthentication.ApiAuthenticationBuild().operator(jwt.getClaim("operator").asString()).audience(jwt.getAudience().get(0)).issuer(jwt.getIssuer())
282   - .issuedAt(jwt.getIssuedAt()).expireDateTime(jwt.getExpiresAt()).bulid();
283   - } catch (TokenExpiredException e) {
284   - result.setSuccess(false);
285   - result.setCode(499);
286   - result.setMessage("系统激活码使用期限已到期");
287   - } catch (Exception e) {
288   - result.setSuccess(false);
289   - result.setCode(499);
290   - result.setMessage("系统激活码无效");
291   - } finally {
292   - if (inputStream != null) {
293   - inputStream.close();
294   - }
295   - }
296   - return result;
297   - }
298   -
299 263 /**
300 264 * 生成第三方系统HTTP访问TOKEN
301 265 * @author TanYibin
... ...
huaheng-wms-core/src/main/java/org/jeecg/utils/HuahengRedisUtil.java
... ... @@ -99,6 +99,21 @@ public class HuahengRedisUtil {
99 99 log.error("操作缓存异常:key:{}", key, e);
100 100 }
101 101 }
  102 +
  103 + /**
  104 + * 设置key,value 无过期时间
  105 + * @author TanYibin
  106 + * @createDate 2023年2月8日
  107 + * @param key
  108 + * @param value
  109 + */
  110 + public void setWithNoExpirationTime(@Nonnull String key, @Nonnull Object value) {
  111 + try {
  112 + redisTemplate.opsForValue().set(key, toJson(value));
  113 + } catch (Exception e) {
  114 + log.error("操作缓存异常:key:{}", key, e);
  115 + }
  116 + }
102 117  
103 118 /**
104 119 * 设置key,value,过期时间
... ...
huaheng-wms-core/src/main/resources/application-dev.yml
... ... @@ -162,6 +162,7 @@ spring:
162 162 host: 127.0.0.1
163 163 port: 6379
164 164 password:
  165 + timeout: 5000 #超时时间ms
165 166 lettuce:
166 167 pool:
167 168 min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
... ...
huaheng-wms-core/src/main/resources/application-prod.yml
... ... @@ -162,6 +162,7 @@ spring:
162 162 host: 172.16.29.77
163 163 port: 6379
164 164 password: 123456
  165 + timeout: 5000 #超时时间ms
165 166 lettuce:
166 167 pool:
167 168 min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
... ...
huaheng-wms-core/src/main/resources/application-test.yml
... ... @@ -163,6 +163,7 @@ spring:
163 163 host: 172.16.29.77
164 164 port: 6379
165 165 password: 123456
  166 + timeout: 5000 #超时时间ms
166 167 lettuce:
167 168 pool:
168 169 min-idle: 0 #最小等待连接中的数量,设 0 为没有限制
... ...