Compare commits

..

No commits in common. 'spring-dev' and 'main' have entirely different histories.

  1. 172
      API_doc.md
  2. 40
      front-end/js/events.js
  3. 18
      front-end/js/welcomepage_message.js
  4. 53
      pom.xml
  5. 17
      src/main/java/me/lensfrex/trailblazer/api/v1/ServerMain.java
  6. 70
      src/main/java/me/lensfrex/trailblazer/api/v1/beans/TokenBody.java
  7. 3
      src/main/java/me/lensfrex/trailblazer/api/v1/config/ConfigLoader.java
  8. 18
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/FeedBack.java
  9. 15
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/Index.java
  10. 49
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/login/Login.java
  11. 48
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/register/Register.java
  12. 16
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/token/TokenChecker.java
  13. 16
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/auth/token/TokenRefresher.java
  14. 15
      src/main/java/me/lensfrex/trailblazer/api/v1/controllers/profile/Profile.java
  15. 11
      src/main/java/me/lensfrex/trailblazer/api/v1/exceptions/user/UserNameAlreadyExistsException.java
  16. 20
      src/main/java/me/lensfrex/trailblazer/api/v1/service/FeedBack.java
  17. 16
      src/main/java/me/lensfrex/trailblazer/api/v1/service/Index.java
  18. 51
      src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/login/LoginService.java
  19. 39
      src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/register/RegisterService.java
  20. 7
      src/main/java/me/lensfrex/trailblazer/api/v1/service/auth/token/TokenRefresher.java
  21. 78
      src/main/java/me/lensfrex/trailblazer/api/v1/service/login/Login.java
  22. 19
      src/main/java/me/lensfrex/trailblazer/api/v1/service/profile/Profile.java
  23. 67
      src/main/java/me/lensfrex/trailblazer/api/v1/service/register/Register.java
  24. 10
      src/main/java/me/lensfrex/trailblazer/api/v1/service/token/TokenChecker.java
  25. 16
      src/main/java/me/lensfrex/trailblazer/api/v1/service/token/TokenRefresher.java
  26. 8
      src/main/java/me/lensfrex/trailblazer/api/v1/utils/jwt/JWTManager.java
  27. 2
      src/main/resources/application.yml
  28. 18
      src/main/webapp/WEB-INF/web.xml

@ -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,
> ...
> ]
> ```
*~~先这样吧~~*

@ -20,10 +20,9 @@ function login() {
function sendLogin(postData) { function sendLogin(postData) {
$.ajax({ $.ajax({
url: "/api/v1/user/login", url: "/api/v1/login",
type: "post", type: "post",
dataType: "json", dataType: "json",
contentType: "application/json",
data: JSON.stringify(postData), data: JSON.stringify(postData),
success: (result) => { success: (result) => {
console.log("获取到数据:" + JSON.stringify(result)); console.log("获取到数据:" + JSON.stringify(result));
@ -32,7 +31,6 @@ function sendLogin(postData) {
case 1: case 1:
showMessage("好啦"); showMessage("好啦");
storeToken(result.data.access_token); storeToken(result.data.access_token);
showDialog("LoginTest", "获得数据:" + JSON.stringify(result.data));
break; break;
case 2: case 2:
showMessage("请求的数据不对哦"); showMessage("请求的数据不对哦");
@ -70,10 +68,9 @@ function register() {
}; };
$.ajax({ $.ajax({
url: "/api/v1/user/register", url: "/api/v1/register",
type: "post", type: "post",
dataType: "json", dataType: "json",
contentType: "application/json",
data: JSON.stringify(postData), data: JSON.stringify(postData),
success: (result) => { success: (result) => {
console.log("获取到数据:" + JSON.stringify(result)); console.log("获取到数据:" + JSON.stringify(result));
@ -82,7 +79,6 @@ function register() {
case 1: case 1:
showMessage("好啦"); showMessage("好啦");
storeToken(result.data.access_token); storeToken(result.data.access_token);
showDialog("RegisterTest", "获得数据:" + JSON.stringify(result.data));
break; break;
case 2: case 2:
showMessage("请求的数据不对哦"); showMessage("请求的数据不对哦");
@ -107,35 +103,3 @@ function register() {
function jumpToFillInformation() { 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;
}

@ -6,6 +6,24 @@ function closeDialog() {
$("#dialogMask").fadeOut(400); $("#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) { function showMessage(message) {
$("#errMsgBox")[0].innerHTML = `<p>${message}</p>`; $("#errMsgBox")[0].innerHTML = `<p>${message}</p>`;
} }

@ -1,29 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" <project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>me.lensfrex</groupId> <groupId>me.lensfrex</groupId>
<artifactId>Trailblazer</artifactId> <artifactId>Trailblazer</artifactId>
<version>0.0.1-dev</version> <version>0.0.1-dev</version>
<name>Trailblazer</name> <name>Trailblazer</name>
<packaging>jar</packaging> <packaging>war</packaging>
<properties> <properties>
<start-class>me.lensfrex.trailblazer.api.v1.ServerMain</start-class>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target> <maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.source>1.8</maven.compiler.source>
<junit.version>5.8.1</junit.version> <junit.version>5.8.1</junit.version>
</properties> </properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.0</version>
<relativePath/>
</parent>
<dependencies> <dependencies>
<dependency> <dependency>
@ -33,6 +25,22 @@
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.inject</groupId>
<artifactId>jersey-hk2</artifactId>
<version>3.0.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency> <dependency>
<groupId>com.google.code.gson</groupId> <groupId>com.google.code.gson</groupId>
@ -85,33 +93,14 @@
<version>2.11.0</version> <version>2.11.0</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope>
</dependency>
</dependencies> </dependencies>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
<groupId>org.springframework.boot</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>maven-war-plugin</artifactId>
<version>3.3.2</version>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>

@ -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;
}
}

@ -7,6 +7,9 @@ import java.io.*;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
public class ConfigLoader { public class ConfigLoader {
private final String globalConfigFilePath; private final String globalConfigFilePath;
public ConfigLoader(String globalConfigFilePath) { public ConfigLoader(String globalConfigFilePath) {

@ -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; import me.lensfrex.trailblazer.api.v1.utils.jwt.JWTManager;
@Path("/token")
public class TokenChecker { public class TokenChecker {
public static final JWTManager jwtManager = JWTManager.getInstance(); public static final JWTManager jwtManager = JWTManager.getInstance();
@POST
@Path("/check")
@Produces(MediaType.APPLICATION_JSON)
public String checkTokenAvailable(String request) { public String checkTokenAvailable(String request) {
return String.valueOf(jwtManager.verifyToken(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;
}
}

@ -23,17 +23,15 @@ public class JWTManager {
return self; return self;
} }
public String createNewJWT(String user, String uuid, long uid, Date invalidDate) { public String createNewJWT(String user, Date invalidDate) {
Map<String, Object> header = new HashMap<>(); Map<String, Object> header = new HashMap<>();
header.put("alg", "HS256"); header.put("alg", "HS256");
header.put("typ", "JWT"); header.put("typ", "JWT");
Map<String, Object> payload = new HashMap<>(); Map<String, Object> payload = new HashMap<>();
payload.put("user", user); payload.put("user", user);
payload.put("uuid", uuid);
payload.put("uid", uid);
payload.put("api_ver", "1"); payload.put("api_ver", "1");
// payload.put("blame", machineId); // payload.put("iss", machineId);
return Jwts.builder() return Jwts.builder()
.setHeader(header) .setHeader(header)
@ -48,7 +46,7 @@ public class JWTManager {
public boolean verifyToken(String token) { public boolean verifyToken(String token) {
try { try {
Jwts.parserBuilder() Jws<Claims> jws = Jwts.parserBuilder()
.setSigningKey(key) .setSigningKey(key)
.build() .build()
.parseClaimsJws(token); .parseClaimsJws(token);

@ -1,2 +0,0 @@
server:
port: 64888

@ -6,17 +6,17 @@
<servlet> <servlet>
<servlet-name>TrailblazerApiV1</servlet-name> <servlet-name>TrailblazerApiV1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<!-- <init-param>--> <init-param>
<!-- <param-name>jersey.config.server.provider.packages</param-name>--> <param-name>jersey.config.server.provider.packages</param-name>
<!-- <param-value>me.lensfrex.trailblazer</param-value>--> <param-value>me.lensfrex.trailblazer</param-value>
<!-- </init-param>--> </init-param>
<!-- <init-param>--> <init-param>
<!-- <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>--> <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
<!-- <param-value>true</param-value>--> <param-value>true</param-value>
<!-- </init-param>--> </init-param>
</servlet> </servlet>
<servlet-mapping> <servlet-mapping>

Loading…
Cancel
Save