From a9fd0c1dfb637c80842493d77e3181d2d05e0a42 Mon Sep 17 00:00:00 2001 From: lensferno Date: Sat, 4 Jun 2022 11:45:25 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E4=BA=9B=E4=BF=AE=E6=94=B9=201.=20?= =?UTF-8?q?=E5=B0=86register=E9=83=A8=E5=88=86=E6=8B=86=E5=88=86=202.=20?= =?UTF-8?q?=E6=9B=B4=E6=94=B9=E4=BA=86jwt=E7=9A=84=E7=BB=93=E6=9E=84=203.?= =?UTF-8?q?=20=E4=BF=AE=E6=94=B9pom.xml=E6=96=87=E4=BB=B6=E4=BB=A5?= =?UTF-8?q?=E8=83=BD=E5=A4=9F=E7=9B=B4=E6=8E=A5=E6=89=93=E5=8C=85jar?= =?UTF-8?q?=E8=BF=90=E8=A1=8C=EF=BC=88war=E5=8C=85=E6=9A=82=E6=97=B6?= =?UTF-8?q?=E4=B8=8D=E5=A4=84=E7=90=86)=204.=20=E4=BF=AE=E6=94=B9api?= =?UTF-8?q?=E6=96=87=E6=A1=A3=E6=8F=8F=E8=BF=B0=205.=20=E4=BF=AE=E6=94=B9?= =?UTF-8?q?=E5=89=8D=E7=AB=AF=E7=9A=84=E6=8E=A5=E5=8F=A3=E8=B0=83=E7=94=A8?= =?UTF-8?q?=EF=BC=88=E6=9C=AA=E6=9D=A5=E5=89=8D=E7=AB=AF=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E4=BC=9A=E6=8D=A2=E7=94=A8vue=E9=87=8D=E5=86=99=EF=BC=8C?= =?UTF-8?q?=E4=BD=86=E4=B8=8D=E6=98=AF=E7=9B=AE=E5=89=8D=E5=B9=B6=E4=B8=8D?= =?UTF-8?q?=E6=98=AF=E9=A6=96=E8=A6=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- API_doc.md | 20 ++++-- front-end/js/events.js | 40 ++++++++++- front-end/js/welcomepage_message.js | 18 ----- pom.xml | 21 ++++-- .../trailblazer/api/v1/beans/TokenBody.java | 70 +++++++++++++++++++ .../api/v1/config/ConfigLoader.java | 3 - .../api/v1/controllers/auth/login/Login.java | 5 +- .../controllers/auth/register/Register.java | 39 +++-------- .../user/UserNameAlreadyExistsException.java | 11 +++ .../v1/service/auth/login/LoginService.java | 7 +- .../v1/service/auth/register/Register.java | 4 -- .../auth/register/RegisterService.java | 39 +++++++++++ .../api/v1/utils/jwt/JWTManager.java | 8 ++- src/main/resources/application.yml | 2 + src/main/webapp/WEB-INF/web.xml | 18 ++--- 15 files changed, 219 insertions(+), 86 deletions(-) create mode 100644 src/main/java/me/lensfrex/trailblazer/api/v1/beans/TokenBody.java create mode 100644 src/main/java/me/lensfrex/trailblazer/api/v1/exceptions/user/UserNameAlreadyExistsException.java delete mode 100644 src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/Register.java create mode 100644 src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/RegisterService.java create mode 100644 src/main/resources/application.yml diff --git a/API_doc.md b/API_doc.md index 8e59974..8d396af 100644 --- a/API_doc.md +++ b/API_doc.md @@ -2,7 +2,13 @@ --- -##### 本文档中,除非特殊说明,URL测试地址均为 https://lb.ciduid.top ,使用POST方法的API参数均为Body部分的参数,以json格式发送 +##### 本文档中,除非特殊说明,URL地址前缀均为 http://[server_address]:[port]/ (本地运行),如果使用 lb.ciduid.top 提供的api服务,则应该为 https://lb.ciduid.top/api/v1/ + +##### 例如:登录接口`https://localhost:64888/user/login`(本地运行) `https://lb.ciduid.top/api/v1/user/login` (使用lb.ciduid.top的api) + +##### POST方法的API参数均为Body部分的参数,以json格式发送 + +--- ## 用户相关 @@ -10,7 +16,7 @@ - 功能:登录一个已经存在的用户,获取会话token -- URL: `/api/v1/login` +- URL: `/user/login` - 方法:`POST` @@ -46,7 +52,7 @@ - 功能:注册创建一个账号 -- URL:`/api/v1/register` +- URL:`/user/register` - 方法:`POST` @@ -80,11 +86,11 @@ ### 3. 修改用户基本信息 -// 这里的接口还没想好怎么设计 +// 这里的接口还没想好怎么设计,所以没写完 - 功能:修改用户的基本信息,如密码、登录名等 -- URL:`/api/v1/modifyUserBasicInfo?uid={uid}` +- URL:`/user/modifyUserBasicInfo?uid={uid}` - 方法:`post` @@ -110,7 +116,7 @@ - 功能:修改用户的基本信息,如密码、登录名等 -- URL:`/api/v1/modifyUserInfo?uid={uid}` +- URL:`/user/modifyUserInfo?uid={uid}` - 方法:`post` @@ -134,7 +140,7 @@ - 功能:修改用户的基本信息,如密码、登录名等 -- URL:`/api/v1/profile?uid={uid}` +- URL:`/user/profile?uid={uid}` - 方法:`get` diff --git a/front-end/js/events.js b/front-end/js/events.js index 379a878..5b4e4ed 100644 --- a/front-end/js/events.js +++ b/front-end/js/events.js @@ -20,9 +20,10 @@ function login() { function sendLogin(postData) { $.ajax({ - url: "/api/v1/login", + url: "/api/v1/user/login", type: "post", dataType: "json", + contentType: "application/json", data: JSON.stringify(postData), success: (result) => { console.log("获取到数据:" + JSON.stringify(result)); @@ -31,6 +32,7 @@ function sendLogin(postData) { case 1: showMessage("好啦"); storeToken(result.data.access_token); + showDialog("LoginTest", "获得数据:" + JSON.stringify(result.data)); break; case 2: showMessage("请求的数据不对哦"); @@ -68,9 +70,10 @@ function register() { }; $.ajax({ - url: "/api/v1/register", + url: "/api/v1/user/register", type: "post", dataType: "json", + contentType: "application/json", data: JSON.stringify(postData), success: (result) => { console.log("获取到数据:" + JSON.stringify(result)); @@ -79,6 +82,7 @@ function register() { case 1: showMessage("好啦"); storeToken(result.data.access_token); + showDialog("RegisterTest", "获得数据:" + JSON.stringify(result.data)); break; case 2: showMessage("请求的数据不对哦"); @@ -102,4 +106,36 @@ function register() { function jumpToFillInformation() { +} + +function checkInputDataCorrect(username, password) { + if (username == "" || passwd == "") { + showMessage("用户名和密码都不可以是空的哦"); + return false; + } + + if (!isLetter(username)) { + showMessage("用户名只能是大小写字母和数字哦"); + return false; + } + + if (!isNormalCharacter(passwd)) { + showMessage("不知道你往密码框都搞了点什么东西..."); + return false; + } + + if (username.length > 32) { + showMessage("用户名太长啦(应该小于32个字符)"); + return; + } + + if (password.length < 8) { + showMessage("密码长度太短啦(大于等于8小于等于32)"); + return; + } else if (password > 32){ + showMessage("密码长度太长啦(大于等于8小于等于32)"); + return; + } + + return true; } \ No newline at end of file diff --git a/front-end/js/welcomepage_message.js b/front-end/js/welcomepage_message.js index 2ac7c65..e76f7f4 100644 --- a/front-end/js/welcomepage_message.js +++ b/front-end/js/welcomepage_message.js @@ -6,24 +6,6 @@ function closeDialog() { $("#dialogMask").fadeOut(400); } -function checkInputDataCorrect(username, password) { - if (username == "" || passwd == "") { - showMessage("用户名和密码都不可以是空的哦"); - return false; - } - - if (!isLetter(username)) { - showMessage("用户名只能是大小写字母和数字哦"); - return false; - } - - if (!isNormalCharacter(passwd)) { - showMessage("不知道你往密码框都搞了点什么东西..."); - return false; - } - return true; -} - function showMessage(message) { $("#errMsgBox")[0].innerHTML = `

${message}

`; } diff --git a/pom.xml b/pom.xml index 325db0a..a20310e 100644 --- a/pom.xml +++ b/pom.xml @@ -8,8 +8,7 @@ Trailblazer 0.0.1-dev Trailblazer - war - + jar me.lensfrex.trailblazer.api.v1.ServerMain @@ -17,6 +16,7 @@ 1.8 1.8 5.8.1 + org.springframework.boot @@ -88,21 +88,30 @@ org.springframework.boot spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-tomcat + + org.springframework.boot spring-boot-starter-test test - + + org.springframework.boot + spring-boot-starter-tomcat + compile + - org.apache.maven.plugins - maven-war-plugin - 3.3.2 + org.springframework.boot + spring-boot-maven-plugin diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/beans/TokenBody.java b/src/main/java/me/lensfrex/trailblazer/api/v1/beans/TokenBody.java new file mode 100644 index 0000000..e6be32a --- /dev/null +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/beans/TokenBody.java @@ -0,0 +1,70 @@ +package me.lensfrex.trailblazer.api.v1.beans; + +import com.google.gson.annotations.SerializedName; + +import java.util.Date; + +public class TokenBody { + @SerializedName("api_ver") + private String apiVersion; + + @SerializedName("user") + private String username; + + @SerializedName("uid") + private long uid; + + @SerializedName("uuid") + private String UUID; + + @SerializedName("exp") + private Date invalidDate; + + public TokenBody(String apiVersion, String username, long uid, String UUID, Date invalidDate) { + this.apiVersion = apiVersion; + this.username = username; + this.uid = uid; + this.UUID = UUID; + this.invalidDate = invalidDate; + } + + public String getApiVersion() { + return apiVersion; + } + + public void setApiVersion(String apiVersion) { + this.apiVersion = apiVersion; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public long getUid() { + return uid; + } + + public void setUid(long uid) { + this.uid = uid; + } + + public String getUUID() { + return UUID; + } + + public void setUUID(String UUID) { + this.UUID = UUID; + } + + public Date getInvalidDate() { + return invalidDate; + } + + public void setInvalidDate(Date invalidDate) { + this.invalidDate = invalidDate; + } +} diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/config/ConfigLoader.java b/src/main/java/me/lensfrex/trailblazer/api/v1/config/ConfigLoader.java index ef6bd0c..e226572 100644 --- a/src/main/java/me/lensfrex/trailblazer/api/v1/config/ConfigLoader.java +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/config/ConfigLoader.java @@ -7,9 +7,6 @@ import java.io.*; import java.nio.charset.StandardCharsets; public class ConfigLoader { - - - private final String globalConfigFilePath; public ConfigLoader(String globalConfigFilePath) { diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/login/Login.java b/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/login/Login.java index 7dffb4b..a7a5e6b 100644 --- a/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/login/Login.java +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/login/Login.java @@ -9,7 +9,6 @@ import me.lensfrex.trailblazer.api.v1.exceptions.RequestDataInvalidException; import me.lensfrex.trailblazer.api.v1.exceptions.user.LoginInfoWrongException; import me.lensfrex.trailblazer.api.v1.service.auth.login.LoginService; import me.lensfrex.trailblazer.api.v1.utils.InputChecker; -import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; import org.mindrot.jbcrypt.BCrypt; import org.springframework.web.bind.annotation.*; @@ -19,7 +18,6 @@ import javax.annotation.Resource; @RequestMapping("/user") public class Login { private static final Gson gson = new Gson(); - private static final JWTManager jwtManager = JWTManager.getInstance(); @Resource private LoginService loginService; @@ -34,12 +32,13 @@ public class Login { throw new RequestDataInvalidException(); } - return gson.toJson(loginService.getLoginResponseBody(loginRequestBody)); + return gson.toJson(loginService.checkLogin(loginRequestBody)); } catch (JsonParseException | RequestDataInvalidException e) { return gson.toJson(ResponseBase.error(ResponseCode.REQUEST_FORMAT_INVALID, "请求的数据格式不对")); } catch (LoginInfoWrongException e) { return gson.toJson(ResponseBase.error(ResponseCode.PASSWORD_WRONG, "用户名或密码错误")); } catch (Exception e) { + System.err.println(e.getMessage()); return gson.toJson(ResponseBase.error(ResponseCode.SERVER_ERROR, "服务器内部错误,请联系那个背锅的家伙")); } } diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/register/Register.java b/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/register/Register.java index f57fa01..e884ad8 100644 --- a/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/register/Register.java +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/register/Register.java @@ -4,35 +4,30 @@ import com.google.gson.Gson; import com.google.gson.JsonParseException; import me.lensfrex.trailblazer.api.v1.beans.requests.RegisterRequestBody; import me.lensfrex.trailblazer.api.v1.beans.responses.general.ResponseCode; -import me.lensfrex.trailblazer.api.v1.beans.responses.RegisterResponseData; import me.lensfrex.trailblazer.api.v1.beans.responses.general.ResponseBase; -import me.lensfrex.trailblazer.api.v1.dao.UserDao; import me.lensfrex.trailblazer.api.v1.exceptions.RequestDataInvalidException; +import me.lensfrex.trailblazer.api.v1.exceptions.user.UserNameAlreadyExistsException; +import me.lensfrex.trailblazer.api.v1.service.auth.register.RegisterService; import me.lensfrex.trailblazer.api.v1.utils.InputChecker; -import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; -import org.mindrot.jbcrypt.BCrypt; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.time.Instant; -import java.time.temporal.ChronoUnit; -import java.util.Date; -import java.util.UUID; +import javax.annotation.Resource; @RestController @RequestMapping("/user") public class Register { - private static final JWTManager jwtManager = JWTManager.getInstance(); + @Resource + private RegisterService registerService; + private static final Gson gson = new Gson(); @PostMapping(value = "/register", produces = "application/json") public String register(@RequestBody String request) { - RegisterRequestBody registerRequestBody; - try { - registerRequestBody = gson.fromJson(request, RegisterRequestBody.class); + RegisterRequestBody registerRequestBody = gson.fromJson(request, RegisterRequestBody.class); if (registerRequestBody == null || InputChecker.hasInvalidChar(registerRequestBody.getUserName()) || @@ -41,25 +36,11 @@ public class Register { throw new RequestDataInvalidException(); } - if (UserDao.isUserAlreadyExist(registerRequestBody.getUserName())) { - return gson.toJson(ResponseBase.error(ResponseCode.USER_ALREADY_EXISTS, "申请注册的用户已经存在")); - } - - String userUUID = UUID.randomUUID().toString(); - String userBcryptPasswd = BCrypt.hashpw(registerRequestBody.getPassword(), BCrypt.gensalt()); - - int newUid = UserDao.addUser(userUUID, registerRequestBody.getUserName(), userBcryptPasswd); - - Date expireDate = Date.from(Instant.now().plus(JWTManager.TOKEN_DEFAULT_EXPIRE_DAY, ChronoUnit.DAYS)); - RegisterResponseData registerResponseBody = new RegisterResponseData( - newUid, - userUUID, - jwtManager.createNewJWT(registerRequestBody.getUserName(), expireDate), - expireDate.getTime()); - - return gson.toJson(ResponseBase.success(registerResponseBody)); + return gson.toJson(ResponseBase.success(registerService.register(registerRequestBody))); } catch (JsonParseException | RequestDataInvalidException e) { return gson.toJson(ResponseBase.error(ResponseCode.REQUEST_FORMAT_INVALID, "请求的数据不正确")); + } catch (UserNameAlreadyExistsException e) { + return gson.toJson(ResponseBase.error(ResponseCode.USER_ALREADY_EXISTS, "用户名已经被使用")); } catch (Exception e) { return gson.toJson(ResponseBase.error(ResponseCode.SERVER_ERROR, "服务器程序发生错误,有个家伙又写bug了。Error:" + e.getMessage())); } diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/exceptions/user/UserNameAlreadyExistsException.java b/src/main/java/me/lensfrex/trailblazer/api/v1/exceptions/user/UserNameAlreadyExistsException.java new file mode 100644 index 0000000..ba0f48f --- /dev/null +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/exceptions/user/UserNameAlreadyExistsException.java @@ -0,0 +1,11 @@ +package me.lensfrex.trailblazer.api.v1.exceptions.user; + +public class UserNameAlreadyExistsException extends Exception { + public UserNameAlreadyExistsException(String message) { + super(message); + } + + public UserNameAlreadyExistsException() { + super("用户名已经被使用"); + } +} diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/login/LoginService.java b/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/login/LoginService.java index a49dce8..2bee990 100644 --- a/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/login/LoginService.java +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/login/LoginService.java @@ -18,7 +18,7 @@ import java.util.Date; public class LoginService { private static final JWTManager jwtManager = JWTManager.getInstance(); - public ResponseBase getLoginResponseBody(LoginRequestBody loginRequestBody) throws LoginInfoWrongException { + public ResponseBase checkLogin(LoginRequestBody loginRequestBody) throws LoginInfoWrongException { UserInformation userDatabaseInformation = UserDao.getUser(loginRequestBody.getUserName()); if (userDatabaseInformation == null) { @@ -30,7 +30,10 @@ public class LoginService { } Date expireDate = Date.from(Instant.now().plus(JWTManager.TOKEN_DEFAULT_EXPIRE_DAY, ChronoUnit.DAYS)); - String userToken = jwtManager.createNewJWT(loginRequestBody.getUserName(), expireDate); + String userToken = jwtManager.createNewJWT(loginRequestBody.getUserName(), + userDatabaseInformation.uuid, + userDatabaseInformation.uid, + expireDate); LoginResponseData loginResponseData = new LoginResponseData( userDatabaseInformation.uid, diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/Register.java b/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/Register.java deleted file mode 100644 index 48f7b41..0000000 --- a/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/Register.java +++ /dev/null @@ -1,4 +0,0 @@ -package me.lensfrex.trailblazer.api.v1.service.auth.register; - -public class Register { -} diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/RegisterService.java b/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/RegisterService.java new file mode 100644 index 0000000..37ed308 --- /dev/null +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/RegisterService.java @@ -0,0 +1,39 @@ +package me.lensfrex.trailblazer.api.v1.service.auth.register; + +import me.lensfrex.trailblazer.api.v1.beans.requests.RegisterRequestBody; +import me.lensfrex.trailblazer.api.v1.beans.responses.RegisterResponseData; +import me.lensfrex.trailblazer.api.v1.dao.UserDao; +import me.lensfrex.trailblazer.api.v1.exceptions.user.UserNameAlreadyExistsException; +import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; +import org.mindrot.jbcrypt.BCrypt; +import org.springframework.stereotype.Service; + +import java.time.Instant; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.UUID; + +@Service +public class RegisterService { + private static final JWTManager jwtManager = JWTManager.getInstance(); + + public RegisterResponseData register(RegisterRequestBody registerRequestBody) throws UserNameAlreadyExistsException { + + if (UserDao.isUserAlreadyExist(registerRequestBody.getUserName())) { + throw new UserNameAlreadyExistsException("用户名已经被使用"); + } + + String userUUID = UUID.randomUUID().toString(); + String userBcryptPasswd = BCrypt.hashpw(registerRequestBody.getPassword(), BCrypt.gensalt()); + + int newUid = UserDao.addUser(userUUID, registerRequestBody.getUserName(), userBcryptPasswd); + + Date expireDate = Date.from(Instant.now().plus(JWTManager.TOKEN_DEFAULT_EXPIRE_DAY, ChronoUnit.DAYS)); + + return new RegisterResponseData( + newUid, + userUUID, + jwtManager.createNewJWT(registerRequestBody.getUserName(), userUUID, newUid, expireDate), + expireDate.getTime()); + } +} diff --git a/src/main/java/me/lensfrex/trailblazer/api/v1/utils/jwt/JWTManager.java b/src/main/java/me/lensfrex/trailblazer/api/v1/utils/jwt/JWTManager.java index 8ce42b1..f6f7aca 100644 --- a/src/main/java/me/lensfrex/trailblazer/api/v1/utils/jwt/JWTManager.java +++ b/src/main/java/me/lensfrex/trailblazer/api/v1/utils/jwt/JWTManager.java @@ -23,15 +23,17 @@ public class JWTManager { return self; } - public String createNewJWT(String user, Date invalidDate) { + public String createNewJWT(String user, String uuid, long uid, Date invalidDate) { Map header = new HashMap<>(); header.put("alg", "HS256"); header.put("typ", "JWT"); Map payload = new HashMap<>(); payload.put("user", user); + payload.put("uuid", uuid); + payload.put("uid", uid); payload.put("api_ver", "1"); -// payload.put("iss", machineId); +// payload.put("blame", machineId); return Jwts.builder() .setHeader(header) @@ -46,7 +48,7 @@ public class JWTManager { public boolean verifyToken(String token) { try { - Jws jws = Jwts.parserBuilder() + Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..9aa1844 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,2 @@ +server: + port: 64888 \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml index b53372f..74e0372 100644 --- a/src/main/webapp/WEB-INF/web.xml +++ b/src/main/webapp/WEB-INF/web.xml @@ -6,17 +6,17 @@ TrailblazerApiV1 - + org.springframework.web.servlet.DispatcherServlet - - jersey.config.server.provider.packages - me.lensfrex.trailblazer - + + + + - - com.sun.jersey.api.json.POJOMappingFeature - true - + + + +