|
16 | 16 | */
|
17 | 17 | public class LoginClientService {
|
18 | 18 |
|
| 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 | + |
19 | 31 |
|
20 | 32 | public static final class Client {
|
21 | 33 | public final String clientId;
|
@@ -164,39 +176,58 @@ public interface ClientActiveWatcher {
|
164 | 176 | }
|
165 | 177 |
|
166 | 178 |
|
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 | + } |
168 | 187 |
|
169 |
| - public LoginClientService(String[] allowClientIds) { |
170 |
| - this.allowClientIds = allowClientIds; |
| 188 | + private int passwordErrorNum; |
171 | 189 | }
|
172 | 190 |
|
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; |
179 | 201 | }
|
180 | 202 |
|
181 | 203 | /**
|
182 | 204 | * 传入的code能解密出客户端id,则登录成功
|
183 | 205 | *
|
184 | 206 | * @param code loginCode
|
185 | 207 | * @param clientActiveWatcher 用以观察客户端活跃状态的变化
|
186 |
| - * @return 登录成功则返回Client对象,否则返回null |
| 208 | + * @return 登录成功则返回Client对象,否则抛出异常 |
187 | 209 | */
|
188 | 210 | 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); |
197 | 226 | }
|
| 227 | + } catch (Exception ignored) { |
198 | 228 | }
|
199 |
| - return null; |
| 229 | + clientInfo.passwordErrorNum++;//理论上会有并发导致次数不准,可忽略 |
| 230 | + throw new RuntimeException("密码不正确或对时时差过长"); |
200 | 231 | }
|
201 | 232 |
|
202 | 233 | }
|
0 commit comments