添加了指令

基本实现了注册接口
(数据库有严重的访问冲突问题)
This commit is contained in:
张宇衡 2022-12-03 01:49:55 +08:00
parent dcbe37cf91
commit 3931731cb2
37 changed files with 305 additions and 97 deletions

1
.gitignore vendored
View File

@ -97,6 +97,7 @@ $RECYCLE.BIN/
*.lnk
target/
test-setver/
pom.xml.tag
pom.xml.releaseBackup

View File

@ -3,5 +3,28 @@
## 功能介绍 TODO List
### 外置登录服务器
- [x] 用户登录
- [x] 刷新令牌
- [x] 验证令牌
- [x] 吊销令牌
- [x] 客户端进入服务器
- [x] 服务端验证客户端
- [x] 查询角色属性
- [x] 按名称批量查询
- [ ] 材质(皮肤)上传/删除
- [ ] 多角色支持
### Web服务器
- [x] 用户注册
- [ ] 邀请码生成
- [ ] 实名认证白名单
- [ ] 用户管理
- [ ] 用户登录
- [ ] 密码修改
- [ ] 用户信息修改
- [ ] 材质(皮肤)上传/删除
- [ ] 多角色创建删除

31
pom.xml
View File

@ -45,6 +45,26 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<configuration>
<target>
<echo message="*******************install*******************" />
<copy file="${project.build.directory}/${project.build.finalName}.jar" tofile="${basedir}/test-server/plugins/${project.build.finalName}.jar" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
@ -75,24 +95,27 @@
<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.39.4.1</version>
<version>3.40.0.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.19</version>
<version>2.0.20</version>
</dependency>
<!--JavaMail基本包-->
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<!--邮件发送的扩展包-->
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.directory.studio</groupId>
<artifactId>org.apache.commons.codec</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
</project>

View File

@ -149,8 +149,6 @@ public class ConfigManager {
}
public void setSignaturePublicKey(String signaturePublicKey) {
m_SignaturePublicKey = signaturePublicKey;
config.set("Yggdrasil.SignaturePublicKey", signaturePublicKey);
plugin.saveConfig();
}
public void setPublicKeyFileName(String signaturePublicKey) {
m_RsaPublicKeyFileName = signaturePublicKey;
@ -166,8 +164,6 @@ public class ConfigManager {
}
public void setSignaturePrivateKey(String signaturePrivateKey) {
m_SignaturePrivateKey = signaturePrivateKey;
config.set("Yggdrasil.SignaturePrivateKey", signaturePrivateKey);
plugin.saveConfig();
}
public void setPrivateKeyFileName(String signaturePrivateKey) {
m_RsaPrivateKeyFileName = signaturePrivateKey;

View File

@ -1,6 +1,7 @@
package site.deercloud.identityverification.Controller;
import site.deercloud.identityverification.HttpServer.model.EmailCode;
import site.deercloud.identityverification.IdentityVerification;
import java.util.Map;
import java.util.Optional;
@ -22,10 +23,12 @@ public class EmailCodeCache {
}
public static boolean isEmailCodeExpired(String email) {
if (IdentityVerification.getInstance().getConfigManager().getDebug()) return false;
return getEmailCode(email).map(EmailCode::isExpired).orElse(true);
}
public static boolean isEmailCodeValid(String email, String code) {
if (IdentityVerification.getInstance().getConfigManager().getDebug()) return true;
return getEmailCode(email).map(emailCode -> emailCode.code.equals(code)).orElse(false);
}
}

View File

@ -28,7 +28,7 @@ public class InviteCodeManager {
if (sender.isOp()) {
Connection connection = SqlManager.getConnection();
try {
User console = UserDAO.selectByEmail(connection, "console@mc.com");
User console = UserDAO.selectByUuid(connection, ((Player) sender).getUniqueId().toString());
InviteCodeDAO.insert(connection, code, console.uuid, false, 0);
} catch (SQLException e) {
throw new RuntimeException(e);

View File

@ -8,6 +8,7 @@ import site.deercloud.identityverification.Utils.MyLogger;
import java.io.IOException;
import java.util.Map;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
import static site.deercloud.identityverification.Utils.Utils.*;
@ -21,7 +22,7 @@ public class Ban implements HttpHandler {
return;
}
JSONObject jsonObject = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject jsonObject = getBody(exchange);
String uuid = jsonObject.getString("uuid");
String reason = jsonObject.getString("reason");
Integer time = jsonObject.getInteger("time");

View File

@ -13,6 +13,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getQuery;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
import static site.deercloud.identityverification.SQLite.SqlManager.getConnection;
import static site.deercloud.identityverification.Utils.Utils.*;
@ -28,8 +29,7 @@ public class GetInviter implements HttpHandler {
return;
}
String query = exchange.getRequestURI().getQuery();
Map<String, String> params = ParseQueryString(query);
Map<String, String> params = getQuery(exchange);
Connection connection = getConnection();
String uuid = params.get("uuid");

View File

@ -14,6 +14,9 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBodyArray;
public class GetProfiles implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
@ -23,7 +26,7 @@ public class GetProfiles implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
JSONArray profiles_json = JSONArray.parseArray(exchange.getRequestBody().toString());
JSONArray profiles_json = getBodyArray(exchange);
if (profiles_json.size() > 5) {
Response.success_no_content(exchange);
return;

View File

@ -13,6 +13,7 @@ import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
public class Login implements HttpHandler {
@ -25,7 +26,7 @@ public class Login implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
JSONObject request = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject request = getBody(exchange);
String username = request.getString("username");
String password = request.getString("password");

View File

@ -10,9 +10,10 @@ import site.deercloud.identityverification.Utils.RandomCode;
import java.io.IOException;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
public class SendEmailCode implements HttpHandler {
public class GetEmailCode implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
try {
@ -21,7 +22,7 @@ public class SendEmailCode implements HttpHandler {
jsonResponse(exchange, 405, "Method Not Allowed", null);
return;
}
JSONObject request = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject request = getBody(exchange);
String email = request.getString("email");
if (!EmailCodeCache.isEmailCodeExpired(email)) {
@ -30,7 +31,10 @@ public class SendEmailCode implements HttpHandler {
}
String code = RandomCode.NewCodeOnlyNumber(6);
EmailSender.sendCodeEmail(email, code);
if(!EmailSender.sendCodeEmail(email, code)) {
jsonResponse(exchange, 500, "邮件发送失败!", null);
return;
}
EmailCodeCache.addEmailCode(email, code);
jsonResponse(exchange, 200, "发送成功,请在五分钟内完成注册。", null);

View File

@ -8,6 +8,7 @@ import site.deercloud.identityverification.Utils.MyLogger;
import java.io.IOException;
import java.util.Map;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getQuery;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
import static site.deercloud.identityverification.Utils.Utils.*;
@ -21,8 +22,7 @@ public class GetOnlineProfile implements HttpHandler {
return;
}
String query = exchange.getRequestURI().getQuery();
Map<String, String> params = ParseQueryString(query);
Map<String, String> params = getQuery(exchange);
String name = params.get("name");
String UUID = getUUIDFromRemote(name);

View File

@ -3,19 +3,24 @@ package site.deercloud.identityverification.HttpServer.Api.Register;
import com.alibaba.fastjson.JSONObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import org.apache.commons.lang.StringEscapeUtils;
import site.deercloud.identityverification.Controller.EmailCodeCache;
import site.deercloud.identityverification.HttpServer.model.Profile;
import site.deercloud.identityverification.HttpServer.model.Texture;
import site.deercloud.identityverification.HttpServer.model.User;
import site.deercloud.identityverification.IdentityVerification;
import site.deercloud.identityverification.SQLite.InviteCodeDAO;
import site.deercloud.identityverification.SQLite.InviteRelationDAO;
import site.deercloud.identityverification.SQLite.ProfileDAO;
import site.deercloud.identityverification.SQLite.UserDAO;
import site.deercloud.identityverification.Utils.MyLogger;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.util.UUID;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
import static site.deercloud.identityverification.SQLite.SqlManager.getConnection;
import static site.deercloud.identityverification.Utils.Utils.*;
@ -31,7 +36,7 @@ public class Registration implements HttpHandler {
return;
}
JSONObject jsonObject = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject jsonObject = getBody(exchange);
String email = jsonObject.getString("email");
String password = jsonObject.getString("password");
@ -41,18 +46,21 @@ public class Registration implements HttpHandler {
String profile_name = jsonObject.getString("profile_name");
// 验证邮箱验证码
if (EmailCodeCache.isEmailCodeExpired(email)) {
jsonResponse(exchange, 500, "验证码无效,请重新获取。", null);
jsonResponse(exchange, 500, "邮箱验证码无效,请重新获取。", null);
return;
}
if (!EmailCodeCache.isEmailCodeValid(email, active_code)) {
jsonResponse(exchange, 500, "验证码错误!", null);
return;
}
// 验证昵称可用性
if (getUUIDFromRemote(profile_name) != null){
jsonResponse(exchange, 400, "此昵称已有正版玩家使用为避免ID碰撞请改名。", null);
return;
}
// 验证邀请码可用性
Connection connection = getConnection();
if (!InviteCodeDAO.isValid(connection, inviteCode)) {
jsonResponse(exchange, 400, "邀请码不存在或已被使用!", null);
@ -62,15 +70,20 @@ public class Registration implements HttpHandler {
String inviteCodeOwner = InviteCodeDAO.getInviterUUID(connection, inviteCode);
// 创建邀请关系
InviteRelationDAO.insert(connection, new_uuid, inviteCodeOwner, System.currentTimeMillis());
MyLogger.debug("邀请关系已建立,邀请人:" + inviteCodeOwner + ",被邀请人:" + new_uuid);
// 标记邀请码已使用
InviteCodeDAO.setUsed(connection, inviteCode, true, System.currentTimeMillis());
MyLogger.debug("邀请码已标记为已使用:" + inviteCode);
// 创建用户
User user = new User();
user.uuid = new_uuid;
user.email = email;
user.password = password;
UserDAO.insert(connection, user);
MyLogger.debug("用户注册成功:" + user.uuid);
// 创建一个默认角色
Profile profile = new Profile();
profile.name = profile_name;
profile.uuid = UUID.randomUUID().toString();
@ -79,6 +92,7 @@ public class Registration implements HttpHandler {
profile.textures = texture.serialWithBase64();
profile.textures_signature = texture.sign();
ProfileDAO.insert(connection, profile);
MyLogger.debug("角色创建成功:" + profile.uuid);
jsonResponse(exchange, 200, "注册成功!", null);
} catch (Exception e) {

View File

@ -15,9 +15,8 @@ import java.sql.SQLException;
import java.util.Map;
import java.util.UUID;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getQuery;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
import static site.deercloud.identityverification.Utils.Utils.ParseQueryString;
public class VerifyCode implements HttpHandler {
@Override
public void handle(HttpExchange exchange){
@ -27,8 +26,7 @@ public class VerifyCode implements HttpHandler {
jsonResponse(exchange, 405, "Method Not Allowed", null);
return;
}
String query = exchange.getRequestURI().getQuery();
Map<String, String> params = ParseQueryString(query);
Map<String, String> params = getQuery(exchange);
String code = params.get("code");
Connection conn = SqlManager.getConnection();

View File

@ -14,6 +14,7 @@ import java.io.IOException;
import java.sql.Connection;
import java.util.Objects;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.jsonResponse;
import static site.deercloud.identityverification.SQLite.SqlManager.getConnection;
import static site.deercloud.identityverification.Utils.Utils.*;
@ -27,7 +28,7 @@ public class SignWhiteList implements HttpHandler {
jsonResponse(exchange, 405, "Method Not Allowed", null);
return;
}
JSONObject jsonObject = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject jsonObject = getBody(exchange);
Connection connection = getConnection();
String id = jsonObject.getString("id"); // 身份证实名认证用

View File

@ -1,8 +1,10 @@
package site.deercloud.identityverification.HttpServer;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpServer;
import site.deercloud.identityverification.HttpServer.Api.Register.GetEmailCode;
import site.deercloud.identityverification.HttpServer.Api.Register.GetOnlineProfile;
import site.deercloud.identityverification.HttpServer.Api.Register.Registration;
import site.deercloud.identityverification.HttpServer.Api.Register.VerifyCode;
@ -18,8 +20,15 @@ import site.deercloud.identityverification.IdentityVerification;
import site.deercloud.identityverification.Controller.ConfigManager;
import site.deercloud.identityverification.Utils.MyLogger;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@ -54,6 +63,8 @@ public class HttpServerManager {
webServer.createContext("/api/getInviter", new GetInviter());
// 登记白名单
webServer.createContext("/api/signWhiteList", new SignWhiteList());
// 获取邮箱验证码
webServer.createContext("/api/getEmailCode", new GetEmailCode());
// Yggdrasil API 元数据
yagServer.createContext("/", new MetaData());
@ -110,6 +121,49 @@ public class HttpServerManager {
exchange.getResponseBody().close();
}
public static JSONObject getBody(HttpExchange exchange) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(exchange.getRequestBody(), "utf-8"));
StringBuilder requestBodyContent = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
requestBodyContent.append(line);
}
MyLogger.debug(requestBodyContent.toString());
return JSONObject.parseObject(requestBodyContent.toString());
}
public static JSONArray getBodyArray(HttpExchange exchange) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(exchange.getRequestBody(), "utf-8"));
StringBuilder requestBodyContent = new StringBuilder();
String line = null;
while ((line = bufferedReader.readLine()) != null) {
requestBodyContent.append(line);
}
MyLogger.debug(requestBodyContent.toString());
return JSONObject.parseArray(requestBodyContent.toString());
}
public static Map<String,String> getQuery(HttpExchange exchange){
String query_string = exchange.getRequestURI().getQuery();
Map<String,String> result = new HashMap<>();
if(query_string== null || query_string.trim().length() == 0) {
return result;
}
final String[] items = query_string.split("&");
Arrays.stream(items).forEach(item ->{
final String[] keyAndVal = item.split("=");
if( keyAndVal.length == 2) {
try{
final String key = URLDecoder.decode( keyAndVal[0],"utf8");
final String val = URLDecoder.decode( keyAndVal[1],"utf8");
MyLogger.debug(key + " : " + val);
result.put(key,val);
}catch (UnsupportedEncodingException ignored) {}
}
});
return result;
}
public static SessionTokenCache getSessionCache() {
return sessionTokenCache;
}

View File

@ -19,6 +19,7 @@ import java.sql.SQLException;
import java.util.ArrayList;
import java.util.UUID;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
import static site.deercloud.identityverification.SQLite.SqlManager.getConnection;
import static site.deercloud.identityverification.HttpServer.model.Response.*;
@ -32,7 +33,7 @@ public class Authenticate implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
JSONObject body = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject body = getBody(exchange);
String username = body.getString("username"); // 邮箱或其他凭证
String password = body.getString("password"); // 密码
String clientToken = body.getString("clientToken"); // 由客户端指定的令牌的 clientToken可选

View File

@ -12,6 +12,8 @@ import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
public class Invalidate implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
@ -21,7 +23,7 @@ public class Invalidate implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
JSONObject request = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject request = getBody(exchange);
String accessToken = request.getString("accessToken");
String clientToken = request.getString("clientToken");

View File

@ -17,6 +17,8 @@ import java.sql.SQLException;
import java.util.Objects;
import java.util.UUID;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
public class Refresh implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
@ -28,7 +30,7 @@ public class Refresh implements HttpHandler {
return;
}
Connection connection = SqlManager.getConnection();
JSONObject body = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject body = getBody(exchange);
String accessToken = body.getString("accessToken");
String clientToken = body.getString("clientToken");
Boolean requestUser = body.getBoolean("requestUser");

View File

@ -17,6 +17,8 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
public class SignOut implements HttpHandler {
@Override
public void handle(HttpExchange exchange) {
@ -26,7 +28,7 @@ public class SignOut implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
JSONObject request = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject request = getBody(exchange);
String username = request.getString("username");
String password = request.getString("password");
Connection connection = SqlManager.getConnection();

View File

@ -14,6 +14,8 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.Objects;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
public class Validate implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
@ -24,7 +26,7 @@ public class Validate implements HttpHandler {
return;
}
Connection connection = SqlManager.getConnection();
JSONObject request = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject request = getBody(exchange);
String accessToken = request.getString("accessToken");
String clientToken = request.getString("clientToken");
Token token = TokenDAO.selectByAccessToken(connection, accessToken);

View File

@ -13,7 +13,7 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;
import static site.deercloud.identityverification.Utils.Utils.ParseQueryString;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getQuery;
public class GetProfile implements HttpHandler {
@Override
@ -25,7 +25,7 @@ public class GetProfile implements HttpHandler {
return;
}
String uuid = exchange.getRequestURI().getPath().split("/")[4];
Map<String, String> request = ParseQueryString(exchange.getRequestURI().getQuery());
Map<String, String> request = getQuery(exchange);
boolean unsigned = true;
if (request.containsKey("unsigned")) {
unsigned = Boolean.parseBoolean(request.get("unsigned"));

View File

@ -15,7 +15,7 @@ import java.sql.Connection;
import java.util.Map;
import java.util.Objects;
import static site.deercloud.identityverification.Utils.Utils.ParseQueryString;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getQuery;
public class HasJoined implements HttpHandler {
@ -27,7 +27,7 @@ public class HasJoined implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
Map<String, String> query = ParseQueryString(exchange.getRequestURI().getQuery());
Map<String, String> query = getQuery(exchange);
String username = query.get("username");
String serverId = query.get("serverId");
String ip = query.get("ip");

View File

@ -14,6 +14,8 @@ import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import static site.deercloud.identityverification.HttpServer.HttpServerManager.getBody;
public class Join implements HttpHandler {
@Override
public void handle(HttpExchange exchange){
@ -23,7 +25,7 @@ public class Join implements HttpHandler {
Response.err_method_not_allowed(exchange);
return;
}
JSONObject request = JSONObject.parseObject(exchange.getRequestBody().toString());
JSONObject request = getBody(exchange);
String accessToken = request.getString("accessToken");
String selectedProfile = request.getString("selectedProfile");
String serverId = request.getString("serverId");

View File

@ -9,9 +9,11 @@ import site.deercloud.identityverification.SQLite.SqlManager;
import site.deercloud.identityverification.SQLite.UserDAO;
import site.deercloud.identityverification.Controller.AFKTracker;
import site.deercloud.identityverification.Controller.ConfigManager;
import site.deercloud.identityverification.Utils.FileToString;
import site.deercloud.identityverification.Utils.MyLogger;
import site.deercloud.identityverification.Controller.GameSessionCache;
import java.io.FileReader;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.UUID;
@ -41,20 +43,31 @@ public final class IdentityVerification extends JavaPlugin {
}
connection.close();
} catch (SQLException e) {
throw new RuntimeException(e);
MyLogger.debug(e);
}
// 初始化RSA
String publicKey = new File(this.getDataFolder(), configManager.getPublicKeyFileName()).toString();
String privateKey = new File(this.getDataFolder(), configManager.getPrivateKeyFileName()).toString();
if (publicKey == null || privateKey == null) {
File publicKeyPath = new File(this.getDataFolder(), configManager.getPublicKeyFileName());
File privateKeyPath = new File(this.getDataFolder(), configManager.getPrivateKeyFileName());
String pubKeyContent = FileToString.Read(publicKeyPath);
String priKeyContent = FileToString.Read(privateKeyPath);
if (pubKeyContent == null || priKeyContent == null) {
MyLogger.error("RSA文件不存在, 插件退出。");
this.getServer().getPluginManager().disablePlugin(this);
}else {
privateKey = privateKey.replace("-----BEGIN OPENSSH PRIVATE KEY-----", "");
privateKey = privateKey.replace("-----END OPENSSH PRIVATE KEY-----", "");
configManager.setSignaturePublicKey(publicKey);
configManager.setSignaturePrivateKey(privateKey);
pubKeyContent = pubKeyContent.replace("-----BEGIN PUBLIC KEY-----", "")
.replace("-----END PUBLIC KEY-----", "")
.replace("\n", "");
priKeyContent = priKeyContent.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replace("\n", "");
MyLogger.debug("publicKey: " + pubKeyContent);
MyLogger.debug("privateKey: " + priKeyContent);
configManager.setSignaturePublicKey(pubKeyContent);
configManager.setSignaturePrivateKey(priKeyContent);
}
// 注册事件 指令
this.getServer().getPluginManager().registerEvents(new Events(), this);
this.getCommand("identityverification").setExecutor(new Commands());
}

View File

@ -3,6 +3,7 @@ package site.deercloud.identityverification.SQLite;
import site.deercloud.identityverification.HttpServer.model.InviteCode;
import java.sql.*;
import java.util.HashSet;
import java.util.Set;
public class InviteCodeDAO {
@ -77,7 +78,7 @@ public class InviteCodeDAO {
PreparedStatement prep = con.prepareStatement(sql);
prep.setString(1, inviterUUID);
ResultSet rs = prep.executeQuery();
Set<InviteCode> inviteCodes = null;
Set<InviteCode> inviteCodes = new HashSet<>();
while (rs.next()) {
InviteCode inviteCode = new InviteCode();
inviteCode.code = rs.getString("code");

View File

@ -15,8 +15,8 @@ public class ProfileDAO {
+ " name text NOT NULL,\n" // 玩家名字
+ " textures text NOT NULL,\n" // 材质
+ " textures_signature text NOT NULL,\n" // 材质签名
+ " uploadableTextures text NOT NULL,\n" // 可上传的材质
+ " uploadableTextures_signature text NOT NULL,\n" // 可上传的材质签名
+ " uploadableTextures text ,\n" // 可上传的材质
+ " uploadableTextures_signature text ,\n" // 可上传的材质签名
+ " update_time integer NOT NULL\n" // 数据更新时间
+ ");";
PreparedStatement preparedStatement = connection.prepareStatement(sql);

View File

@ -7,17 +7,34 @@ import java.sql.*;
public class SqlManager {
public SqlManager() throws SQLException {
SQLiteConfig config = new SQLiteConfig();
config.setSharedCache(true);
config.enableRecursiveTriggers(true);
config.setBusyTimeout(10000);
SQLiteDataSource ds = new SQLiteDataSource(config);
String url = System.getProperty("user.dir"); // 获取工作目录
ds.setUrl("jdbc:sqlite:"+url+"/plugins/IdentityVerification/"+"IV-Database.db");
session = ds.getConnection();
}
public static Connection session;
public static Connection getConnection(){
try {
SQLiteConfig config = new SQLiteConfig();
config.setSharedCache(true);
config.enableRecursiveTriggers(true);
SQLiteDataSource ds = new SQLiteDataSource(config);
String url = System.getProperty("user.dir"); // 获取工作目录
ds.setUrl("jdbc:sqlite:"+url+"/plugins/IdentityVerification/"+"IV-Database.db");
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
// 加锁 防止多线程同时访问
synchronized (SqlManager.class) {
try {
SQLiteConfig config = new SQLiteConfig();
config.setSharedCache(true);
config.enableRecursiveTriggers(true);
config.setBusyTimeout(10000);
SQLiteDataSource ds = new SQLiteDataSource(config);
String url = System.getProperty("user.dir"); // 获取工作目录
ds.setUrl("jdbc:sqlite:"+url+"/plugins/IdentityVerification/"+"IV-Database.db");
return ds.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

View File

@ -22,7 +22,7 @@ public class UserDAO {
}
public static void insert(Connection con, User user) throws SQLException {
String sql = "INSERT INTO user(uuid, email, password, create_time, update_time) VALUES(?,?,?,?,?,?)";
String sql = "INSERT INTO user(uuid, email, password, create_time, update_time) VALUES(?,?,?,?,?)";
PreparedStatement prep = con.prepareStatement(sql);
prep.setString(1, user.uuid);
prep.setString(2, user.email);
@ -90,9 +90,10 @@ public class UserDAO {
}
public static Boolean isEmailExist(Connection con, String email) throws SQLException {
String sql = "SELECT * FROM user WHERE email = ?";
String sql = "SELECT count(*) FROM user WHERE email = ?";
PreparedStatement prep = con.prepareStatement(sql);
return prep.executeQuery().next();
prep.setString(1, email);
return prep.executeQuery().getInt(1) > 0;
}
}

View File

@ -38,13 +38,15 @@ public class EmailSender {
try {
// 1. 创建参数配置, 用于连接邮件服务器的参数配置
Properties props = new Properties(); // 参数配置
props.setProperty("mail.debug", "false");
props.setProperty("mail.transport.protocol", "smtp"); // 使用的协议JavaMail规范要求
props.setProperty("mail.smtp.host", host); // 发件人的邮箱的 SMTP 服务器地址
props.setProperty("mail.smtp.auth", "true"); // 需要请求认证
props.setProperty("mail.smtp.port", port);
props.setProperty("mail.smtp.ssl.enable", "true");
props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.smtp.socketFactory.fallback", "false");
props.setProperty("mail.smtp.socketFactory.port", port);
// 2. 根据配置创建会话对象, 用于和邮件服务器交互
Session session = Session.getInstance(props);
@ -52,7 +54,7 @@ public class EmailSender {
// 3. 创建一封邮件
MimeMessage message = new MimeMessage(session);
message.setFrom(new InternetAddress(from, "IdentityVerification", "UTF-8")); // 发件人
message.setFrom(new InternetAddress(from, account, "UTF-8")); // 发件人
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to, "no-reply", "UTF-8")); // 收件人
message.setSubject(subject, "UTF-8"); // 邮件主题
message.setContent(content, "text/html;charset=UTF-8"); // 邮件正文可以使用html标签

View File

@ -0,0 +1,22 @@
package site.deercloud.identityverification.Utils;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class FileToString {
public static String Read(File file){
try (FileReader fileReader = new FileReader(file)) {
char[] chars = new char[(int) file.length()];
if (fileReader.read(chars) != -1) {
return new String(chars);
}
return new String(chars);
} catch (Exception e) {
MyLogger.debug(e);
return null;
}
}
}

View File

@ -28,6 +28,7 @@ public class MyLogger {
public static void debug(Exception e) {
if (plugin.getConfigManager().getDebug()) {
plugin.getLogger().info(ChatColor.AQUA + "| " + e.getMessage());
e.printStackTrace();
}
}

View File

@ -6,7 +6,7 @@ import java.io.StringWriter;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import org.apache.commons.codec.binary.Base64;
public class SignatureUtil {
private final static String SIGN_TYPE_RSA = "RSA";
@ -24,10 +24,10 @@ public class SignatureUtil {
if (algorithm == null || "".equals(algorithm) || priKey == null || "".equals(priKey))
return null;
KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
KeyFactory keyFactory = KeyFactory.getInstance(algorithm); // 获取密钥工厂
byte[] encodedKey = StreamUtil.readText(new ByteArrayInputStream(priKey.getBytes())).getBytes();
encodedKey = Base64.getDecoder().decode(priKey.getBytes());
encodedKey = Base64.decodeBase64(priKey.getBytes());
return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(encodedKey));
}
@ -49,7 +49,7 @@ public class SignatureUtil {
StreamUtil.io(new InputStreamReader(new ByteArrayInputStream(pubKey.getBytes())), writer);
byte[] encodeByte = writer.toString().getBytes();
encodeByte = Base64.getDecoder().decode(pubKey.getBytes());
encodeByte = Base64.decodeBase64(pubKey.getBytes());
return keyFactory.generatePublic(new X509EncodedKeySpec(encodeByte));
}
@ -71,7 +71,7 @@ public class SignatureUtil {
signature.update(plain.getBytes(CHARSETTING));
byte[] signed = signature.sign();
return new String(Base64.getEncoder().encode(signed));
return new String(Base64.encodeBase64(signed));
}
/**
@ -91,6 +91,6 @@ public class SignatureUtil {
signature.initVerify(publicKey);
signature.update(plain.getBytes(CHARSETTING));
return signature.verify(Base64.getDecoder().decode(sign.getBytes()));
return signature.verify(Base64.decodeBase64(sign.getBytes()));
}
}

View File

@ -47,8 +47,7 @@ public class StreamUtil {
return readText(in, encoding, -1);
}
public static String readText(InputStream in, String encoding, int bufferSize)
throws IOException {
public static String readText(InputStream in, String encoding, int bufferSize) throws IOException {
Reader reader = (encoding == null) ? new InputStreamReader(in) : new InputStreamReader(in,
encoding);

View File

@ -13,24 +13,24 @@ import java.util.*;
public class Utils {
public static Map<String,String> ParseQueryString(String formData ) {
Map<String,String> result = new HashMap<>();
if(formData== null || formData.trim().length() == 0) {
return result;
}
final String[] items = formData.split("&");
Arrays.stream(items).forEach(item ->{
final String[] keyAndVal = item.split("=");
if( keyAndVal.length == 2) {
try{
final String key = URLDecoder.decode( keyAndVal[0],"utf8");
final String val = URLDecoder.decode( keyAndVal[1],"utf8");
result.put(key,val);
}catch (UnsupportedEncodingException ignored) {}
}
});
return result;
}
// public static Map<String,String> ParseQueryString(String formData ) {
// Map<String,String> result = new HashMap<>();
// if(formData== null || formData.trim().length() == 0) {
// return result;
// }
// final String[] items = formData.split("&");
// Arrays.stream(items).forEach(item ->{
// final String[] keyAndVal = item.split("=");
// if( keyAndVal.length == 2) {
// try{
// final String key = URLDecoder.decode( keyAndVal[0],"utf8");
// final String val = URLDecoder.decode( keyAndVal[1],"utf8");
// result.put(key,val);
// }catch (UnsupportedEncodingException ignored) {}
// }
// });
// return result;
// }
/**
* 根据玩家名字从Mojiang服务器获取UUID如果不存在则返回null

View File

@ -7,3 +7,9 @@ load: STARTUP
authors: [ Luming ]
description: 实名认证添加白名单、正版玩家邀请非正版注册管理。
website: https://blog.deercloud.site
commands:
identityverification:
description: 实名认证插件
usage: /iv <help>
aliases: [iv]
plugin: IdentityVerification

View File

@ -7,21 +7,21 @@
</n-form-item>
</n-grid-item>
<n-grid-item span="24">
<n-form-item label="设置密码">
<n-input type="password" show-password-on="click" placeholder="" v-model:value="password" />
</n-form-item>
</n-grid-item>
<n-grid-item span="12">
<n-form-item label="验证码">
<n-input placeholder="" v-model:value="email_code" />
<n-form-item label="创建一个游戏昵称">
<n-input placeholder="" v-model:value="invite_code" />
</n-form-item>
</n-grid-item>
<n-grid-item span="12">
<n-form-item label="&nbsp;">
<n-button @click="send_email_code" style="width: 100%">{{send_code_text}}</n-button>
</n-form-item>
</n-grid-item>
<n-grid-item span="24">
<n-form-item label="密码">
<n-input type="password" show-password-on="click" placeholder="" v-model:value="password" />
<n-button @click="send_email_code" style="width: 100%">{{profile_name_text}}</n-button>
</n-form-item>
</n-grid-item>
@ -36,6 +36,18 @@
<n-button @click="send_email_code" style="width: 100%">{{verify_invite_code_text}}</n-button>
</n-form-item>
</n-grid-item>
<n-grid-item span="12">
<n-form-item label="邮箱验证码">
<n-input placeholder="" v-model:value="email_code" />
</n-form-item>
</n-grid-item>
<n-grid-item span="12">
<n-form-item label="&nbsp;">
<n-button @click="send_email_code" style="width: 100%">{{send_code_text}}</n-button>
</n-form-item>
</n-grid-item>
<n-grid-item span="24">
<n-form-item>
@ -57,6 +69,7 @@ const invite_code = ref('')
const send_code_text = ref('发送验证码')
const verify_invite_code_text = ref('验证邀请码')
const profile_name_text = ref('验证可用性')
const onSubmit = () => {