parent
0b920d312a
commit
fe81cb5e16
@ -0,0 +1,113 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
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"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
|
||||
<groupId>me.lensfrex</groupId> |
||||
<artifactId>LittleBusters</artifactId> |
||||
<version>0.0.1-dev</version> |
||||
<name>LittleBusters</name> |
||||
<packaging>war</packaging> |
||||
|
||||
<properties> |
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
<maven.compiler.target>1.8</maven.compiler.target> |
||||
<maven.compiler.source>1.8</maven.compiler.source> |
||||
<junit.version>5.8.1</junit.version> |
||||
</properties> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>javax.servlet</groupId> |
||||
<artifactId>javax.servlet-api</artifactId> |
||||
<version>4.0.1</version> |
||||
<scope>provided</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.junit.jupiter</groupId> |
||||
<artifactId>junit-jupiter-api</artifactId> |
||||
<version>${junit.version}</version> |
||||
<scope>test</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.junit.jupiter</groupId> |
||||
<artifactId>junit-jupiter-engine</artifactId> |
||||
<version>${junit.version}</version> |
||||
<scope>test</scope> |
||||
</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 --> |
||||
<dependency> |
||||
<groupId>com.google.code.gson</groupId> |
||||
<artifactId>gson</artifactId> |
||||
<version>2.9.0</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.mindrot/jbcrypt --> |
||||
<dependency> |
||||
<groupId>org.mindrot</groupId> |
||||
<artifactId>jbcrypt</artifactId> |
||||
<version>0.4</version> |
||||
</dependency> |
||||
|
||||
<dependency> |
||||
<groupId>io.jsonwebtoken</groupId> |
||||
<artifactId>jjwt-api</artifactId> |
||||
<version>0.11.5</version> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>io.jsonwebtoken</groupId> |
||||
<artifactId>jjwt-impl</artifactId> |
||||
<version>0.11.5</version> |
||||
<scope>runtime</scope> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>io.jsonwebtoken</groupId> |
||||
<artifactId>jjwt-gson</artifactId> <!-- or jjwt-gson if Gson is preferred --> |
||||
<version>0.11.5</version> |
||||
<scope>runtime</scope> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --> |
||||
<dependency> |
||||
<groupId>org.mybatis</groupId> |
||||
<artifactId>mybatis</artifactId> |
||||
<version>3.5.9</version> |
||||
</dependency> |
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.mariadb.jdbc/mariadb-java-client --> |
||||
<dependency> |
||||
<groupId>org.mariadb.jdbc</groupId> |
||||
<artifactId>mariadb-java-client</artifactId> |
||||
<version>3.0.4</version> |
||||
</dependency> |
||||
|
||||
|
||||
</dependencies> |
||||
|
||||
<build> |
||||
<plugins> |
||||
<plugin> |
||||
<groupId>org.apache.maven.plugins</groupId> |
||||
<artifactId>maven-war-plugin</artifactId> |
||||
<version>3.3.2</version> |
||||
</plugin> |
||||
</plugins> |
||||
</build> |
||||
</project> |
@ -0,0 +1,16 @@ |
||||
package me.lensfrex.littlebusters; |
||||
|
||||
import jakarta.ws.rs.GET; |
||||
import jakarta.ws.rs.Path; |
||||
import jakarta.ws.rs.Produces; |
||||
import jakarta.ws.rs.core.MediaType; |
||||
|
||||
@Path("/") |
||||
public class ApiIndex { |
||||
@GET |
||||
@Produces(MediaType.TEXT_HTML) |
||||
public String index() { |
||||
return "Here is the API root of LittleBusters.</br>\n" + |
||||
"To use the API currently, please see the LittleBusters RESTFul API document."; |
||||
} |
||||
} |
@ -0,0 +1,15 @@ |
||||
package me.lensfrex.littlebusters; |
||||
|
||||
import jakarta.ws.rs.GET; |
||||
import jakarta.ws.rs.Path; |
||||
import jakarta.ws.rs.Produces; |
||||
import jakarta.ws.rs.core.MediaType; |
||||
|
||||
@Path("/lb") |
||||
public class RestTest { |
||||
@GET |
||||
@Produces(MediaType.TEXT_PLAIN) |
||||
public String getMessage() { |
||||
return "ASJKDFHYG"; |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
package me.lensfrex.littlebusters.api.v1; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import jakarta.ws.rs.POST; |
||||
import jakarta.ws.rs.Path; |
||||
import jakarta.ws.rs.Produces; |
||||
import jakarta.ws.rs.core.MediaType; |
||||
import me.lensfrex.littlebusters.api.v1.dao.UserInformation; |
||||
import me.lensfrex.littlebusters.api.v1.dao.UserRegister; |
||||
import me.lensfrex.littlebusters.api.v1.responses.RegisterResponseData; |
||||
import me.lensfrex.littlebusters.api.v1.responses.general.ErrorResponse; |
||||
import me.lensfrex.littlebusters.api.v1.responses.general.ResponseBase; |
||||
import me.lensfrex.littlebusters.api.v1.utils.InputChecker; |
||||
import me.lensfrex.littlebusters.api.v1.utils.MyBatisUtil; |
||||
import org.apache.ibatis.session.SqlSession; |
||||
import org.mindrot.jbcrypt.BCrypt; |
||||
|
||||
import java.util.UUID; |
||||
|
||||
@Path("/register") |
||||
public class Register { |
||||
private final static Gson gson = new Gson(); |
||||
|
||||
@POST |
||||
@Produces(MediaType.APPLICATION_JSON) |
||||
public String register(String request) { |
||||
System.out.println("Start register."); |
||||
RegisterRequestBody registerRequestBody; |
||||
try { |
||||
registerRequestBody = gson.fromJson(request, RegisterRequestBody.class); |
||||
if (InputChecker.hasInvalidChar(registerRequestBody.userName) || |
||||
InputChecker.hasInvisibleChar(registerRequestBody.password)) { |
||||
ErrorResponse errorResponse = new ErrorResponse(1, "用户名或密码非法"); |
||||
|
||||
return gson.toJson(errorResponse); |
||||
} |
||||
} catch (Exception e) { |
||||
System.err.println(request); |
||||
ErrorResponse errorResponse = new ErrorResponse(2, "请求的数据格式不对"); |
||||
|
||||
return gson.toJson(errorResponse); |
||||
} |
||||
|
||||
String userUUID = UUID.randomUUID().toString(); |
||||
String userBcryptPasswd = BCrypt.hashpw(registerRequestBody.password, BCrypt.gensalt()); |
||||
|
||||
SqlSession sqlSession = MyBatisUtil.getSqlSession(true); |
||||
UserRegister userRegister = sqlSession.getMapper(UserRegister.class); |
||||
|
||||
userRegister.addRegisterInfoIntoDb(userUUID, registerRequestBody.userName, userBcryptPasswd); |
||||
|
||||
RegisterResponseData registerResponseBody = new RegisterResponseData(10101, userUUID, userBcryptPasswd); |
||||
ResponseBase<RegisterResponseData> response = new ResponseBase<>(200, "success", registerResponseBody); |
||||
|
||||
return gson.toJson(response); |
||||
} |
||||
|
||||
public static class RegisterRequestBody { |
||||
@SerializedName("user_name") |
||||
private String userName; |
||||
|
||||
private String password; |
||||
|
||||
public RegisterRequestBody(String userName, String password) { |
||||
this.userName = userName; |
||||
this.password = password; |
||||
} |
||||
|
||||
public String getUserName() { |
||||
return userName; |
||||
} |
||||
|
||||
public void setUserName(String userName) { |
||||
this.userName = userName; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
package me.lensfrex.littlebusters.api.v1.beans; |
||||
|
||||
public class ProfileItem { |
||||
private String itemName; |
||||
private String data; |
||||
|
||||
public ProfileItem(String itemName, String data) { |
||||
this.itemName = itemName; |
||||
this.data = data; |
||||
} |
||||
|
||||
public String getItemName() { |
||||
return itemName; |
||||
} |
||||
|
||||
public void setItemName(String itemName) { |
||||
this.itemName = itemName; |
||||
} |
||||
|
||||
public String getData() { |
||||
return data; |
||||
} |
||||
|
||||
public void setData(String data) { |
||||
this.data = data; |
||||
} |
||||
} |
@ -0,0 +1,10 @@ |
||||
package me.lensfrex.littlebusters.api.v1.dao; |
||||
|
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
import java.util.Map; |
||||
|
||||
public interface UserInformation { |
||||
|
||||
Map<String, Object> getBasicInfoByUserName(@Param("userName") String userName); |
||||
} |
@ -0,0 +1,9 @@ |
||||
package me.lensfrex.littlebusters.api.v1.dao; |
||||
|
||||
import org.apache.ibatis.annotations.Param; |
||||
|
||||
public interface UserRegister { |
||||
int addRegisterInfoIntoDb(@Param("uuid") String UUID, |
||||
@Param("userName") String userName, |
||||
@Param("password") String password); |
||||
} |
@ -0,0 +1,15 @@ |
||||
package me.lensfrex.littlebusters.api.v1; |
||||
|
||||
import jakarta.ws.rs.POST; |
||||
import jakarta.ws.rs.Path; |
||||
import jakarta.ws.rs.Produces; |
||||
import jakarta.ws.rs.core.MediaType; |
||||
|
||||
@Path("/inputTest") |
||||
public class inputTest { |
||||
@POST |
||||
@Produces(MediaType.APPLICATION_JSON) |
||||
public String inputTest(String string) { |
||||
return string; |
||||
} |
||||
} |
@ -0,0 +1,89 @@ |
||||
package me.lensfrex.littlebusters.api.v1.login; |
||||
|
||||
import com.google.gson.Gson; |
||||
import com.google.gson.JsonParseException; |
||||
import com.google.gson.annotations.SerializedName; |
||||
import com.sun.org.apache.xalan.internal.xsltc.trax.XSLTCSource; |
||||
import jakarta.ws.rs.POST; |
||||
import jakarta.ws.rs.Path; |
||||
import jakarta.ws.rs.Produces; |
||||
import jakarta.ws.rs.core.MediaType; |
||||
import me.lensfrex.littlebusters.api.v1.dao.UserInformation; |
||||
import me.lensfrex.littlebusters.api.v1.responses.LoginResponseData; |
||||
import me.lensfrex.littlebusters.api.v1.responses.general.ErrorResponse; |
||||
import me.lensfrex.littlebusters.api.v1.responses.general.ResponseBase; |
||||
import me.lensfrex.littlebusters.api.v1.utils.InputChecker; |
||||
import me.lensfrex.littlebusters.api.v1.utils.MyBatisUtil; |
||||
import org.apache.ibatis.session.SqlSession; |
||||
import org.mindrot.jbcrypt.BCrypt; |
||||
|
||||
import java.math.BigInteger; |
||||
import java.time.LocalDate; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
@Path("/login") |
||||
public class Login { |
||||
private final static Gson gson = new Gson(); |
||||
|
||||
@POST |
||||
@Produces(MediaType.APPLICATION_JSON) |
||||
public String login(String request) { |
||||
LoginRequestBody loginRequestBody; |
||||
try { |
||||
loginRequestBody = gson.fromJson(request, LoginRequestBody.class); |
||||
if (InputChecker.hasInvalidChar(loginRequestBody.userName) || |
||||
InputChecker.hasInvisibleChar(loginRequestBody.password)) { |
||||
ErrorResponse errorResponse = new ErrorResponse(100, "请求的用户名或密码非法"); |
||||
|
||||
return gson.toJson(errorResponse); |
||||
} |
||||
|
||||
if () |
||||
LoginResponseData loginResponseData = new LoginResponseData(((BigInteger) selectResult.get("uid")).intValue(), (String) selectResult.get("password"), LocalDate.now().toString()); |
||||
ResponseBase<LoginResponseData> response = new ResponseBase<>(200, "success", loginResponseData); |
||||
|
||||
return gson.toJson(response); |
||||
|
||||
} catch (JsonParseException e) { |
||||
System.err.println(request); |
||||
|
||||
ErrorResponse errorResponse = new ErrorResponse(300, "请求的数据格式不对"); |
||||
return gson.toJson(errorResponse); |
||||
} catch (Exception e) { |
||||
System.err.println(request); |
||||
System.err.println(e.getMessage()); |
||||
|
||||
ErrorResponse errorResponse = new ErrorResponse(400, "服务器内部错误,请联系那个背锅的家伙。"); |
||||
return gson.toJson(errorResponse); |
||||
} |
||||
} |
||||
|
||||
public static class LoginRequestBody { |
||||
@SerializedName("user_name") |
||||
private String userName; |
||||
|
||||
private String password; |
||||
|
||||
public LoginRequestBody(String userName, String password) { |
||||
this.userName = userName; |
||||
this.password = password; |
||||
} |
||||
|
||||
public String getUserName() { |
||||
return userName; |
||||
} |
||||
|
||||
public void setUserName(String userName) { |
||||
this.userName = userName; |
||||
} |
||||
|
||||
public String getPassword() { |
||||
return password; |
||||
} |
||||
|
||||
public void setPassword(String password) { |
||||
this.password = password; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
package me.lensfrex.littlebusters.api.v1.login; |
||||
|
||||
import me.lensfrex.littlebusters.api.v1.dao.UserInformation; |
||||
import me.lensfrex.littlebusters.api.v1.utils.MyBatisUtil; |
||||
import org.apache.ibatis.session.SqlSession; |
||||
import org.mindrot.jbcrypt.BCrypt; |
||||
|
||||
|
||||
import java.util.Map; |
||||
|
||||
public class LoginIdentify { |
||||
|
||||
public boolean identifyLoginUserName(String userName, String passwordSHA256) { |
||||
SqlSession sqlSession = MyBatisUtil.getSqlSession(true); |
||||
|
||||
UserInformation mapper = sqlSession.getMapper(UserInformation.class); |
||||
Map<String, Object> selectResult = mapper.getBasicInfoByUserName(userName); |
||||
if (selectResult == null) { |
||||
return false; |
||||
} |
||||
|
||||
return BCrypt.checkpw(passwordSHA256, (String) selectResult.get("password")); |
||||
} |
||||
} |
@ -0,0 +1,17 @@ |
||||
package me.lensfrex.littlebusters.api.v1.pojos; |
||||
|
||||
public class UserResult { |
||||
public final int uid; |
||||
public final String UUID; |
||||
public final String password; |
||||
public final boolean deleted; |
||||
public final short accountStatus; |
||||
|
||||
public UserResult(int uid, String UUID, String password, boolean deleted, short accountStatus) { |
||||
this.uid = uid; |
||||
this.UUID = UUID; |
||||
this.password = password; |
||||
this.deleted = deleted; |
||||
this.accountStatus = accountStatus; |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
package me.lensfrex.littlebusters.api.v1.responses; |
||||
|
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
/** |
||||
* 登录响应中data字段的对象 |
||||
*/ |
||||
public class LoginResponseData { |
||||
/** |
||||
* 登录用户的uid |
||||
*/ |
||||
private int uid; |
||||
|
||||
/** |
||||
* 用户本次登录得到的token |
||||
*/ |
||||
@SerializedName("access_token") |
||||
private String accessToken; |
||||
|
||||
/** |
||||
* 用户此次得到的token的过期时间 |
||||
*/ |
||||
@SerializedName("expired_at") |
||||
private String expiredAt; |
||||
|
||||
public LoginResponseData(int uid, String accessToken, String expiredAt) { |
||||
this.uid = uid; |
||||
this.accessToken = accessToken; |
||||
this.expiredAt = expiredAt; |
||||
} |
||||
|
||||
public int getUid() { |
||||
return uid; |
||||
} |
||||
|
||||
public void setUid(int uid) { |
||||
this.uid = uid; |
||||
} |
||||
|
||||
public String getAccessToken() { |
||||
return accessToken; |
||||
} |
||||
|
||||
public void setAccessToken(String accessToken) { |
||||
this.accessToken = accessToken; |
||||
} |
||||
|
||||
public String getExpiredAt() { |
||||
return expiredAt; |
||||
} |
||||
|
||||
public void setExpiredAt(String expiredAt) { |
||||
this.expiredAt = expiredAt; |
||||
} |
||||
} |
@ -0,0 +1,24 @@ |
||||
package me.lensfrex.littlebusters.api.v1.responses; |
||||
|
||||
import me.lensfrex.littlebusters.api.v1.beans.ProfileItem; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
public class ProfileResponseData { |
||||
private List<ProfileItem> profileItems; |
||||
|
||||
public ProfileResponseData(List<ProfileItem> profileItems) { |
||||
this.profileItems = new ArrayList<>(profileItems); |
||||
} |
||||
|
||||
public List<ProfileItem> getProfileItems() { |
||||
return profileItems; |
||||
} |
||||
|
||||
public void setProfileItems(List<ProfileItem> profileItems) { |
||||
this.profileItems = profileItems; |
||||
} |
||||
} |
||||
|
||||
|
@ -0,0 +1,52 @@ |
||||
package me.lensfrex.littlebusters.api.v1.responses; |
||||
|
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
public class RegisterResponseData { |
||||
/** |
||||
* 用户注册分派到的uid |
||||
*/ |
||||
private int uid; |
||||
|
||||
/** |
||||
* 用户本次注册时得到的token |
||||
*/ |
||||
@SerializedName("access_token") |
||||
private String accessToken; |
||||
|
||||
/** |
||||
* 用户此次得到的token的过期时间 |
||||
*/ |
||||
@SerializedName("expired_at") |
||||
private String expiredAt; |
||||
|
||||
public RegisterResponseData(int uid, String accessToken, String expiredAt) { |
||||
this.uid = uid; |
||||
this.accessToken = accessToken; |
||||
this.expiredAt = expiredAt; |
||||
} |
||||
|
||||
public int getUid() { |
||||
return uid; |
||||
} |
||||
|
||||
public void setUid(int uid) { |
||||
this.uid = uid; |
||||
} |
||||
|
||||
public String getAccessToken() { |
||||
return accessToken; |
||||
} |
||||
|
||||
public void setAccessToken(String accessToken) { |
||||
this.accessToken = accessToken; |
||||
} |
||||
|
||||
public String getExpiredAt() { |
||||
return expiredAt; |
||||
} |
||||
|
||||
public void setExpiredAt(String expiredAt) { |
||||
this.expiredAt = expiredAt; |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
package me.lensfrex.littlebusters.api.v1.responses.general; |
||||
|
||||
/** |
||||
* 错误响应类。 |
||||
*/ |
||||
public class ErrorResponse extends ResponseBase<ErrorData> { |
||||
public ErrorResponse(int code, String message) { |
||||
super(code, message, null); |
||||
} |
||||
} |
||||
|
||||
class ErrorData {} |
||||
|
||||
class ErrorCode { |
||||
public static final int REQUEST_PARAM_INVALID = 100; |
||||
} |
@ -0,0 +1,53 @@ |
||||
package me.lensfrex.littlebusters.api.v1.responses.general; |
||||
|
||||
import com.google.gson.annotations.SerializedName; |
||||
|
||||
public class ResponseBase<T> { |
||||
/** |
||||
* 信息码 |
||||
*/ |
||||
private int code; |
||||
|
||||
/** |
||||
* 处理信息 |
||||
*/ |
||||
@SerializedName("msg") |
||||
private String message; |
||||
|
||||
private T data; |
||||
|
||||
/** |
||||
* 构造一个基本响应 |
||||
* @param code 信息码 |
||||
* @param message 处理信息 |
||||
*/ |
||||
public ResponseBase(int code, String message, T data) { |
||||
this.code = code; |
||||
this.message = message; |
||||
this.data = data; |
||||
} |
||||
|
||||
public int getCode() { |
||||
return code; |
||||
} |
||||
|
||||
public void setCode(int code) { |
||||
this.code = code; |
||||
} |
||||
|
||||
public String getMessage() { |
||||
return message; |
||||
} |
||||
|
||||
public void setMessage(String message) { |
||||
this.message = message; |
||||
} |
||||
|
||||
public T getData() { |
||||
return data; |
||||
} |
||||
|
||||
public void setData(T data) { |
||||
this.data = data; |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
package me.lensfrex.littlebusters.api.v1.utils; |
||||
|
||||
public class InputChecker { |
||||
|
||||
public static boolean hasInvalidChar(String input) { |
||||
char[] source = input.toCharArray(); |
||||
for (char c : source) { |
||||
if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || |
||||
(c >= '0' && c <= '9'))) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
public static boolean hasInvisibleChar(String input) { |
||||
char[] source = input.toCharArray(); |
||||
for (char c : source) { |
||||
if (!(c >= ' ' && c <= '~')) { |
||||
return true; |
||||
} |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
} |
@ -0,0 +1,28 @@ |
||||
package me.lensfrex.littlebusters.api.v1.utils; |
||||
|
||||
import org.apache.ibatis.io.Resources; |
||||
import org.apache.ibatis.session.SqlSession; |
||||
import org.apache.ibatis.session.SqlSessionFactory; |
||||
import org.apache.ibatis.session.SqlSessionFactoryBuilder; |
||||
|
||||
import java.io.IOException; |
||||
import java.io.InputStream; |
||||
|
||||
public class MyBatisUtil { |
||||
|
||||
private static SqlSessionFactory sqlSessionFactory; |
||||
|
||||
static { |
||||
try { |
||||
String resource = "mybatis-config.xml"; |
||||
InputStream inputStream = Resources.getResourceAsStream(resource); |
||||
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
|
||||
public static SqlSession getSqlSession(boolean autoCommit) { |
||||
return sqlSessionFactory.openSession(autoCommit); |
||||
} |
||||
} |
@ -0,0 +1,13 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<!DOCTYPE mapper |
||||
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" |
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
||||
<mapper namespace="me.lensfrex.littlebusters.api.v1.dao.UserInformation"> |
||||
<select id="getBasicInfoByUserName" resultType="Map" parameterType="java.lang.String"> |
||||
select uid, uuid, passwd as password, deleted, account_status as accountStstus |
||||
from `account_basic` |
||||
where user_name = #{userName} |
||||
</select> |
||||
</mapper> |
@ -0,0 +1,12 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
||||
<!DOCTYPE mapper |
||||
PUBLIC "-//mybatis.org//DTD Config 3.0//EN" |
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
||||
|
||||
<mapper namespace="me.lensfrex.littlebusters.api.v1.dao.UserRegister"> |
||||
<insert id="addRegisterInfoIntoDb"> |
||||
insert into `LittleBusters`.`account_basic` (`uuid`, `user_name`, `passwd`) |
||||
values (#{uuid}, #{userName}, #{password}) |
||||
</insert> |
||||
</mapper> |
@ -0,0 +1,93 @@ |
||||
<!DOCTYPE html> |
||||
|
||||
<head> |
||||
<title>出问题啦 - 真不愧是lensfrex的破站呢</title> |
||||
<meta http-equiv="Content-Type" name="viewport" content="text/html width=device-width initial-scale=1" |
||||
charset=utf-8> |
||||
<style> |
||||
a { |
||||
text-decoration: none; |
||||
font-size: 15.0pt; |
||||
font-family: sans-serif; |
||||
margin-top: 10.0pt; |
||||
margin-bottom: 10.0pt; |
||||
color: rgb(255, 255, 255); |
||||
} |
||||
|
||||
/* a:hover { |
||||
text-decoration: none; |
||||
} */ |
||||
|
||||
body { |
||||
word-wrap: break-word; |
||||
background-image: url(https://res.ciduid.top/blog/backgrounds/95761609_p0_land_processed.jpg); |
||||
background-position: 45% 0; |
||||
background-repeat: no-repeat; |
||||
background-attachment: fixed; |
||||
background-size: cover; |
||||
} |
||||
|
||||
#button_box { |
||||
background-color: rgba(102, 51, 153, 0.45); |
||||
border-radius: 10px; |
||||
padding: 7px 10px 7px 10px; |
||||
margin: 0 auto; |
||||
max-inline-size: fit-content; |
||||
text-align: left; |
||||
} |
||||
|
||||
.button { |
||||
font-size: 15.0pt; |
||||
font-family: sans-serif; |
||||
margin-top: 10.0pt; |
||||
margin-bottom: 10.0pt; |
||||
color: rgb(255, 255, 255); |
||||
} |
||||
|
||||
.center_box { |
||||
text-align: center; |
||||
} |
||||
|
||||
.title { |
||||
text-align: center; |
||||
font-size: 40.0pt; |
||||
color: white; |
||||
} |
||||
|
||||
.msg { |
||||
font-size: 20.0pt; |
||||
font-family: -webkit-body; |
||||
color: white; |
||||
} |
||||
</style> |
||||
</head> |
||||
|
||||
<body lang="ZH-CN"> |
||||
<div> |
||||
<div id="main_div"> |
||||
<!-- <p id="title" align="center" style="text-align:center; font-size: 40.0pt; color: white;">50x error page</p> --> |
||||
<p class="title">找不到页面...</p> |
||||
|
||||
<hr color="white" size="10"> |
||||
|
||||
<div class="center_box"> |
||||
<p class="msg">找不到你要访问的页面哟</p> |
||||
<p class="msg">是不是把地址给搞错了?</p> |
||||
</div> |
||||
<div class="center_box" style="margin-top: 100px;"> |
||||
<!-- <br><br> --> |
||||
<div id="button_box"> |
||||
<a href="https://huhu.ciduid.top" class="button"> |
||||
-> 要不,去博客那里瞧瞧? |
||||
</a> |
||||
<br><br> |
||||
<a href="javascript:history.back(-1)" class="button"> |
||||
-> 还是说只是想回上一页? |
||||
</a> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</body> |
||||
|
||||
</html> |
@ -0,0 +1,27 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" |
||||
version="4.0"> |
||||
|
||||
<servlet> |
||||
<servlet-name>LittleBustersApiV1</servlet-name> |
||||
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> |
||||
|
||||
<init-param> |
||||
<param-name>jersey.config.server.provider.packages</param-name> |
||||
<param-value>me.lensfrex.littlebusters</param-value> |
||||
</init-param> |
||||
|
||||
<init-param> |
||||
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name> |
||||
<param-value>true</param-value> |
||||
</init-param> |
||||
</servlet> |
||||
|
||||
<servlet-mapping> |
||||
<servlet-name>LittleBustersApiV1</servlet-name> |
||||
<url-pattern>/api/v1/*</url-pattern> |
||||
</servlet-mapping> |
||||
|
||||
</web-app> |
@ -0,0 +1,180 @@ |
||||
body { |
||||
word-wrap: break-word; |
||||
/* background: url(https://res.ciduid.top/static/imgs/compressed/93527505_p0_conpressed.jpg) no-repeat fixed; */ |
||||
background-position: 45% 0; |
||||
background-size: cover; |
||||
} |
||||
|
||||
.login-box { |
||||
background-color: rgb(256, 256, 256, 0.6); |
||||
position: fixed; |
||||
top: 10%; |
||||
left: 5%; |
||||
border-radius: 15px; |
||||
padding: 20px 20px 17px 20px; |
||||
} |
||||
|
||||
.input-field-group { |
||||
transition: height .5s; |
||||
} |
||||
|
||||
.login-box-title { |
||||
font-size: 45px; |
||||
padding-bottom: 40px; |
||||
} |
||||
|
||||
.input-field input { |
||||
width: 400px; |
||||
height: 40px; |
||||
font-family: Consolas monospace; |
||||
padding-left: 10px; |
||||
font-size: 16px; |
||||
font-weight: bold; |
||||
border-radius: 10px; |
||||
border: none; |
||||
background: rgba(256, 256, 256, 0.6); |
||||
outline: none; |
||||
outline: 0; |
||||
transition: background-color .5s; |
||||
} |
||||
|
||||
.input-field input:focus { |
||||
background-color: rgb(214, 234, 248, 0.6); |
||||
} |
||||
|
||||
.input-field { |
||||
margin-bottom: 15px; |
||||
} |
||||
|
||||
/* 仿的是pixiv上登录页的按钮 */ |
||||
.operator-box .big-button { |
||||
display: block; |
||||
margin-top: 15px; |
||||
margin-bottom: 15px; |
||||
width: 190px; |
||||
height: 40px; |
||||
line-height: 40px; |
||||
border-radius: 10px; |
||||
border-style: none; |
||||
color: #fff; |
||||
|
||||
outline: none; |
||||
font-weight: 700; |
||||
font-size: 14px; |
||||
text-align: center; |
||||
transition: background-color .2s; |
||||
cursor: pointer; |
||||
display: inline-block; |
||||
text-decoration: none; |
||||
} |
||||
|
||||
#login-botton { |
||||
background-color: rgb(0 150 250); |
||||
} |
||||
|
||||
#register-botton { |
||||
background-color: rgb(34 139 34); |
||||
} |
||||
|
||||
.botton-box { |
||||
text-align: center; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
} |
||||
|
||||
.operator-box .big-button:hover { |
||||
background-color: #0382d6; |
||||
} |
||||
|
||||
.operator-box .rl-layout-box .small-link { |
||||
cursor: pointer; |
||||
} |
||||
|
||||
.rl-layout-box { |
||||
text-align: center; |
||||
display: flex; |
||||
justify-content: space-between; |
||||
/* line-height: 25px; */ |
||||
} |
||||
|
||||
#dialogMask { |
||||
width: 100%; |
||||
height: 100%; |
||||
word-wrap: break-word; |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
background: rgb(45 44 44 / 45%); |
||||
transition: background 300ms; |
||||
z-index: 1001; |
||||
display: none; |
||||
} |
||||
|
||||
#background { |
||||
width: 100%; |
||||
height: 100%; |
||||
background: url(https://res.ciduid.top/static/imgs/compressed/93527505_p0_conpressed.jpg) no-repeat fixed; |
||||
background-position: 45% 0; |
||||
background-size: cover; |
||||
word-wrap: break-word; |
||||
position: fixed; |
||||
top: 0; |
||||
left: 0; |
||||
z-index: -1; |
||||
filter: blur(1.5px); |
||||
/* 稍微放大除白边 */ |
||||
transform: scale(1.01); |
||||
} |
||||
|
||||
.dialogContentBox { |
||||
display: block; |
||||
position: fixed; |
||||
top: 50%; |
||||
left: 50%; |
||||
width: 435px; |
||||
/* height: 313px; */ |
||||
margin-left: -227px; |
||||
margin-top: -200px; |
||||
box-shadow: 2px 2px 11px #a0a0a0, -2px -2px 4px #a0a0a0; |
||||
background-color: #fff; |
||||
border-radius: 15px; |
||||
padding: 30px 20px 15px 20px; |
||||
} |
||||
|
||||
.dialogContentBox .titleBox { |
||||
} |
||||
|
||||
.dialogContentBox .titleBox #title { |
||||
font-size: 30px; |
||||
margin: auto auto 15px auto; |
||||
} |
||||
|
||||
.dialogContentBox .bodyBox p { |
||||
font-size: 20px; |
||||
} |
||||
|
||||
.dialogContentBox .bottonBox { |
||||
text-align: right; |
||||
/* margin: auto auto 15px auto; */ |
||||
} |
||||
|
||||
.dialogContentBox .bottonBox #okbtn { |
||||
border: none; |
||||
background: rgb(0 150 250); |
||||
cursor: pointer; |
||||
color: white; |
||||
font-family: sans-serif; |
||||
font-size: 16px; |
||||
border-radius: 5px; |
||||
height: 31px; |
||||
width: 80px; |
||||
} |
||||
|
||||
#errMsgBox p { |
||||
margin: 0 0 0 0; |
||||
color: red; |
||||
} |
||||
|
||||
@media screen and (max-width: 494px) { |
||||
|
||||
} |
After Width: | Height: | Size: 128 KiB |
@ -0,0 +1,52 @@ |
||||
<!DOCTYPE html> |
||||
<html lang="zh"> |
||||
|
||||
<head> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1"> |
||||
<title>欢迎 - LittleBusters</title> |
||||
|
||||
<link rel="stylesheet" type="text/css" href="css\welcomepage.css"> |
||||
|
||||
<script src="js/sha256-min.js"></script> |
||||
<script src="js/jquery-3.6.0.min.js"></script> |
||||
|
||||
<script src="js/utils.js"></script> |
||||
<script src="js/welcomepage_message.js"></script> |
||||
<script src="js/events.js"></script> |
||||
<script src="js/init.js"></script> |
||||
<!--[if IE]><script>alert("别用IE浏览器啦,快换一个吧!");</script><![endif]--> |
||||
|
||||
</head> |
||||
|
||||
<!-- 前端不擅长,逻辑做的很简单,见谅 ( ̄﹏ ̄;)--> |
||||
|
||||
<body lang="ZH-CN"> |
||||
<div id="content"> |
||||
<div id="background"></div> |
||||
<div id="dialogMask"></div> |
||||
<div class="login-box"> |
||||
<div class="login-box-title">登录/注册</div> |
||||
<div class="input-field-group"> |
||||
<div class="input-field"> |
||||
<input id="username" type="text" autocomplete="username" placeholder="用户名/UID"> |
||||
</div> |
||||
<div class="input-field"> |
||||
<input id="passwd" type="password" autocomplete="current-password" placeholder="密码"> |
||||
</div> |
||||
<div id="errMsgBox"></div> |
||||
</div> |
||||
<div class="operator-box"> |
||||
<div class="botton-box"> |
||||
<button class="big-button" type="submit" id="register-botton">注册</button> |
||||
<button class="big-button" type="submit" id="login-botton">登录</button> |
||||
</div> |
||||
<div class="rl-layout-box"> |
||||
<a class="small-link" id="forgotPasswordLabel">不记得密码了?</a> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</body> |
||||
|
||||
</html> |
@ -0,0 +1,28 @@ |
||||
function login() { |
||||
console.log("start login"); |
||||
username = $("#username").val(); |
||||
password = $("#passwd").val(); |
||||
|
||||
if (!checkInputDataCorrect(username, password)) { |
||||
return; |
||||
} |
||||
|
||||
encPassword = encryptPassword(password); |
||||
postData = { |
||||
"user_name": username, |
||||
"password": encPassword |
||||
}; |
||||
|
||||
$.ajax({ |
||||
url: "/api/v1/login", |
||||
type: "post", |
||||
dataType: "json", |
||||
data: JSON.stringify(postData), |
||||
success: (result) => { |
||||
showDialog("Test", "获取到数据:" + JSON.stringify(result)); |
||||
}, |
||||
error: (msg, status) => { |
||||
showMessage("登陆时发生错误:",JSON.stringify(msg)); |
||||
} |
||||
}) |
||||
} |
@ -0,0 +1,12 @@ |
||||
init(); |
||||
|
||||
function init() { |
||||
addEventListeners(); |
||||
} |
||||
|
||||
function addEventListeners() { |
||||
$(document).on("click", "#register-botton", register); |
||||
$(document).on("click", "#login-botton", login); |
||||
$(document).on("click", "#forgotPasswordLabel", forgotPasswd); |
||||
} |
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,16 @@ |
||||
/* |
||||
CryptoJS v3.1.2 |
||||
code.google.com/p/crypto-js |
||||
(c) 2009-2013 by Jeff Mott. All rights reserved. |
||||
code.google.com/p/crypto-js/wiki/License |
||||
*/ |
||||
var CryptoJS=CryptoJS||function(h,s){var f={},t=f.lib={},g=function(){},j=t.Base={extend:function(a){g.prototype=this;var c=new g;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, |
||||
q=t.WordArray=j.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=s?c:4*a.length},toString:function(a){return(a||u).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e<a;e++)c[b+e>>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535<d.length)for(e=0;e<a;e+=4)c[b+e>>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< |
||||
32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=j.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d<a;d+=4)c.push(4294967296*h.random()|0);return new q.init(c,a)}}),v=f.enc={},u=v.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b<a;b++){var e=c[b>>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b<c;b+=2)d[b>>>3]|=parseInt(a.substr(b, |
||||
2),16)<<24-4*(b%8);return new q.init(d,c/2)}},k=v.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b<a;b++)d.push(String.fromCharCode(c[b>>>2]>>>24-8*(b%4)&255));return d.join("")},parse:function(a){for(var c=a.length,d=[],b=0;b<c;b++)d[b>>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new q.init(d,c)}},l=v.Utf8={stringify:function(a){try{return decodeURIComponent(escape(k.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return k.parse(unescape(encodeURIComponent(a)))}}, |
||||
x=t.BufferedBlockAlgorithm=j.extend({reset:function(){this._data=new q.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=l.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var m=0;m<a;m+=e)this._doProcessBlock(d,m);m=d.splice(0,a);c.sigBytes-=b}return new q.init(m,b)},clone:function(){var a=j.clone.call(this); |
||||
a._data=this._data.clone();return a},_minBufferSize:0});t.Hasher=x.extend({cfg:j.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){x.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(c,d){return(new a.init(d)).finalize(c)}},_createHmacHelper:function(a){return function(c,d){return(new w.HMAC.init(a, |
||||
d)).finalize(c)}}});var w=f.algo={};return f}(Math); |
||||
(function(h){for(var s=CryptoJS,f=s.lib,t=f.WordArray,g=f.Hasher,f=s.algo,j=[],q=[],v=function(a){return 4294967296*(a-(a|0))|0},u=2,k=0;64>k;){var l;a:{l=u;for(var x=h.sqrt(l),w=2;w<=x;w++)if(!(l%w)){l=!1;break a}l=!0}l&&(8>k&&(j[k]=v(h.pow(u,0.5))),q[k]=v(h.pow(u,1/3)),k++);u++}var a=[],f=f.SHA256=g.extend({_doReset:function(){this._hash=new t.init(j.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],m=b[2],h=b[3],p=b[4],j=b[5],k=b[6],l=b[7],n=0;64>n;n++){if(16>n)a[n]= |
||||
c[d+n]|0;else{var r=a[n-15],g=a[n-2];a[n]=((r<<25|r>>>7)^(r<<14|r>>>18)^r>>>3)+a[n-7]+((g<<15|g>>>17)^(g<<13|g>>>19)^g>>>10)+a[n-16]}r=l+((p<<26|p>>>6)^(p<<21|p>>>11)^(p<<7|p>>>25))+(p&j^~p&k)+q[n]+a[n];g=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&m^f&m);l=k;k=j;j=p;p=h+r|0;h=m;m=f;f=e;e=r+g|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+m|0;b[3]=b[3]+h|0;b[4]=b[4]+p|0;b[5]=b[5]+j|0;b[6]=b[6]+k|0;b[7]=b[7]+l|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes; |
||||
d[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=g.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=g._createHelper(f);s.HmacSHA256=g._createHmacHelper(f)})(Math); |
@ -0,0 +1,28 @@ |
||||
function isLetter(source) { |
||||
for (i = 0; i < source.length; i++) { |
||||
char = source.charCodeAt(i); |
||||
if (!((char >= 65 && char <= 90) || |
||||
(char >= 97 && char <= 122) || |
||||
(char >= 48 && char <= 57))) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
function isNormalCharacter(source) { |
||||
for (i = 0; i < source.length; i++) { |
||||
char = source.charCodeAt(i); |
||||
if (!(char >= 32 && char <= 126)) { |
||||
return false; |
||||
} |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
function encryptPassword(password) { |
||||
sha256 = CryptoJS.SHA256; |
||||
return sha256(sha256(password).toString()).toString(); |
||||
} |
@ -0,0 +1,54 @@ |
||||
function forgotPasswd() { |
||||
showDialog("( ̄﹏ ̄;)", "欸这个嘛...我还没做完呢...( ̄﹏ ̄;)"); |
||||
} |
||||
|
||||
function register() { |
||||
showDialog("( ̄﹏ ̄;)", "欸这个嘛...我还没做完呢...( ̄﹏ ̄;)"); |
||||
} |
||||
|
||||
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 = `<p>${message}</p>`; |
||||
} |
||||
|
||||
function showDialog(title, message) { |
||||
html = `<div class="dialogContentBox">
|
||||
<div class="titleBox"> |
||||
<p id="title">${title}</p> |
||||
</div><hr> |
||||
<div class="bodyBox"> |
||||
<p id="bodyText">${message}</p> |
||||
</div> |
||||
<div class="bottonBox"> |
||||
<button id="okbtn">知道啦</button> |
||||
</div> |
||||
</div>`; |
||||
|
||||
dialogMask = $("#dialogMask"); |
||||
|
||||
dialogMask[0].innerHTML = html; |
||||
$(".dialogContentBox .bottonBox #okbtn").click(closeDialog); |
||||
dialogMask.fadeIn(400); |
||||
dialogMask.css("display", "block"); |
||||
} |
Loading…
Reference in new issue