Compare commits
	
		
			No commits in common. 'spring-dev' and 'main' have entirely different histories. 
		
	
	
		
			spring-dev
			...
			main
		
	
		
	| @ -1,172 +0,0 @@ | ||||
| # Trailblazer RESTful API 文档 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ##### 本文档中,除非特殊说明,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格式发送 | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## 用户相关 | ||||
| 
 | ||||
| ### 1. 登录 | ||||
| 
 | ||||
| - 功能:登录一个已经存在的用户,获取会话token | ||||
| 
 | ||||
| - URL: `/user/login` | ||||
| 
 | ||||
| - 方法:`POST` | ||||
| 
 | ||||
| - 参数: | ||||
|    | ||||
|   | 参数        | 参数类型   | 说明                                       | | ||||
|   | --------- | ------ | ---------------------------------------- | | ||||
|   | user_name | string | 登录用户名,必选                                 | | ||||
|   | password  | string | 一次sha256后,再在尾部拼接原始密码,然后再一次sha256得到的密文,必选 | | ||||
|   | verify    | string | 验证码,可选,在服务器要求的时候需要提供,目前没有用               | | ||||
|    | ||||
|   示例: | ||||
|    | ||||
|   ```json | ||||
|   { | ||||
|       "user_name": "userName", | ||||
|       "password": "57a8a929b8fc077da76769179159a1d3ae44e9f255c270fc98d4b125b30d5cca", | ||||
|       "verify": "114514" | ||||
|   } | ||||
|   ``` | ||||
| 
 | ||||
| - 返回: | ||||
| 
 | ||||
| - | 字段           | 字段类型   | 说明                                          | | ||||
|   | ------------ | ------ | ------------------------------------------- | | ||||
|   | code         | int    | 请求的状态信息码,详见“状态信息码”                          | | ||||
|   | msg          | string | 本次请求的信息                                     | | ||||
|   | uid          | int    | 用户的uid                                      | | ||||
|   | access_token | string | 会话token,用于其他API调用,成功时返回正确token,不成功时为null    | | ||||
|   | expired_at   | string | token过期时间,应当在token过期前调用token续期API以获取新的token | | ||||
| 
 | ||||
| ### 2. 注册 | ||||
| 
 | ||||
| - 功能:注册创建一个账号 | ||||
| 
 | ||||
| - URL:`/user/register` | ||||
| 
 | ||||
| - 方法:`POST` | ||||
| 
 | ||||
| - 参数: | ||||
|    | ||||
|   | 参数        | 参数类型   | 说明                                                 | | ||||
|   | --------- | ------ | -------------------------------------------------- | | ||||
|   | user_name | string | 注册的用户名,用于登录,最长不超过32位,必选                            | | ||||
|   | password  | string | 第一次sha256后再在尾部拼接原始密码,然后再一次sha256得到的密文,长度应为8~32位,必选 | | ||||
|   | verify    | string | 验证码,可选,在服务器要求的时候需要提供,目前没有用                         | | ||||
|    | ||||
|   示例: | ||||
|    | ||||
|   ```json | ||||
|   { | ||||
|       "user_name": "userName", | ||||
|       "password": "57a8a929b8fc077da76769179159a1d3ae44e9f255c270fc98d4b125b30d5cca", | ||||
|       "verify": "114514" | ||||
|   } | ||||
|   ``` | ||||
| 
 | ||||
| - 返回: | ||||
| 
 | ||||
| - | 字段         | 字段类型   | 说明                                          | | ||||
|   | ---------- | ------ | ------------------------------------------- | | ||||
|   | code       | int    | 请求的状态信息码,详见“状态信息码”                          | | ||||
|   | msg        | string | 本次请求的信息                                     | | ||||
|   | uid        | int    | 用户uid                                       | | ||||
|   | token      | string | 会话token,用于其他API调用,成功时返回正确token,不成功时为null    | | ||||
|   | expired_at | string | token过期时间,应当在token过期前调用token续期API以获取新的token | | ||||
| 
 | ||||
| ### 3. 修改用户基本信息 | ||||
| 
 | ||||
| // 这里的接口还没想好怎么设计,所以没写完 | ||||
| 
 | ||||
| - 功能:修改用户的基本信息,如密码、登录名等 | ||||
| 
 | ||||
| - URL:`/user/modifyUserBasicInfo?uid={uid}` | ||||
| 
 | ||||
| - 方法:`post` | ||||
| 
 | ||||
| - 参数: | ||||
| 
 | ||||
| - | 参数        | 参数类型   | 说明                      | | ||||
|   | --------- | ------ | ----------------------- | | ||||
|   | uid       | int    | 欲修改的用户的uid,必选           | | ||||
|   | user_name | string | 注册的用户名,用于登录,最长不超过32位,必选 | | ||||
|   | token     | string | 登陆时获得的token,必选          | | ||||
|    | ||||
|   示例: | ||||
| 
 | ||||
| ```json | ||||
| { | ||||
|     "user_name": "userName", | ||||
|     "token": "57a8a929b8fc077da76769179159a1d3ae44e9f255c270fc98d4b125b30d5cca",    "" | ||||
| 
 | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| ### 4. 修改用户个性信息 | ||||
| 
 | ||||
| - 功能:修改用户的基本信息,如密码、登录名等 | ||||
| 
 | ||||
| - URL:`/user/modifyUserInfo?uid={uid}` | ||||
| 
 | ||||
| - 方法:`post` | ||||
| 
 | ||||
| - 参数: | ||||
| 
 | ||||
| - | 参数           | 参数类型   | 说明                        | | ||||
|   | ------------ | ------ | ------------------------- | | ||||
|   | uid          | int    | 欲修改的用户的uid,放置于请求URL参数中,必选 | | ||||
|   | token        | string | 有效的会话token,必选             | | ||||
|   | modify_tiems | json   | 欲更改的个性数据信息                | | ||||
| 
 | ||||
| - 返回: | ||||
| 
 | ||||
| - | 字段     | 字段类型      | 说明           | | ||||
|   | ------ | --------- | ------------ | | ||||
|   | code   | int       | 状态信息码        | | ||||
|   | msg    | string    | 结果信息         | | ||||
|   | result | jsonArray | 更改后用户的完整个性信息 | | ||||
| 
 | ||||
| ### 5. 获取用户个性信息 | ||||
| 
 | ||||
| - 功能:修改用户的基本信息,如密码、登录名等 | ||||
| 
 | ||||
| - URL:`/user/profile?uid={uid}` | ||||
| 
 | ||||
| - 方法:`get` | ||||
| 
 | ||||
| - 参数: | ||||
| 
 | ||||
| - | 参数    | 参数类型   | 说明                          | | ||||
|   | ----- | ------ | --------------------------- | | ||||
|   | uid   | int    | 欲获取的用户的uid,放置于请求URL参数中,必选   | | ||||
|   | token | string | 有效的会话token,可选,若不提供仅能显示公开的信息 | | ||||
| 
 | ||||
| - 返回: | ||||
| 
 | ||||
| - | 字段     | 字段类型      | 说明     | | ||||
|   | ------ | --------- | ------ | | ||||
|   | code   | int       | 状态信息码  | | ||||
|   | msg    | string    | 结果信息   | | ||||
|   | result | jsonArray | 获取到的信息 | | ||||
| 
 | ||||
| > 4、5中用户信息result字段的json结构: | ||||
| >  | ||||
| > ```json | ||||
| > [ | ||||
| >     "nick_name": "lensfrex", | ||||
| >     "desc": null, | ||||
| >     ... | ||||
| > ] | ||||
| > ``` | ||||
| 
 | ||||
| *~~先这样吧~~* | ||||
| @ -1,17 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1; | ||||
| 
 | ||||
| import org.springframework.boot.SpringApplication; | ||||
| import org.springframework.boot.autoconfigure.SpringBootApplication; | ||||
| import org.springframework.boot.builder.SpringApplicationBuilder; | ||||
| import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; | ||||
| 
 | ||||
| @SpringBootApplication | ||||
| public class ServerMain extends SpringBootServletInitializer { | ||||
|     @Override | ||||
|     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { | ||||
|         return application.sources(ServerMain.class); | ||||
|     } | ||||
|     public static void main(String[] args) { | ||||
|         SpringApplication.run(ServerMain.class, args); | ||||
|     } | ||||
| } | ||||
| @ -1,70 +0,0 @@ | ||||
| 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; | ||||
|     } | ||||
| } | ||||
| @ -1,18 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers; | ||||
| 
 | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.PostMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| 
 | ||||
| /** | ||||
|  * 只是方便前端测试自己到底发了什么数据给后端 | ||||
|  * 返回数据不是很详细,只是把数据体原样给返回了 | ||||
|  * 但是header信息之类的并没有提供 | ||||
|  */ | ||||
| @RequestMapping("/test") | ||||
| public class FeedBack { | ||||
|     @PostMapping() | ||||
|     public String returnPostRequest(String string) { | ||||
|         return string; | ||||
|     } | ||||
| } | ||||
| @ -1,15 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers; | ||||
| 
 | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/") | ||||
| public class Index { | ||||
|     @GetMapping() | ||||
|     public String index() { | ||||
|         return "Here is the API root of Trailblazer.</br>\n" + | ||||
|                 "To use the API currently, please see the Trailblazer RESTFul API document."; | ||||
|     } | ||||
| } | ||||
| @ -1,49 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers.auth.login; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonParseException; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.requests.LoginRequestBody; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.general.ResponseBase; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.general.ResponseCode; | ||||
| 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 org.mindrot.jbcrypt.BCrypt; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| 
 | ||||
| import javax.annotation.Resource; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/user") | ||||
| public class Login { | ||||
|     private static final Gson gson = new Gson(); | ||||
| 
 | ||||
|     @Resource | ||||
|     private LoginService loginService; | ||||
| 
 | ||||
|     @PostMapping(value = "/login", produces = "application/json") | ||||
|     public String login(@RequestBody String request) { | ||||
|         LoginRequestBody loginRequestBody; | ||||
|         try { | ||||
|             loginRequestBody = gson.fromJson(request, LoginRequestBody.class); | ||||
|             if (InputChecker.hasInvalidChar(loginRequestBody.getUserName()) || | ||||
|                     InputChecker.hasInvisibleChar(loginRequestBody.getPassword())) { | ||||
|                 throw new RequestDataInvalidException(); | ||||
|             } | ||||
| 
 | ||||
|             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, "服务器内部错误,请联系那个背锅的家伙")); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public boolean identifyPassword(String originPassword, String bcryptPassword) { | ||||
|         return BCrypt.checkpw(originPassword, bcryptPassword); | ||||
|     } | ||||
| } | ||||
| @ -1,48 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers.auth.register; | ||||
| 
 | ||||
| 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.general.ResponseBase; | ||||
| 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 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 javax.annotation.Resource; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/user") | ||||
| public class Register { | ||||
|     @Resource | ||||
|     private RegisterService registerService; | ||||
| 
 | ||||
|     private static final Gson gson = new Gson(); | ||||
| 
 | ||||
|     @PostMapping(value = "/register", produces = "application/json") | ||||
|     public String register(@RequestBody String request) { | ||||
|         try { | ||||
|             RegisterRequestBody registerRequestBody = gson.fromJson(request, RegisterRequestBody.class); | ||||
| 
 | ||||
|             if (registerRequestBody == null || | ||||
|                     InputChecker.hasInvalidChar(registerRequestBody.getUserName()) || | ||||
|                     InputChecker.hasInvisibleChar(registerRequestBody.getPassword())) { | ||||
| 
 | ||||
|                 throw new RequestDataInvalidException(); | ||||
|             } | ||||
| 
 | ||||
|             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())); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,16 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers.auth.token; | ||||
| 
 | ||||
| 
 | ||||
| import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; | ||||
| import org.springframework.web.bind.annotation.*; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/token") | ||||
| public class TokenChecker { | ||||
|     public static final JWTManager jwtManager = JWTManager.getInstance(); | ||||
| 
 | ||||
|     @PostMapping(value = "/check", produces = "application/json") | ||||
|     public String checkTokenAvailable(@RequestBody String request) { | ||||
|         return String.valueOf(jwtManager.verifyToken(request)); | ||||
|     } | ||||
| } | ||||
| @ -1,16 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers.auth.token; | ||||
| 
 | ||||
| 
 | ||||
| import org.springframework.web.bind.annotation.RequestBody; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMethod; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/token") | ||||
| public class TokenRefresher { | ||||
|     @RequestMapping(value = "/refresh", method = RequestMethod.POST, produces = "application/json") | ||||
|     public String refreshToken(@RequestBody String request) { | ||||
|         return request; | ||||
|     } | ||||
| } | ||||
| @ -1,15 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.controllers.profile; | ||||
| 
 | ||||
| import org.springframework.web.bind.annotation.RequestBody; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| 
 | ||||
| @RequestMapping("/profile") | ||||
| public class Profile { | ||||
| 
 | ||||
| //    @Path("/getItems/{uid}")
 | ||||
| //    @Produces(MediaType.APPLICATION_JSON)
 | ||||
|     public String getProfiles(@RequestBody String uid) { | ||||
|         return "unfinished feature..."; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -1,11 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.exceptions.user; | ||||
| 
 | ||||
| public class UserNameAlreadyExistsException extends Exception { | ||||
|     public UserNameAlreadyExistsException(String message) { | ||||
|         super(message); | ||||
|     } | ||||
| 
 | ||||
|     public UserNameAlreadyExistsException() { | ||||
|         super("用户名已经被使用"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,20 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service; | ||||
| 
 | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| 
 | ||||
| /** | ||||
|  * 只是方便前端测试自己到底发了什么数据给后端 | ||||
|  * 返回数据不是很详细,只是把数据体原样给返回了 | ||||
|  * 但是header信息之类的并没有提供 | ||||
|  */ | ||||
| @Path("/test") | ||||
| public class FeedBack { | ||||
|     @POST | ||||
|     @Produces(MediaType.TEXT_PLAIN) | ||||
|     public String returnRequest(String string) { | ||||
|         return string; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,16 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service; | ||||
| 
 | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| 
 | ||||
| @Path("/") | ||||
| public class Index { | ||||
|     @GET | ||||
|     @Produces(MediaType.TEXT_HTML) | ||||
|     public String index() { | ||||
|         return "Here is the API root of Trailblazer.</br>\n" + | ||||
|                 "To use the API currently, please see the Trailblazer RESTFul API document."; | ||||
|     } | ||||
| } | ||||
| @ -1,51 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.auth.login; | ||||
| 
 | ||||
| import me.lensfrex.trailblazer.api.v1.beans.requests.LoginRequestBody; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.LoginResponseData; | ||||
| 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.user.LoginInfoWrongException; | ||||
| import me.lensfrex.trailblazer.api.v1.pojos.UserInformation; | ||||
| 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; | ||||
| 
 | ||||
| @Service | ||||
| public class LoginService { | ||||
|     private static final JWTManager jwtManager = JWTManager.getInstance(); | ||||
| 
 | ||||
|     public ResponseBase<LoginResponseData> checkLogin(LoginRequestBody loginRequestBody) throws LoginInfoWrongException { | ||||
|         UserInformation userDatabaseInformation = UserDao.getUser(loginRequestBody.getUserName()); | ||||
| 
 | ||||
|         if (userDatabaseInformation == null) { | ||||
|             throw new LoginInfoWrongException(); | ||||
|         } | ||||
| 
 | ||||
|         if (!identifyPassword(loginRequestBody.getPassword(), userDatabaseInformation.password)) { | ||||
|             throw new LoginInfoWrongException(); | ||||
|         } | ||||
| 
 | ||||
|         Date expireDate = Date.from(Instant.now().plus(JWTManager.TOKEN_DEFAULT_EXPIRE_DAY, ChronoUnit.DAYS)); | ||||
|         String userToken = jwtManager.createNewJWT(loginRequestBody.getUserName(), | ||||
|                 userDatabaseInformation.uuid, | ||||
|                 userDatabaseInformation.uid, | ||||
|                 expireDate); | ||||
| 
 | ||||
|         LoginResponseData loginResponseData = new LoginResponseData( | ||||
|                 userDatabaseInformation.uid, | ||||
|                 userDatabaseInformation.uuid, | ||||
|                 userDatabaseInformation.accountStatus, | ||||
|                 userToken, | ||||
|                 expireDate.getTime()); | ||||
| 
 | ||||
|         return ResponseBase.success(loginResponseData); | ||||
|     } | ||||
| 
 | ||||
|     private boolean identifyPassword(String originPassword, String bcryptPassword) { | ||||
|         return BCrypt.checkpw(originPassword, bcryptPassword); | ||||
|     } | ||||
| } | ||||
| @ -1,39 +0,0 @@ | ||||
| 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()); | ||||
|     } | ||||
| } | ||||
| @ -1,7 +0,0 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.auth.token; | ||||
| 
 | ||||
| public class TokenRefresher { | ||||
|     public String refreshToken(String request) { | ||||
|         return request; | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,78 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.login; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonParseException; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.requests.LoginRequestBody; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.LoginResponseData; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.general.ErrorResponse; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.general.ResponseBase; | ||||
| import me.lensfrex.trailblazer.api.v1.beans.responses.general.ResponseCode; | ||||
| import me.lensfrex.trailblazer.api.v1.exceptions.user.LoginInfoWrongException; | ||||
| import me.lensfrex.trailblazer.api.v1.pojos.UserInformation; | ||||
| import me.lensfrex.trailblazer.api.v1.utils.InputChecker; | ||||
| import me.lensfrex.trailblazer.api.v1.dao.UserDao; | ||||
| import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; | ||||
| import org.mindrot.jbcrypt.BCrypt; | ||||
| 
 | ||||
| import java.time.Instant; | ||||
| import java.time.temporal.ChronoUnit; | ||||
| import java.util.Date; | ||||
| 
 | ||||
| @Path("/login") | ||||
| public class Login { | ||||
|     private static final Gson gson = new Gson(); | ||||
|     private static final JWTManager jwtManager = JWTManager.getInstance(); | ||||
| 
 | ||||
|     @POST | ||||
|     @Produces(MediaType.APPLICATION_JSON) | ||||
|     public String login(String request) { | ||||
|         LoginRequestBody loginRequestBody; | ||||
|         try { | ||||
|             loginRequestBody = gson.fromJson(request, LoginRequestBody.class); | ||||
|             if (InputChecker.hasInvalidChar(loginRequestBody.getUserName()) || | ||||
|                     InputChecker.hasInvisibleChar(loginRequestBody.getPassword())) { | ||||
|                 ErrorResponse errorResponse = new ErrorResponse(100, "请求的用户名或密码非法"); | ||||
| 
 | ||||
|                 return gson.toJson(errorResponse); | ||||
|             } | ||||
| 
 | ||||
|             UserInformation userDatabaseInformation = UserDao.getUser(loginRequestBody.getUserName()); | ||||
| 
 | ||||
|             if (userDatabaseInformation == null) { | ||||
|                 throw new LoginInfoWrongException(); | ||||
|             } | ||||
| 
 | ||||
|             if (!identifyPassword(loginRequestBody.getPassword(), userDatabaseInformation.password)) { | ||||
|                 throw new LoginInfoWrongException(); | ||||
|             } | ||||
| 
 | ||||
|             Date expireDate = Date.from(Instant.now().plus(JWTManager.TOKEN_DEFAULT_EXPIRE_DAY, ChronoUnit.DAYS)); | ||||
|             String userToken = jwtManager.createNewJWT(loginRequestBody.getUserName(), expireDate); | ||||
| 
 | ||||
|             LoginResponseData loginResponseData = new LoginResponseData( | ||||
|                     userDatabaseInformation.uid, | ||||
|                     userDatabaseInformation.uuid, | ||||
|                     userDatabaseInformation.accountStatus, | ||||
|                     userToken, | ||||
|                     expireDate.getTime()); | ||||
| 
 | ||||
|             ResponseBase<LoginResponseData> response = ResponseBase.success(loginResponseData); | ||||
| 
 | ||||
|             return gson.toJson(response); | ||||
|         } catch (JsonParseException e) { | ||||
|             return gson.toJson(ResponseBase.error(ResponseCode.REQUEST_FORMAT_INVALID, "请求的数据格式不对")); | ||||
|         } catch (LoginInfoWrongException e) { | ||||
|             return gson.toJson(ResponseBase.error(ResponseCode.PASSWORD_WRONG, "用户名或密码错误")); | ||||
|         } catch (Exception e) { | ||||
|             return gson.toJson(ResponseBase.error(ResponseCode.SERVER_ERROR, "服务器内部错误,请联系那个背锅的家伙")); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     public boolean identifyPassword(String originPassword, String bcryptPassword) { | ||||
|         return BCrypt.checkpw(originPassword, bcryptPassword); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,19 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.profile; | ||||
| 
 | ||||
| import jakarta.ws.rs.GET; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.PathParam; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| 
 | ||||
| @Path("/profile") | ||||
| public class Profile { | ||||
| 
 | ||||
|     @GET | ||||
|     @Path("/getItems/{uid}") | ||||
|     @Produces(MediaType.APPLICATION_JSON) | ||||
|     public String getProfiles(@PathParam("uid") String uid) { | ||||
|         return "unfinished feature..."; | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| @ -0,0 +1,67 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.register; | ||||
| 
 | ||||
| import com.google.gson.Gson; | ||||
| import com.google.gson.JsonParseException; | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| 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.utils.InputChecker; | ||||
| import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; | ||||
| import org.mindrot.jbcrypt.BCrypt; | ||||
| 
 | ||||
| import java.time.Instant; | ||||
| import java.time.temporal.ChronoUnit; | ||||
| import java.util.Date; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| @Path("/register") | ||||
| public class Register { | ||||
|     private static final JWTManager jwtManager = JWTManager.getInstance(); | ||||
|     private static final Gson gson = new Gson(); | ||||
| 
 | ||||
|     @POST | ||||
|     @Produces(MediaType.APPLICATION_JSON) | ||||
|     public String register(String request) { | ||||
|         RegisterRequestBody registerRequestBody; | ||||
| 
 | ||||
|         try { | ||||
|             registerRequestBody = gson.fromJson(request, RegisterRequestBody.class); | ||||
| 
 | ||||
|             if (registerRequestBody == null || | ||||
|                     InputChecker.hasInvalidChar(registerRequestBody.getUserName()) || | ||||
|                     InputChecker.hasInvisibleChar(registerRequestBody.getPassword())) { | ||||
| 
 | ||||
|                 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)); | ||||
|         } catch (JsonParseException | RequestDataInvalidException e) { | ||||
|             return gson.toJson(ResponseBase.error(ResponseCode.REQUEST_FORMAT_INVALID, "请求的数据不正确")); | ||||
|         } catch (Exception e) { | ||||
|             return gson.toJson(ResponseBase.error(ResponseCode.SERVER_ERROR, "服务器程序发生错误,有个家伙又写bug了。Error:" + e.getMessage())); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @ -1,10 +1,18 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.auth.token; | ||||
| package me.lensfrex.trailblazer.api.v1.service.token; | ||||
| 
 | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager; | ||||
| 
 | ||||
| @Path("/token") | ||||
| public class TokenChecker { | ||||
|     public static final JWTManager jwtManager = JWTManager.getInstance(); | ||||
| 
 | ||||
|     @POST | ||||
|     @Path("/check") | ||||
|     @Produces(MediaType.APPLICATION_JSON) | ||||
|     public String checkTokenAvailable(String request) { | ||||
|         return String.valueOf(jwtManager.verifyToken(request)); | ||||
|     } | ||||
| @ -0,0 +1,16 @@ | ||||
| package me.lensfrex.trailblazer.api.v1.service.token; | ||||
| 
 | ||||
| import jakarta.ws.rs.POST; | ||||
| import jakarta.ws.rs.Path; | ||||
| import jakarta.ws.rs.Produces; | ||||
| import jakarta.ws.rs.core.MediaType; | ||||
| 
 | ||||
| @Path("/token") | ||||
| public class TokenRefresher { | ||||
|     @Path("/refresh") | ||||
|     @POST | ||||
|     @Produces(MediaType.APPLICATION_JSON) | ||||
|     public String refreshToken(String request) { | ||||
|         return request; | ||||
|     } | ||||
| } | ||||
| @ -1,2 +0,0 @@ | ||||
| server: | ||||
|   port: 64888 | ||||
					Loading…
					
					
				
		Reference in new issue