添加了指令
基本实现了注册接口 (数据库有严重的访问冲突问题)
This commit is contained in:
parent
dcbe37cf91
commit
3931731cb2
1
.gitignore
vendored
1
.gitignore
vendored
@ -97,6 +97,7 @@ $RECYCLE.BIN/
|
||||
*.lnk
|
||||
|
||||
target/
|
||||
test-setver/
|
||||
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
|
23
README.md
23
README.md
@ -3,5 +3,28 @@
|
||||
|
||||
## 功能介绍 (TODO List)
|
||||
|
||||
### 外置登录服务器
|
||||
|
||||
- [x] 用户登录
|
||||
- [x] 刷新令牌
|
||||
- [x] 验证令牌
|
||||
- [x] 吊销令牌
|
||||
- [x] 客户端进入服务器
|
||||
- [x] 服务端验证客户端
|
||||
- [x] 查询角色属性
|
||||
- [x] 按名称批量查询
|
||||
- [ ] 材质(皮肤)上传/删除
|
||||
- [ ] 多角色支持
|
||||
|
||||
### Web服务器
|
||||
|
||||
- [x] 用户注册
|
||||
- [ ] 邀请码生成
|
||||
- [ ] 实名认证白名单
|
||||
- [ ] 用户管理
|
||||
- [ ] 用户登录
|
||||
- [ ] 密码修改
|
||||
- [ ] 用户信息修改
|
||||
- [ ] 材质(皮肤)上传/删除
|
||||
- [ ] 多角色创建删除
|
||||
|
||||
|
31
pom.xml
31
pom.xml
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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"); // 身份证(实名认证用)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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(可选)
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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"));
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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标签)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -7,3 +7,9 @@ load: STARTUP
|
||||
authors: [ Luming ]
|
||||
description: 实名认证添加白名单、正版玩家邀请非正版注册管理。
|
||||
website: https://blog.deercloud.site
|
||||
commands:
|
||||
identityverification:
|
||||
description: 实名认证插件
|
||||
usage: /iv <help>
|
||||
aliases: [iv]
|
||||
plugin: IdentityVerification
|
||||
|
@ -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=" ">
|
||||
<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=" ">
|
||||
<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 = () => {
|
||||
|
Loading…
Reference in New Issue
Block a user