commit 894f8741e7f50812426b2b63788e3c44e6b175fb Author: davy126dell Date: Mon Apr 21 16:00:42 2025 +0800 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..35410ca --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# 默认忽略的文件 +/shelf/ +/workspace.xml +# 基于编辑器的 HTTP 客户端请求 +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/dataSources.xml b/.idea/dataSources.xml new file mode 100644 index 0000000..7b770aa --- /dev/null +++ b/.idea/dataSources.xml @@ -0,0 +1,30 @@ + + + + + mysql.8 + true + com.mysql.cj.jdbc.Driver + jdbc:mysql://114.115.137.102:3306 + + + + + + $ProjectFileDir$ + + + mysql.8 + true + com.mysql.cj.jdbc.Driver + jdbc:mysql://10.11.25.79:3306 + + + + + + + $ProjectFileDir$ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d4829c0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..9a6dd14 --- /dev/null +++ b/pom.xml @@ -0,0 +1,67 @@ + + 4.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 3.1.3 + + org.example + big-event + 1.0-SNAPSHOT + jar + + big-event + http://maven.apache.org + + + UTF-8 + + + + + + org.springframework.boot + spring-boot-starter-web + + + + + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 3.0.0 + + + + + com.mysql + mysql-connector-j + + + + + org.projectlombok + lombok + + + + org.springframework.boot + spring-boot-starter-validation + + + + com.auth0 + java-jwt + 3.14.0 + + + + org.springframework.boot + spring-boot-starter-actuator + + + + diff --git a/src/main/java/org/example/BigEventApplication.java b/src/main/java/org/example/BigEventApplication.java new file mode 100644 index 0000000..98ba7f0 --- /dev/null +++ b/src/main/java/org/example/BigEventApplication.java @@ -0,0 +1,20 @@ +package org.example; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +/** + * Hello world! + * + */ +@SpringBootApplication +public class BigEventApplication +{ + public static void main( String[] args ) + { +// SpringApplication.run(BigEventApplication.class,args); + SpringApplication.run(BigEventApplication.class,args); + + } +} diff --git a/src/main/java/org/example/config/WebConfig.java b/src/main/java/org/example/config/WebConfig.java new file mode 100644 index 0000000..b131835 --- /dev/null +++ b/src/main/java/org/example/config/WebConfig.java @@ -0,0 +1,25 @@ +package org.example.config; + +import org.example.interceptors.LoginInterceptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + + @Autowired + private LoginInterceptor loginInterceptor; + @Override + public void addInterceptors(InterceptorRegistry registry) { + System.out.println("Registering LoginInterceptor..."); + //login page and login api don't need to be intercepted + registry.addInterceptor(loginInterceptor) + .addPathPatterns("/**") + .excludePathPatterns("/user/login", "/user/register"); + } +} diff --git a/src/main/java/org/example/controller/ArticleController.java b/src/main/java/org/example/controller/ArticleController.java new file mode 100644 index 0000000..c094c9a --- /dev/null +++ b/src/main/java/org/example/controller/ArticleController.java @@ -0,0 +1,32 @@ +package org.example.controller; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.example.pojo.Result; +import org.example.utils.JwtUtil; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + + +@RestController +@RequestMapping("/article") +public class ArticleController { + @GetMapping("/list") + public Result list(/*@RequestHeader(name = "Authorization") String token, HttpServletResponse response*/) { + //验证token +// try { +// Map clains = JwtUtil.parseToken(token); +// +// }catch (Exception e) { +// response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); +// return Result.error("login error"); +// } +// +// } + return Result.success("all"); + } +} diff --git a/src/main/java/org/example/controller/UserController.java b/src/main/java/org/example/controller/UserController.java new file mode 100644 index 0000000..3cd7126 --- /dev/null +++ b/src/main/java/org/example/controller/UserController.java @@ -0,0 +1,62 @@ +package org.example.controller; + +import jakarta.validation.constraints.Pattern; +import org.example.pojo.Result; +import org.example.pojo.User; +import org.example.service.UserService; +import org.example.utils.JwtUtil; +import org.example.utils.Md5Util; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/user") +@Validated +public class UserController { + + @Autowired + private UserService userService; + + @PostMapping("/register") + public Result register(@Pattern(regexp = "^[a-zA-Z0-9_-]{6,16}$")String username, @Pattern(regexp = "^[a-zA-Z0-9_-]{6,16}$") String password) { + //查询用户 + System.out.println("Register - Username: " + username); + User u = userService.findByUsername(username); + if (u != null) + return Result.error("用户名已存在"); + //注册用户 + userService.register(username, password); + return Result.success(); + } + @PostMapping("/login") + public Result login(@Pattern(regexp = "^[a-zA-Z0-9_-]{3,16}$") String username, @Pattern(regexp = "^[a-zA-Z0-9_-]{6,16}$") String password) { + //查询用户 + User u = userService.findByUsername(username); + if (u == null) + return Result.error("用户名不存在"); + //校验密码 + if (!u.getPassword().equals(Md5Util.getMD5String(password))) + return Result.error("密码错误"); + //登录成功 + Map claims = new HashMap<>(); + claims.put("id", u.getId()); + claims.put("username", u.getUsername()); + String token = JwtUtil.genToken(claims); + return Result.success(token); + } + + @GetMapping("/info") + public Result info(@RequestHeader(name = "Authorization") String token) { + Map map = JwtUtil.parseToken(token); + if (map == null) + return Result.error("token无效"); + User u = userService.findByUsername(map.get("username").toString()); + if (u == null) + return Result.error("用户不存在"); + return Result.success(u); + } +} diff --git a/src/main/java/org/example/exception/GlobalExceptionHandler.java b/src/main/java/org/example/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..c88efd8 --- /dev/null +++ b/src/main/java/org/example/exception/GlobalExceptionHandler.java @@ -0,0 +1,21 @@ +package org.example.exception; + +import org.springframework.util.StringUtils; +import org.example.pojo.Result; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + @ExceptionHandler(Exception.class) + public Result handleException(Exception e) { + e.printStackTrace(); + // 提取 e.getMessage() 的值到局部变量,减少重复调用 + String errorMessage = e.getMessage(); + // 检查 errorMessage 是否为空或长度为 0,提供默认值 "操作失败" + errorMessage = StringUtils.hasLength(errorMessage) ? errorMessage : "操作失败"; + // 返回结果 + return Result.error(errorMessage); + + } +} diff --git a/src/main/java/org/example/interceptors/LoginInterceptor.java b/src/main/java/org/example/interceptors/LoginInterceptor.java new file mode 100644 index 0000000..0f4fa68 --- /dev/null +++ b/src/main/java/org/example/interceptors/LoginInterceptor.java @@ -0,0 +1,33 @@ +package org.example.interceptors; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.example.pojo.Result; +import org.example.utils.JwtUtil; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.util.Map; + +@Component +public class LoginInterceptor implements HandlerInterceptor { + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + System.out.println("LoginInterceptor has been initialized."); + //令牌验证 + String token = request.getHeader("Authorization"); + //token 验证 + try { + + Map clains = JwtUtil.parseToken(token); + System.out.println("Interceptor"); + return true; + + }catch (Exception e) + { + response.setStatus(401); + System.out.println("Interceptor"); + return false; + } + } +} diff --git a/src/main/java/org/example/mapper/UserMapper.java b/src/main/java/org/example/mapper/UserMapper.java new file mode 100644 index 0000000..3ce8561 --- /dev/null +++ b/src/main/java/org/example/mapper/UserMapper.java @@ -0,0 +1,16 @@ +package org.example.mapper; + +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; +import org.example.pojo.User; + +@Mapper +public interface UserMapper { + //search the username + @Select("select * from user where username = #{username}") + User findByUsername(String username); + + @Insert("insert into user(username, password,create_time, update_time) values(#{username}, #{password},now(),now())") + void add(String username, String password); +} diff --git a/src/main/java/org/example/pojo/Article.java b/src/main/java/org/example/pojo/Article.java new file mode 100644 index 0000000..50cd7d6 --- /dev/null +++ b/src/main/java/org/example/pojo/Article.java @@ -0,0 +1,20 @@ +package org.example.pojo; + + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data + +public class Article { + private Integer id;//主键ID + private String title;//文章标题 + private String content;//文章内容 + private String coverImg;//封面图像 + private String state;//发布状态 已发布|草稿 + private Integer categoryId;//文章分类id + private Integer createUser;//创建人ID + private LocalDateTime createTime;//创建时间 + private LocalDateTime updateTime;//更新时间 +} diff --git a/src/main/java/org/example/pojo/Category.java b/src/main/java/org/example/pojo/Category.java new file mode 100644 index 0000000..62daf88 --- /dev/null +++ b/src/main/java/org/example/pojo/Category.java @@ -0,0 +1,15 @@ +package org.example.pojo; + +import lombok.Data; + +import java.time.LocalDateTime; + +@Data +public class Category { + private Integer id;//主键ID + private String categoryName;//分类名称 + private String categoryAlias;//分类别名 + private Integer createUser;//创建人ID + private LocalDateTime createTime;//创建时间 + private LocalDateTime updateTime;//更新时间 +} diff --git a/src/main/java/org/example/pojo/Result.java b/src/main/java/org/example/pojo/Result.java new file mode 100644 index 0000000..bb381c0 --- /dev/null +++ b/src/main/java/org/example/pojo/Result.java @@ -0,0 +1,31 @@ +package org.example.pojo; + + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +//统一响应结果 +@NoArgsConstructor +@AllArgsConstructor +@Data + +public class Result { + private Integer code;//业务状态码 0-成功 1-失败 + private String message;//提示信息 + private T data;//响应数据 + + //快速返回操作成功响应结果(带响应数据) + public static Result success(E data) { + return new Result<>(0, "操作成功", data); + } + + //快速返回操作成功响应结果 + public static Result success() { + return new Result(0, "操作成功", null); + } + + public static Result error(String message) { + return new Result(1, message, null); + } +} diff --git a/src/main/java/org/example/pojo/User.java b/src/main/java/org/example/pojo/User.java new file mode 100644 index 0000000..da02d53 --- /dev/null +++ b/src/main/java/org/example/pojo/User.java @@ -0,0 +1,20 @@ +package org.example.pojo; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.Data; + +import java.time.LocalDateTime; +//lombok插件 在编译阶段 为实体类自动生成setter getter toString +//pom文件中引入依赖 在实体类上添加注解 +@Data +public class User { + private Integer id;//主键ID + private String username;//用户名 + @JsonIgnore + private String password;//密码 + private String nickname;//昵称 + private String email;//邮箱 + private String userPic;//用户头像地址 + private LocalDateTime createTime;//创建时间 + private LocalDateTime updateTime;//更新时间 +} diff --git a/src/main/java/org/example/service/UserService.java b/src/main/java/org/example/service/UserService.java new file mode 100644 index 0000000..a1aabbb --- /dev/null +++ b/src/main/java/org/example/service/UserService.java @@ -0,0 +1,11 @@ +package org.example.service; + +import org.example.pojo.User; + +public interface UserService { + //根据用户名查询用户 + User findByUsername(String username); + + //注册 + void register(String username, String password); +} diff --git a/src/main/java/org/example/service/impl/UserServiceImpl.java b/src/main/java/org/example/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..69c619d --- /dev/null +++ b/src/main/java/org/example/service/impl/UserServiceImpl.java @@ -0,0 +1,31 @@ +package org.example.service.impl; + +import org.example.mapper.UserMapper; +import org.example.pojo.User; +import org.example.service.UserService; +import org.example.utils.Md5Util; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserMapper userMapper; + + @Override + public User findByUsername(String username) { + System.out.println("findByUsername - username: " + username); + User user = userMapper.findByUsername(username); + return user; + } + + @Override + public void register(String username, String password) { + //加密 + String md5String = Md5Util.getMD5String(password); + //添加 + userMapper.add(username,md5String); + + } +} diff --git a/src/main/java/org/example/utils/JwtUtil.java b/src/main/java/org/example/utils/JwtUtil.java new file mode 100644 index 0000000..0de28fe --- /dev/null +++ b/src/main/java/org/example/utils/JwtUtil.java @@ -0,0 +1,30 @@ +package org.example.utils; + +import com.auth0.jwt.JWT; +import com.auth0.jwt.algorithms.Algorithm; + +import java.util.Date; +import java.util.Map; + +public class JwtUtil { + + private static final String KEY = "itheima"; + + //接收业务数据,生成token并返回 + public static String genToken(Map claims) { + return JWT.create() + .withClaim("claims", claims) + .withExpiresAt(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 12)) + .sign(Algorithm.HMAC256(KEY)); + } + + //接收token,验证token,并返回业务数据 + public static Map parseToken(String token) { + return JWT.require(Algorithm.HMAC256(KEY)) + .build() + .verify(token) + .getClaim("claims") + .asMap(); + } + +} diff --git a/src/main/java/org/example/utils/Md5Util.java b/src/main/java/org/example/utils/Md5Util.java new file mode 100644 index 0000000..a4af778 --- /dev/null +++ b/src/main/java/org/example/utils/Md5Util.java @@ -0,0 +1,73 @@ +package org.example.utils; + + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class Md5Util { + /** + * 默认的密码字符串组合,用来将字节转换成 16 进制表示的字符,apache校验下载的文件的正确性用的就是默认的这个组合 + */ + protected static char hexDigits[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + + protected static MessageDigest messagedigest = null; + + static { + try { + messagedigest = MessageDigest.getInstance("MD5"); + } catch (NoSuchAlgorithmException nsaex) { + System.err.println(Md5Util.class.getName() + "初始化失败,MessageDigest不支持MD5Util。"); + nsaex.printStackTrace(); + } + } + + /** + * 生成字符串的md5校验值 + * + * @param s + * @return + */ + public static String getMD5String(String s) { + return getMD5String(s.getBytes()); + } + + /** + * 判断字符串的md5校验码是否与一个已知的md5码相匹配 + * + * @param password 要校验的字符串 + * @param md5PwdStr 已知的md5校验码 + * @return + */ + public static boolean checkPassword(String password, String md5PwdStr) { + String s = getMD5String(password); + return s.equals(md5PwdStr); + } + + + public static String getMD5String(byte[] bytes) { + messagedigest.update(bytes); + return bufferToHex(messagedigest.digest()); + } + + private static String bufferToHex(byte bytes[]) { + return bufferToHex(bytes, 0, bytes.length); + } + + private static String bufferToHex(byte bytes[], int m, int n) { + StringBuffer stringbuffer = new StringBuffer(2 * n); + int k = m + n; + for (int l = m; l < k; l++) { + appendHexPair(bytes[l], stringbuffer); + } + return stringbuffer.toString(); + } + + private static void appendHexPair(byte bt, StringBuffer stringbuffer) { + char c0 = hexDigits[(bt & 0xf0) >> 4];// 取字节中高 4 位的数字转换, >>> + // 为逻辑右移,将符号位一起右移,此处未发现两种符号有何不同 + char c1 = hexDigits[bt & 0xf];// 取字节中低 4 位的数字转换 + stringbuffer.append(c0); + stringbuffer.append(c1); + } + +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..c9c22ea --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,10 @@ +spring: + datasource: + driver-class-name: com.mysql.cj.jdbc.Driver + url: jdbc:mysql://114.115.137.102:3306/big_event?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC + username: root + password: 123456 + +mybatis: + configuration: + map-underscore-to-camel-case: true diff --git a/src/test/java/org/example/AppTest.java b/src/test/java/org/example/AppTest.java new file mode 100644 index 0000000..d5f435d --- /dev/null +++ b/src/test/java/org/example/AppTest.java @@ -0,0 +1,38 @@ +package org.example; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class AppTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public AppTest( String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( AppTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +}