Compare commits

...

6 Commits

Author SHA1 Message Date
jsh
1a71904608 add: 登录 2025-10-12 16:13:35 +08:00
jsh
68474c0c80 add: 登录 2025-10-12 16:13:04 +08:00
jsh
23ff4c814d style: 修改注释 2025-10-12 14:49:01 +08:00
jsh
363bcb83c6 fix: 修复还有多少天变成负数的问题 2025-10-12 14:27:19 +08:00
jsh
0200382ddf style: 清理引入 2025-10-12 14:11:01 +08:00
jsh
fa278dec01 add: 周年纪念日 2025-10-12 14:08:16 +08:00
18 changed files with 249 additions and 4 deletions

View File

@@ -1,3 +1,19 @@
drop table if exists `user`
create table user
(
id int unsigned auto_increment
primary key,
create_time datetime null,
update_time datetime null,
username varchar(100) not null,
password varchar(255) not null,
nickname varchar(100) null
)
comment '用户表';
drop table if exists `goal`;
CREATE TABLE if not exists `goal`
@@ -34,8 +50,9 @@ create table habit_record
id int unsigned auto_increment,
create_time datetime null,
update_time datetime null,
name varchar(100) not null,
date date not null comment '重要的日期',
type enum ('anniversary', 'commemoration') default 'anniversary' not null
type enum ('ANNIVERSARY', 'COMMEMORATION') default 'ANNIVERSARY' not null
)
comment '周年纪念日';

View File

@@ -27,7 +27,7 @@
<url/>
</scm>
<properties>
<java.version>21</java.version>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>

View File

@@ -14,6 +14,14 @@ public class AnniversaryController {
this.anniversaryService = anniversaryService;
}
/**
* 获取所有周年日和纪念日
*/
@GetMapping
public R get() {
return R.ok(anniversaryService.getAll());
}
@PostMapping
public R add(Anniversary anniversary) {
anniversaryService.save(anniversary);

View File

@@ -0,0 +1,28 @@
package com.dota.nexus.controller;
import com.dota.nexus.entity.LoginDTO;
import com.dota.nexus.entity.R;
import com.dota.nexus.service.UserService;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("user")
public class UserController {
UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@PostMapping("login")
public R login(LoginDTO loginDTO) throws Exception {
var res = userService.login(loginDTO.username(), loginDTO.password());
if (res==null) {
return R.error("用户不存在或者密码错误");
}
return R.ok(res);
}
}

View File

@@ -8,7 +8,9 @@ import java.time.LocalDate;
@Data
@EqualsAndHashCode(callSuper = true)
public class Anniversary extends Entity{
private String name;
private LocalDate date;
private type;
private AnniversaryEnum type;
}

View File

@@ -0,0 +1,4 @@
package com.dota.nexus.entity;
public record LoginDTO(String username, String password) {
}

View File

@@ -27,8 +27,12 @@ public class R {
return new R(200, "ok", data);
}
public static R error(String msg){
return new R(500, msg);
}
public static R error(){
return new R(500, "服务端发生未知错误");
return error("服务端发生未知错误");
}
public static R unauthorized() {

View File

@@ -0,0 +1,14 @@
package com.dota.nexus.entity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class User extends Entity{
private String name;
private String password;
private String nickname;
}

View File

@@ -0,0 +1,4 @@
package com.dota.nexus.entity.vo;
public record AnniversaryRecord(String name, String date, int distance) {
}

View File

@@ -0,0 +1,6 @@
package com.dota.nexus.entity.vo;
import java.util.List;
public record AnniversaryVO (List<AnniversaryRecord> anniversaryList, List<AnniversaryRecord> commemorationList){
}

View File

@@ -0,0 +1,9 @@
package com.dota.nexus.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dota.nexus.entity.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

View File

@@ -2,6 +2,8 @@ package com.dota.nexus.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dota.nexus.entity.Anniversary;
import com.dota.nexus.entity.vo.AnniversaryVO;
public interface AnniversaryService extends IService<Anniversary> {
AnniversaryVO getAll();
}

View File

@@ -0,0 +1,9 @@
package com.dota.nexus.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.dota.nexus.entity.User;
public interface UserService extends IService<User> {
String login(String username, String password) throws Exception;
}

View File

@@ -2,10 +2,45 @@ package com.dota.nexus.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dota.nexus.entity.Anniversary;
import com.dota.nexus.entity.AnniversaryEnum;
import com.dota.nexus.entity.vo.AnniversaryRecord;
import com.dota.nexus.entity.vo.AnniversaryVO;
import com.dota.nexus.mapper.AnniversaryMapper;
import com.dota.nexus.service.AnniversaryService;
import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
@Service
public class AnniversaryServiceImpl extends ServiceImpl<AnniversaryMapper, Anniversary> implements AnniversaryService {
/**
*
*/
@Override
public AnniversaryVO getAll() {
var aList = new ArrayList<AnniversaryRecord>();
var bList = new ArrayList<AnniversaryRecord>();
var res = new AnniversaryVO(aList, bList);
var anniversaries = this.baseMapper.selectList(null);
var now = LocalDate.now();
for (Anniversary anniversary : anniversaries) {
// 周年,变成今年或者明年
if (anniversary.getType() == AnniversaryEnum.ANNIVERSARY) {
LocalDate date = anniversary.getDate();
date = date.withYear(now.getYear());
if (date.isBefore(now)) {
date = date.withYear(now.getYear() + 1);
}
aList.add(new AnniversaryRecord(anniversary.getName(), date.toString(), (int) ChronoUnit.DAYS.between(now, date)));
} else if (anniversary.getType() == AnniversaryEnum.COMMEMORATION) {
bList.add(new AnniversaryRecord(anniversary.getName(), anniversary.getDate().toString(), (int) ChronoUnit.DAYS.between(anniversary.getDate(), now)));
}
}
return res;
}
}

View File

@@ -0,0 +1,27 @@
package com.dota.nexus.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dota.nexus.entity.User;
import com.dota.nexus.mapper.UserMapper;
import com.dota.nexus.service.UserService;
import com.dota.nexus.util.GlobalMap;
import com.dota.nexus.util.PasswordUtil;
import org.springframework.stereotype.Service;
import java.util.UUID;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
public String login(String username, String password) throws Exception {
var q = new LambdaQueryWrapper<User>();
q.eq(User::getName, username);
var u = this.baseMapper.selectOne(q);
if (u!=null && PasswordUtil.verify(password, u.getPassword())) {
var uuid = UUID.randomUUID().toString();
GlobalMap.put(uuid, u.getId());
return uuid;
}
return null;
}
}

View File

@@ -0,0 +1,16 @@
package com.dota.nexus.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class GlobalMap {
private static final Map<String, Object> MAP = new ConcurrentHashMap<>();
public static void put(String k, Object v) {
MAP.put(k,v);
}
public static Object get(String k) {
return MAP.get(k);
}
}

View File

@@ -0,0 +1,47 @@
package com.dota.nexus.util;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import java.security.SecureRandom;
import java.util.Base64;
public class PasswordUtil {
public static String encrypt(String password) throws Exception{
var random = new SecureRandom();
var salt = new byte[16];
random.nextBytes(salt);
var spec = new PBEKeySpec(
password.toCharArray(),
salt,
100000,
256
);
var factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
var hash = factory.generateSecret(spec).getEncoded();
return Base64.getEncoder().encodeToString(salt) + ":" + Base64.getEncoder().encodeToString(hash);
}
public static boolean verify(String password, String storedHash) throws Exception {
var parts = storedHash.split(":");
var salt = Base64.getDecoder().decode(parts[0]);
PBEKeySpec spec = new PBEKeySpec(
password.toCharArray(),
salt,
100000,
256
);
byte[] testHash = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256")
.generateSecret(spec).getEncoded();
return parts[1].equals(Base64.getEncoder().encodeToString(testHash));
}
public static void main(String[] args) throws Exception{
var s = "nexus2017";
var pass =encrypt(s);
System.out.println(pass);
System.out.println(pass.length());
System.out.println(verify(s, pass));
}
}

View File

@@ -0,0 +1,13 @@
package com.dota.nexus.util;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
public class TokenUtil {
public static Integer CurrentUserId() {
var req = ((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest();
String authorization = req.getHeader("Authorization");
var token = authorization.replace("Bearer ", "");
return (Integer) GlobalMap.get(token);
}
}