16 changed files with 519 additions and 14 deletions
@ -1,4 +1,7 @@ |
|||||||
# 程序自身数据源配置 |
# 程序自身数据源配置 |
||||||
spring.datasource.url=jdbc:mysql://10.100.0.108:3306/idle_game?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true |
spring.datasource.url=jdbc:mysql://10.100.0.108:3306/idle_game?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&allowMultiQueries=true |
||||||
spring.datasource.username=root |
spring.datasource.username=root |
||||||
spring.datasource.password=mBMjp2v74c7MzhC/5RGeXF1V3E+AcRFs1f5OH6PDHi3nWaM3njaaoewswq8Sl7/AY631t0sONVDG672pX4mFpZx/8xex8BJP3uX1wUu9NGpTCSHskb5cD6KZMNV4jNsfoqxFRyJq8yk86djPsCfR4ch0sPnLH+LCg9XY1DAw8szh93QnKDkiImq2JLkaIwG3R3t8dNWv1wVoMR6vVecPsEUyPJu5vsrvJhjP3uAL7jZYJVGZG6bkrpV3R6I6mja0QnTdF41NCL5Ex0TINSi7GKnrALjZ0qWcT9fe2bTUCKq50+CtVEAQnEz2ZJpYUaBZXJbHh4OrUyqjAmA5s7IelQ== |
spring.datasource.password=123456 |
||||||
|
|
||||||
|
login.token.timeout=10080 |
||||||
|
login.token.domain= |
@ -0,0 +1,46 @@ |
|||||||
|
package vip.xumy.idle.server.conf; |
||||||
|
|
||||||
|
import java.nio.charset.Charset; |
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
import org.springframework.http.MediaType; |
||||||
|
import org.springframework.http.converter.HttpMessageConverter; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.serializer.SerializerFeature; |
||||||
|
import com.alibaba.fastjson.support.config.FastJsonConfig; |
||||||
|
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; |
||||||
|
|
||||||
|
/** Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2025年5月19日 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Configuration |
||||||
|
public class Configer { |
||||||
|
|
||||||
|
@Bean |
||||||
|
public HttpMessageConverter<?> configureMessageConverters() { |
||||||
|
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); |
||||||
|
FastJsonConfig config = new FastJsonConfig(); |
||||||
|
config.setSerializerFeatures( |
||||||
|
SerializerFeature.WriteMapNullValue, |
||||||
|
SerializerFeature.WriteNullStringAsEmpty, |
||||||
|
SerializerFeature.WriteNullNumberAsZero, |
||||||
|
SerializerFeature.WriteNullListAsEmpty, |
||||||
|
SerializerFeature.WriteNullBooleanAsFalse, |
||||||
|
SerializerFeature.DisableCircularReferenceDetect |
||||||
|
); |
||||||
|
|
||||||
|
converter.setFastJsonConfig(config); |
||||||
|
converter.setDefaultCharset(Charset.forName("UTF-8")); |
||||||
|
List<MediaType> mediaTypeList = new ArrayList<>(); |
||||||
|
mediaTypeList.add(MediaType.APPLICATION_JSON); |
||||||
|
converter.setSupportedMediaTypes(mediaTypeList); |
||||||
|
return converter; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
package vip.xumy.idle.server.ctrl; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.bind.annotation.GetMapping; |
||||||
|
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 vip.xumy.core.pojo.com.BaseResponse; |
||||||
|
import vip.xumy.idle.server.pojo.Archive; |
||||||
|
import vip.xumy.idle.server.service.ArchiveService; |
||||||
|
import vip.xumy.idle.server.util.LoginUtil; |
||||||
|
|
||||||
|
/** |
||||||
|
* Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2025年5月19日 |
||||||
|
*/ |
||||||
|
|
||||||
|
@RestController |
||||||
|
@RequestMapping("archive") |
||||||
|
public class ArchiveController { |
||||||
|
@Autowired |
||||||
|
private ArchiveService archiveService; |
||||||
|
|
||||||
|
@PostMapping |
||||||
|
public BaseResponse saveArchive(@RequestBody Archive archive) { |
||||||
|
String userId = LoginUtil.getUserId(); |
||||||
|
if (userId == null) { |
||||||
|
return new BaseResponse(true, "请先登录"); |
||||||
|
} |
||||||
|
archive.setUsername(userId); |
||||||
|
archiveService.saveOrUpdate(archive); |
||||||
|
return new BaseResponse(true, "存档保存成功"); |
||||||
|
} |
||||||
|
|
||||||
|
@GetMapping |
||||||
|
public BaseResponse getArchive(String version) { |
||||||
|
String userId = LoginUtil.getUserId(); |
||||||
|
Archive archive = archiveService.getByKey(userId, version); |
||||||
|
if (archive == null) { |
||||||
|
return new BaseResponse(false, "未查询到你的存档"); |
||||||
|
} |
||||||
|
return new BaseResponse(true, archive.getArchive()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,18 @@ |
|||||||
|
package vip.xumy.idle.server.mapper; |
||||||
|
|
||||||
|
import org.apache.ibatis.annotations.Mapper; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||||
|
|
||||||
|
import vip.xumy.idle.server.pojo.Archive; |
||||||
|
|
||||||
|
/** Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2025年5月19日 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Mapper |
||||||
|
public interface IArchiveMapper extends BaseMapper<Archive> { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package vip.xumy.idle.server.pojo; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName; |
||||||
|
|
||||||
|
import lombok.Getter; |
||||||
|
import lombok.Setter; |
||||||
|
|
||||||
|
/** |
||||||
|
* Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2025年5月19日 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Setter |
||||||
|
@Getter |
||||||
|
@TableName("archive") |
||||||
|
public class Archive { |
||||||
|
|
||||||
|
private String username; |
||||||
|
private String version; |
||||||
|
private int lv; |
||||||
|
private long coins; |
||||||
|
private String archive; |
||||||
|
|
||||||
|
} |
@ -1,29 +1,33 @@ |
|||||||
package vip.xumy.idle.server.pojo; |
package vip.xumy.idle.server.pojo; |
||||||
|
|
||||||
|
import com.alibaba.fastjson.annotation.JSONField; |
||||||
|
import com.baomidou.mybatisplus.annotation.TableId; |
||||||
import com.baomidou.mybatisplus.annotation.TableName; |
import com.baomidou.mybatisplus.annotation.TableName; |
||||||
|
|
||||||
import lombok.Getter; |
import lombok.Getter; |
||||||
import lombok.Setter; |
import lombok.Setter; |
||||||
|
|
||||||
/** Ownership belongs to the company |
/** |
||||||
|
* Ownership belongs to the company |
||||||
* |
* |
||||||
* @author:mengyxu |
* @author:mengyxu |
||||||
* @date:2025年4月18日 |
* @date:2025年4月18日 |
||||||
*/ |
*/ |
||||||
|
|
||||||
@Setter |
@Setter |
||||||
@Getter |
@Getter |
||||||
@TableName("user") |
@TableName("user") |
||||||
public class User { |
public class User { |
||||||
|
|
||||||
private String useranme; |
@TableId |
||||||
|
private String username; |
||||||
|
@JSONField(serialize = false) |
||||||
private String password; |
private String password; |
||||||
private String state; |
private String state; |
||||||
private String phone; |
private String phone; |
||||||
private String idCard; |
private String idCard; |
||||||
private String name; |
private String name; |
||||||
private String registerTime; |
private String registerTime; |
||||||
private String last_login; |
private String lastLogin; |
||||||
|
|
||||||
|
|
||||||
} |
} |
||||||
|
@ -0,0 +1,38 @@ |
|||||||
|
package vip.xumy.idle.server.service; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
||||||
|
|
||||||
|
import vip.xumy.idle.server.mapper.IArchiveMapper; |
||||||
|
import vip.xumy.idle.server.pojo.Archive; |
||||||
|
|
||||||
|
/** Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2025年5月19日 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Service |
||||||
|
public class ArchiveService { |
||||||
|
@Autowired |
||||||
|
private IArchiveMapper archiveMapper; |
||||||
|
|
||||||
|
public void saveOrUpdate(Archive archive) { |
||||||
|
Archive exit = getByKey(archive.getUsername(), archive.getVersion()); |
||||||
|
if(exit == null) { |
||||||
|
archiveMapper.insert(archive); |
||||||
|
}else { |
||||||
|
archiveMapper.updateById(archive); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public Archive getByKey(String username, String version) { |
||||||
|
QueryWrapper<Archive> wrapper = new QueryWrapper<>(); |
||||||
|
wrapper.eq("username", username); |
||||||
|
wrapper.eq("version", version); |
||||||
|
return archiveMapper.selectOne(wrapper); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
package vip.xumy.idle.server.service; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import vip.xumy.core.utils.DateUtil; |
||||||
|
import vip.xumy.core.utils.StringUtil; |
||||||
|
import vip.xumy.idle.server.mapper.IUserMapper; |
||||||
|
import vip.xumy.idle.server.pojo.User; |
||||||
|
|
||||||
|
/** |
||||||
|
* Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2025年5月19日 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Service |
||||||
|
public class UserService { |
||||||
|
@Autowired |
||||||
|
private IUserMapper userMapper; |
||||||
|
|
||||||
|
public User login(User param) { |
||||||
|
String username = param.getUsername(); |
||||||
|
String password = param.getPassword(); |
||||||
|
if (StringUtil.isEmpty(username, password)) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
User user = getById(username); |
||||||
|
if (user != null) { |
||||||
|
if (password.equals(user.getPassword())) { |
||||||
|
userMapper.login(username); |
||||||
|
return user; |
||||||
|
} else { |
||||||
|
return null; |
||||||
|
} |
||||||
|
} else { |
||||||
|
String time = DateUtil.format(); |
||||||
|
param.setState("0"); |
||||||
|
param.setRegisterTime(time); |
||||||
|
param.setLastLogin(time); |
||||||
|
userMapper.insert(param); |
||||||
|
return param; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public User getById(String username) { |
||||||
|
return userMapper.selectById(username); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,205 @@ |
|||||||
|
package vip.xumy.idle.server.util; |
||||||
|
|
||||||
|
import javax.servlet.http.Cookie; |
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import vip.xumy.core.golbal.GlobalBuffer; |
||||||
|
import vip.xumy.core.pojo.com.Cache; |
||||||
|
import vip.xumy.core.utils.StringUtil; |
||||||
|
import vip.xumy.idle.server.pojo.User; |
||||||
|
|
||||||
|
/** |
||||||
|
* Ownership belongs to the company |
||||||
|
* |
||||||
|
* @author:mengyxu |
||||||
|
* @date:2024年3月5日 |
||||||
|
*/ |
||||||
|
|
||||||
|
//@Log4j2
|
||||||
|
@Component |
||||||
|
public class LoginUtil { |
||||||
|
public static final String TIKEN_KEY_PREFIX = "token-"; |
||||||
|
public static final String LOGIN_COOKIE_NAME = "token"; |
||||||
|
|
||||||
|
@Value("${login.token.timeout}") |
||||||
|
public void setTimeout(Integer timeout) { |
||||||
|
LoginUtil.timeout = timeout; |
||||||
|
} |
||||||
|
|
||||||
|
private static Integer timeout; |
||||||
|
|
||||||
|
@Value("${login.token.domain}") |
||||||
|
public void setDomain(String domain) { |
||||||
|
LoginUtil.domain = domain; |
||||||
|
} |
||||||
|
|
||||||
|
private static String domain; |
||||||
|
|
||||||
|
private static HttpServletRequest request; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
public void setRequest(HttpServletRequest request) { |
||||||
|
LoginUtil.request = request; |
||||||
|
} |
||||||
|
|
||||||
|
private static HttpServletResponse response; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
public void setResponse(HttpServletResponse response) { |
||||||
|
LoginUtil.response = response; |
||||||
|
} |
||||||
|
|
||||||
|
private static String getTokenKey(String userId) { |
||||||
|
return TIKEN_KEY_PREFIX + userId; |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean isLogin(String userId) { |
||||||
|
Cache cache = GlobalBuffer.getCache(getTokenKey(userId)); |
||||||
|
return !Cache.isEmpty(cache); |
||||||
|
} |
||||||
|
|
||||||
|
public static void remveLoginInfo(String userId) { |
||||||
|
String tokenKey = LoginUtil.getTokenKey(userId); |
||||||
|
Cache token = GlobalBuffer.getCache(tokenKey); |
||||||
|
if (!Cache.isEmpty(token)) { |
||||||
|
String value = token.getValue(); |
||||||
|
GlobalBuffer.removeCache(value.substring(0, 10)); |
||||||
|
GlobalBuffer.removeCache(tokenKey); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static void saveLoginInfo(User user) { |
||||||
|
// 删除旧的token信息
|
||||||
|
String userId = user.getUsername(); |
||||||
|
Cache exitToken = GlobalBuffer.getCache(LoginUtil.getTokenKey(userId)); |
||||||
|
if (!Cache.isEmpty(exitToken)) { |
||||||
|
String value = exitToken.getValue(); |
||||||
|
GlobalBuffer.removeCache(value.substring(0, 10)); |
||||||
|
} |
||||||
|
|
||||||
|
// 计算新的token
|
||||||
|
String ip = getIpAddr(); |
||||||
|
String seq = GlobalBuffer.getSeq(); |
||||||
|
String token = seq + StringUtil.md5(user.getUsername() + ip + System.currentTimeMillis(), false); |
||||||
|
|
||||||
|
// 保存用户token
|
||||||
|
GlobalBuffer.addCache(LoginUtil.getTokenKey(userId), new Cache(token, timeout * 60)); |
||||||
|
// 保存token的用户信息
|
||||||
|
GlobalBuffer.addCache(seq, new Cache(user, timeout * 60)); |
||||||
|
|
||||||
|
LoginUtil.addToken(token, response); |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
private static void addToken(String token, HttpServletResponse response) { |
||||||
|
Cookie cookie = new Cookie(LOGIN_COOKIE_NAME, token); |
||||||
|
if (!StringUtil.isEmpty(domain)) { |
||||||
|
cookie.setDomain(domain); |
||||||
|
} |
||||||
|
cookie.setPath("/"); |
||||||
|
response.addCookie(cookie); |
||||||
|
} |
||||||
|
|
||||||
|
public static User getUserInfo(String token, boolean refresh) { |
||||||
|
if (StringUtil.isEmpty(token)) { |
||||||
|
token = getToken(); |
||||||
|
} |
||||||
|
User empty = new User(); |
||||||
|
if (StringUtil.isEmpty(token) || token.length() != 42) { |
||||||
|
return empty; |
||||||
|
} |
||||||
|
Cache userCache = GlobalBuffer.getCache(token.substring(0, 10)); |
||||||
|
if (Cache.isEmpty(userCache)) { |
||||||
|
return empty; |
||||||
|
} |
||||||
|
User user = userCache.getValue(); |
||||||
|
String userId = user.getUsername(); |
||||||
|
Cache exitToken = GlobalBuffer.getCache(LoginUtil.getTokenKey(userId)); |
||||||
|
if (Cache.isEmpty(exitToken)) { |
||||||
|
return empty; |
||||||
|
} |
||||||
|
if (StringUtil.equals(token, exitToken.getValue())) { |
||||||
|
if (refresh) { |
||||||
|
userCache.refresh(); |
||||||
|
exitToken.refresh(); |
||||||
|
} |
||||||
|
return user; |
||||||
|
} |
||||||
|
return empty; |
||||||
|
} |
||||||
|
|
||||||
|
public static String getUserId() { |
||||||
|
return getUserInfo(null, false).getUsername(); |
||||||
|
} |
||||||
|
|
||||||
|
public static String getUserIdAndRefresh() { |
||||||
|
return getUserInfo(null, true).getUsername(); |
||||||
|
} |
||||||
|
|
||||||
|
public static User getUserInfo() { |
||||||
|
return getUserInfo(null, false); |
||||||
|
} |
||||||
|
|
||||||
|
public static void loginOut() { |
||||||
|
String token = LoginUtil.getToken(); |
||||||
|
if (!StringUtil.isEmpty(token)) { |
||||||
|
String seq = token.substring(0, 10); |
||||||
|
Cache userCache = GlobalBuffer.getCache(seq); |
||||||
|
if (!Cache.isEmpty(userCache)) { |
||||||
|
User user = userCache.getValue(); |
||||||
|
String userId = user.getUsername(); |
||||||
|
GlobalBuffer.removeCache(getTokenKey(userId)); |
||||||
|
} |
||||||
|
GlobalBuffer.removeCache(seq); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public static String getToken() { |
||||||
|
Cookie[] cookies = request.getCookies(); |
||||||
|
if (cookies == null) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
for (Cookie cookie : cookies) { |
||||||
|
if (LOGIN_COOKIE_NAME.equals(cookie.getName())) { |
||||||
|
return cookie.getValue(); |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取访问者IP |
||||||
|
* |
||||||
|
* 在一般情况下使用Request.getRemoteAddr()即可,但是经过nginx等反向代理软件后,这个方法会失效。 |
||||||
|
* |
||||||
|
* 本方法先从Header中获取X-Real-IP,如果不存在再从X-Forwarded-For获得第一个IP(用,分割), 如果还不存在则调用Request |
||||||
|
* .getRemoteAddr()。 |
||||||
|
* |
||||||
|
* @param request |
||||||
|
* @return |
||||||
|
*/ |
||||||
|
public static String getIpAddr() { |
||||||
|
String ip = request.getHeader("X-Real-IP"); |
||||||
|
if (!StringUtil.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) { |
||||||
|
return ip; |
||||||
|
} |
||||||
|
ip = request.getHeader("X-Forwarded-For"); |
||||||
|
if (!StringUtil.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip)) { |
||||||
|
// 多次反向代理后会有多个IP值,第一个为真实IP。
|
||||||
|
int index = ip.indexOf(','); |
||||||
|
if (index != -1) { |
||||||
|
return ip.substring(0, index); |
||||||
|
} else { |
||||||
|
return ip; |
||||||
|
} |
||||||
|
} else { |
||||||
|
return request.getRemoteAddr(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,15 @@ |
|||||||
|
export const post = (url, data) => { |
||||||
|
const options = { |
||||||
|
method: 'POST', |
||||||
|
body: JSON.stringify(data), |
||||||
|
headers: { |
||||||
|
'Content-Type': 'application/json', |
||||||
|
}, |
||||||
|
}; |
||||||
|
return new Promise((reslove, reject) => { |
||||||
|
fetch(url, options) |
||||||
|
.then((response) => response.json()) |
||||||
|
.then((data) => console.log(data)) |
||||||
|
.catch((error) => console.error('Error:', error)); |
||||||
|
}); |
||||||
|
}; |
@ -0,0 +1,11 @@ |
|||||||
|
import { post } from './base'; |
||||||
|
|
||||||
|
let commit; |
||||||
|
|
||||||
|
export const setCommit = (data) => { |
||||||
|
commit = data; |
||||||
|
}; |
||||||
|
|
||||||
|
export const login = (param) => { |
||||||
|
post('api/public/login', param); |
||||||
|
}; |
Loading…
Reference in new issue