Skip to content

Commit ca2ead7

Browse files
committed
从clientId调整为用户名+密码的登录方式
1 parent 9e70e7f commit ca2ead7

File tree

8 files changed

+116
-70
lines changed

8 files changed

+116
-70
lines changed

common/src/main/java/org/wowtools/hppt/common/server/LoginClientService.java

+50-19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616
*/
1717
public class LoginClientService {
1818

19+
public static final class Config {
20+
/**
21+
* 每行一条用户名和密码
22+
*/
23+
public ArrayList<String[]> users = new ArrayList<>();
24+
25+
/**
26+
* 密码重试次数
27+
*/
28+
public int passwordRetryNum;
29+
}
30+
1931

2032
public static final class Client {
2133
public final String clientId;
@@ -164,39 +176,58 @@ public interface ClientActiveWatcher {
164176
}
165177

166178

167-
private final String[] allowClientIds;
179+
private static final class ClientInfo {
180+
private final String user;
181+
private final String password;
182+
183+
public ClientInfo(String user, String password) {
184+
this.user = user;
185+
this.password = password;
186+
}
168187

169-
public LoginClientService(String[] allowClientIds) {
170-
this.allowClientIds = allowClientIds;
188+
private int passwordErrorNum;
171189
}
172190

173-
/**
174-
* @param allowClientIds 允许的clientId
175-
*/
176-
public LoginClientService(Collection<String> allowClientIds) {
177-
this.allowClientIds = new String[allowClientIds.size()];
178-
allowClientIds.toArray(this.allowClientIds);
191+
private final Map<String, ClientInfo> users;
192+
private final int passwordRetryNum;
193+
194+
public LoginClientService(Config config) {
195+
Map<String, ClientInfo> _users = new HashMap<>();
196+
for (String[] u : config.users) {
197+
_users.put(u[0], new ClientInfo(u[0], u[1]));
198+
}
199+
users = Map.copyOf(_users);
200+
passwordRetryNum = config.passwordRetryNum;
179201
}
180202

181203
/**
182204
* 传入的code能解密出客户端id,则登录成功
183205
*
184206
* @param code loginCode
185207
* @param clientActiveWatcher 用以观察客户端活跃状态的变化
186-
* @return 登录成功则返回Client对象,否则返回null
208+
* @return 登录成功则返回Client对象,否则抛出异常
187209
*/
188210
public Client login(String code, ClientActiveWatcher clientActiveWatcher) {
189-
byte[] bytesCode = BytesUtil.base642bytes(code);
190-
for (String clientId : allowClientIds) {
191-
AesCipherUtil aesCipherUtil = new AesCipherUtil(clientId, System.currentTimeMillis());
192-
try {
193-
if (new String(aesCipherUtil.descriptor.decrypt(bytesCode), StandardCharsets.UTF_8).equals(clientId)) {
194-
return new Client(clientId, aesCipherUtil, clientActiveWatcher);
195-
}
196-
} catch (Exception e) {
211+
String[] strs = code.split(" ", 2);
212+
String user = strs[0];
213+
String pwdCode = strs[1];
214+
ClientInfo clientInfo = users.get(user);
215+
if (null == clientInfo) {
216+
throw new RuntimeException("用户名不存在");
217+
}
218+
if (clientInfo.passwordErrorNum > passwordRetryNum) {
219+
throw new RuntimeException("多次登录失败,用户已锁定");
220+
}
221+
AesCipherUtil aesCipherUtil = new AesCipherUtil(clientInfo.password, System.currentTimeMillis());
222+
try {
223+
if (new String(aesCipherUtil.descriptor.decrypt(BytesUtil.base642bytes(pwdCode)), StandardCharsets.UTF_8).equals(clientInfo.password)) {
224+
clientInfo.passwordErrorNum = 0;
225+
return new Client(user, aesCipherUtil, clientActiveWatcher);
197226
}
227+
} catch (Exception ignored) {
198228
}
199-
return null;
229+
clientInfo.passwordErrorNum++;//理论上会有并发导致次数不准,可忽略
230+
throw new RuntimeException("密码不正确或对时时差过长");
200231
}
201232

202233
}

kafkademo/src/main/java/org/wowtools/hppt/kafkademo/ClientDemo.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ protected void sendBytesToServer(byte[] bytes) {
4747

4848
public static void main(String[] args) throws Exception{
4949
ScConfig cfg = new ScConfig();
50-
cfg.clientId = "user1";
50+
cfg.clientUser = "user1";
51+
cfg.clientPassword = "12345";
5152
ScConfig.Forward forward = new ScConfig.Forward();
5253
forward.localPort = 10022;
5354
forward.remoteHost = "wsl";

kafkademo/src/main/java/org/wowtools/hppt/kafkademo/ServerDemo.java

+5-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,11 @@ protected void doClose() throws Exception {
5757

5858
public static void main(String[] args) throws Exception{
5959
SsConfig cfg = new SsConfig();
60-
cfg.clientIds = new ArrayList<>();
61-
cfg.clientIds.add("user1");
60+
SsConfig.Client client = new SsConfig.Client();
61+
client.user = "user1";
62+
client.password = "12345";
63+
cfg.clients = new ArrayList<>(1);
64+
cfg.clients.add(client);
6265
ServerDemo server = new ServerDemo(cfg);
6366
server.init(cfg);
6467
server.sync();

run/src/main/java/org/wowtools/hppt/run/sc/common/ClientSessionService.java

+6-18
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ public abstract class ClientSessionService {
3838

3939
protected volatile boolean running = true;
4040

41-
private String reConnectCode;
4241

4342
/**
4443
* 当一个事件结束时发起的回调
@@ -139,17 +138,16 @@ protected void receiveServerBytes(byte[] bytes) throws Exception {
139138
break;
140139
case "login":
141140
String code = cmd[1];
142-
if (!"0".equals(code)) {
141+
if ("0".equals(code)) {
143142
noLogin = false;
144-
reConnectCode = new String(aesCipherUtil.descriptor.decrypt(BytesUtil.base642bytes(code)), StandardCharsets.UTF_8);
145143
log.info("登录成功");
146144
} else if (firstLoginErr) {
147145
firstLoginErr = false;
148-
log.warn("第一次登录失败 重试");
146+
log.warn("第一次登录失败 {} ,重试", code);
149147
Thread.sleep(10000);
150148
sendLoginCommand();
151149
} else {
152-
log.error("登录失败");
150+
log.error("登录失败 {}", code);
153151
System.exit(0);
154152
}
155153
break;
@@ -222,19 +220,9 @@ private Thread buildSendThread() {
222220

223221

224222
private void sendLoginCommand() {
225-
aesCipherUtil = new AesCipherUtil(config.clientId, System.currentTimeMillis() + dt);
226-
String loginCode = BytesUtil.bytes2base64(aesCipherUtil.encryptor.encrypt(config.clientId.getBytes(StandardCharsets.UTF_8)));
227-
sendBytesToServer(GridAesCipherUtil.encrypt(("login " + loginCode).getBytes(StandardCharsets.UTF_8)));
228-
}
229-
230-
/**
231-
* 发送重连接命令给服务端,当出现连接断开等问题时,可考虑重新建立连接后调用用此方法使得服务端知晓新旧CTX间的关系从而完成重连
232-
*/
233-
protected void sendReConnectCommand() {
234-
noLogin = true;
235-
long st = System.currentTimeMillis() + dt;
236-
String code = BytesUtil.bytes2base64(aesCipherUtil.encryptor.encrypt((reConnectCode + " " + st).getBytes(StandardCharsets.UTF_8)));
237-
sendBytesToServer(GridAesCipherUtil.encrypt(("reConnect " + code).getBytes(StandardCharsets.UTF_8)));
223+
aesCipherUtil = new AesCipherUtil(config.clientPassword, System.currentTimeMillis() + dt);
224+
String loginCode = BytesUtil.bytes2base64(aesCipherUtil.encryptor.encrypt(config.clientPassword.getBytes(StandardCharsets.UTF_8)));
225+
sendBytesToServer(GridAesCipherUtil.encrypt(("login " + config.clientUser + " " + loginCode).getBytes(StandardCharsets.UTF_8)));
238226
}
239227

240228

run/src/main/java/org/wowtools/hppt/run/sc/pojo/ScConfig.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -122,10 +122,13 @@ public static final class FileConfig {
122122
public String type;
123123

124124
/**
125-
* 客户端id,每个sc.jar用一个,不要重复
125+
* 客户端用户名,每个sc进程用一个,不要重复
126126
*/
127-
public String clientId;
128-
127+
public String clientUser;
128+
/**
129+
* 客户端密码
130+
*/
131+
public String clientPassword;
129132

130133
/**
131134
* 向服务端发数据请求体的字节数最大值

run/src/main/java/org/wowtools/hppt/run/ss/common/ServerSessionService.java

+28-23
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,12 @@ public void toActivity() {
5353

5454
public ServerSessionService(SsConfig ssConfig) {
5555
this.ssConfig = ssConfig;
56-
loginClientService = new LoginClientService(ssConfig.clientIds);
56+
LoginClientService.Config lConfig = new LoginClientService.Config();
57+
for (SsConfig.Client client : ssConfig.clients) {
58+
lConfig.users.add(new String[]{client.user, client.password});
59+
}
60+
lConfig.passwordRetryNum = ssConfig.passwordRetryNum;
61+
loginClientService = new LoginClientService(lConfig);
5762
serverSessionManager = SsUtil.createServerSessionManagerBuilder(ssConfig).build();
5863
}
5964

@@ -102,31 +107,31 @@ public void receiveClientBytes(CTX ctx, byte[] bytes) {
102107
LoginClientService.Client client;
103108
String loginCode = cmd[1];
104109
log.debug("请求login {}", loginCode);
105-
client = loginClientService.login(loginCode, clientCell.clientActiveWatcher);
106-
if (client == null) {
107-
log.warn("登录失败 {}", loginCode);
108-
byte[] login = ("login 0").getBytes(StandardCharsets.UTF_8);
109-
login = GridAesCipherUtil.encrypt(login);
110-
sendBytesToClient(ctx, login);
111-
} else {
112-
clientCell.client = client;
113-
clientCell.ctx = ctx;
114-
synchronized (ctxClientCellMap) {
115-
ctxClientCellMap.forEach((oldCtx, oldCell) -> {
116-
if (oldCell.client.clientId.equals(client.clientId)) {
117-
log.info("重复登录,移除旧client {} {}", oldCell.client.clientId, ctx);
118-
removeCtx(oldCtx);
119-
}
120-
});
121-
ctxClientCellMap.put(ctx, clientCell);
122-
}
123-
log.info("客户端接入成功 {}", clientCell.client.clientId);
124-
startSendThread(clientCell);
125-
String code = BytesUtil.bytes2base64(client.aesCipherUtil.encryptor.encrypt(clientCell.reConnectToken.getBytes(StandardCharsets.UTF_8)));
126-
byte[] login = ("login " + code).getBytes(StandardCharsets.UTF_8);
110+
try {
111+
client = loginClientService.login(loginCode, clientCell.clientActiveWatcher);
112+
} catch (Exception e) {
113+
log.warn("登录失败 {} {}", loginCode, e.getMessage());
114+
byte[] login = ("login " + e.getMessage()).getBytes(StandardCharsets.UTF_8);
127115
login = GridAesCipherUtil.encrypt(login);
128116
sendBytesToClient(ctx, login);
117+
break;
118+
}
119+
clientCell.client = client;
120+
clientCell.ctx = ctx;
121+
synchronized (ctxClientCellMap) {
122+
ctxClientCellMap.forEach((oldCtx, oldCell) -> {
123+
if (oldCell.client.clientId.equals(client.clientId)) {
124+
log.info("重复登录,移除旧client {} {}", oldCell.client.clientId, ctx);
125+
removeCtx(oldCtx);
126+
}
127+
});
128+
ctxClientCellMap.put(ctx, clientCell);
129129
}
130+
log.info("客户端接入成功 {}", clientCell.client.clientId);
131+
startSendThread(clientCell);
132+
byte[] login = ("login 0").getBytes(StandardCharsets.UTF_8);
133+
login = GridAesCipherUtil.encrypt(login);
134+
sendBytesToClient(ctx, login);
130135
break;
131136
case "reConnect":
132137
byte[] base64Bytes = BytesUtil.base642bytes(cmd[1]);

run/src/main/java/org/wowtools/hppt/run/ss/pojo/SsConfig.java

+18-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
44
import org.wowtools.hppt.common.util.CommonConfig;
5-
import org.wowtools.hppt.run.sc.pojo.ScConfig;
65

76
import java.util.ArrayList;
87

@@ -41,8 +40,24 @@ public class SsConfig extends CommonConfig {
4140
/**
4241
* 允许的客户端
4342
*/
44-
public ArrayList<String> clientIds;
43+
public ArrayList<Client> clients;
4544

45+
/**
46+
* 密码最大尝试次数,超过次数没输入对会锁定账号直至重启
47+
*/
48+
public int passwordRetryNum = 5;
49+
50+
public static final class Client {
51+
/**
52+
* 用户名
53+
*/
54+
public String user;
55+
56+
/**
57+
* 密码
58+
*/
59+
public String password;
60+
}
4661

4762
public static final class PostConfig {
4863
/**
@@ -100,7 +115,7 @@ public static final class RHpptConfig {
100115

101116
public RHpptConfig rhppt = new RHpptConfig();
102117

103-
public static final class RPostConfig{
118+
public static final class RPostConfig {
104119
/**
105120
* 服务端http地址,可以填nginx转发过的地址
106121
*/

run/src/main/java/org/wowtools/hppt/run/ss/post/PostServerSessionService.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class PostServerSessionService extends ServerSessionService<PostCtx> {
2727

2828
public PostServerSessionService(SsConfig ssConfig) throws Exception {
2929
super(ssConfig);
30-
ctxMap = LruCache.buildCache(ssConfig.clientIds.size() * 2, ssConfig.clientIds.size() * 2);
30+
ctxMap = LruCache.buildCache(ssConfig.clients.size() * 2, ssConfig.clients.size() * 2);
3131
}
3232

3333
@Override

0 commit comments

Comments
 (0)