parent
b122d6b1c6
commit
5e5fb9a07d
36 changed files with 1401 additions and 57 deletions
@ -0,0 +1,15 @@ |
|||||||
|
package cn.soul2.jyjc.admin.annotation; |
||||||
|
|
||||||
|
import java.lang.annotation.ElementType; |
||||||
|
import java.lang.annotation.Retention; |
||||||
|
import java.lang.annotation.RetentionPolicy; |
||||||
|
import java.lang.annotation.Target; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-04-02 |
||||||
|
*/ |
||||||
|
@Target({ElementType.METHOD, ElementType.TYPE}) |
||||||
|
@Retention(RetentionPolicy.RUNTIME) |
||||||
|
public @interface SkinLogin { |
||||||
|
} |
@ -0,0 +1,92 @@ |
|||||||
|
package cn.soul2.jyjc.admin.config; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.entity.UserLoginOutDO; |
||||||
|
import org.apache.commons.lang3.StringUtils; |
||||||
|
import org.springframework.stereotype.Component; |
||||||
|
|
||||||
|
import java.time.LocalDateTime; |
||||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||||
|
|
||||||
|
@Component |
||||||
|
public class UserLoginStatusBean { |
||||||
|
|
||||||
|
private ConcurrentHashMap<String, UserLoginOutDO> loginStatusMap = new ConcurrentHashMap<>(); |
||||||
|
|
||||||
|
/** |
||||||
|
* 缓存登录信息 |
||||||
|
* |
||||||
|
* @param token token |
||||||
|
* @param loginOutStatus 登录信息 |
||||||
|
*/ |
||||||
|
public void login(String token, UserLoginOutDO loginOutStatus) { |
||||||
|
loginStatusMap.put(token, loginOutStatus); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 从缓存读取登录信息 |
||||||
|
* |
||||||
|
* @param token token |
||||||
|
* @return {@link UserLoginOutDO} |
||||||
|
*/ |
||||||
|
public UserLoginOutDO getStatus(String token) { |
||||||
|
UserLoginOutDO loginStatus = loginStatusMap.getOrDefault(token, null); |
||||||
|
if (loginStatus.getLapseTime() != null) { |
||||||
|
LocalDateTime now = LocalDateTime.now(); |
||||||
|
if (now.isAfter(loginStatus.getLapseTime())) { |
||||||
|
logout(token); |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
return loginStatus; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 为key设置登出 |
||||||
|
* |
||||||
|
* @param token token |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
public Boolean logout(String token) { |
||||||
|
if (StringUtils.isNotBlank(token) && loginStatusMap.containsKey(token)) { |
||||||
|
UserLoginOutDO removedUser = loginStatusMap.remove(token); |
||||||
|
// 返回true表示成功登出,返回false表示未成功登出
|
||||||
|
return removedUser != null; |
||||||
|
} |
||||||
|
return Boolean.TRUE; |
||||||
|
} |
||||||
|
|
||||||
|
public Boolean logoutByUserId(String userId) { |
||||||
|
final String[] targetKey = {null}; |
||||||
|
loginStatusMap.forEach((k, v) -> { |
||||||
|
if (targetKey[0] == null && v.getUserId().equals(userId)) { |
||||||
|
targetKey[0] = k; |
||||||
|
} |
||||||
|
}); |
||||||
|
return logout(targetKey[0]); |
||||||
|
} |
||||||
|
|
||||||
|
public String getTokenByUsername(String username) { |
||||||
|
final String[] token = {null}; |
||||||
|
loginStatusMap.forEach((k, v) -> { |
||||||
|
if (token[0] == null && v.getUserName().equals(username)) { |
||||||
|
token[0] = k; |
||||||
|
} |
||||||
|
}); |
||||||
|
return token[0]; |
||||||
|
} |
||||||
|
|
||||||
|
public Boolean containsToken(String token) { |
||||||
|
if (StringUtils.isBlank(token)) { |
||||||
|
return Boolean.FALSE; |
||||||
|
} |
||||||
|
UserLoginOutDO loginStatus = loginStatusMap.getOrDefault(token, null); |
||||||
|
if (loginStatus.getLapseTime() != null) { |
||||||
|
LocalDateTime now = LocalDateTime.now(); |
||||||
|
if (now.isAfter(loginStatus.getLapseTime())) { |
||||||
|
logout(token); |
||||||
|
} |
||||||
|
} |
||||||
|
return loginStatusMap.containsKey(token); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,24 @@ |
|||||||
|
package cn.soul2.jyjc.admin.config; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.interceptor.TokenInterceptor; |
||||||
|
import org.springframework.context.annotation.Configuration; |
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; |
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; |
||||||
|
|
||||||
|
/** |
||||||
|
* 注册请求拦截器 |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-04-02 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Configuration |
||||||
|
public class WebMvcConfig implements WebMvcConfigurer { |
||||||
|
|
||||||
|
@Override |
||||||
|
public void addInterceptors(InterceptorRegistry registry) { |
||||||
|
registry.addInterceptor(new TokenInterceptor()) |
||||||
|
// 拦截所有路径
|
||||||
|
.addPathPatterns("/**"); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,32 @@ |
|||||||
|
package cn.soul2.jyjc.admin.controller; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.AnswerSubmitDTO; |
||||||
|
import cn.soul2.jyjc.admin.service.IAnswerService; |
||||||
|
import cn.soul2.jyjc.admin.utils.base.BackUtils; |
||||||
|
import cn.soul2.jyjc.admin.vo.base.Back; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
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; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-27 13:24 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@RestController |
||||||
|
@RequestMapping("/answer") |
||||||
|
public class AnswerController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IAnswerService answerService; |
||||||
|
|
||||||
|
@PostMapping("submit") |
||||||
|
public Back<Boolean> submit(@RequestBody AnswerSubmitDTO dto) { |
||||||
|
return BackUtils.success(answerService.handleSubmit(dto)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
package cn.soul2.jyjc.admin.controller; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.annotation.SkinLogin; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLogoutDTO; |
||||||
|
import cn.soul2.jyjc.admin.service.IUserService; |
||||||
|
import cn.soul2.jyjc.admin.utils.base.BackUtils; |
||||||
|
import cn.soul2.jyjc.admin.vo.UserVO; |
||||||
|
import cn.soul2.jyjc.admin.vo.base.Back; |
||||||
|
import lombok.extern.slf4j.Slf4j; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
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; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-31 15:48 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Slf4j |
||||||
|
@RestController |
||||||
|
@RequestMapping("/user") |
||||||
|
public class UserController { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IUserService userService; |
||||||
|
|
||||||
|
@PostMapping("login") |
||||||
|
@SkinLogin |
||||||
|
public Back<UserVO> login(@RequestBody UserLoginDTO dto) { |
||||||
|
return BackUtils.success(userService.login(dto)); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("register") |
||||||
|
@SkinLogin |
||||||
|
public Back<UserVO> register(@RequestBody UserLoginDTO dto) { |
||||||
|
return BackUtils.success(userService.register(dto)); |
||||||
|
} |
||||||
|
|
||||||
|
@PostMapping("logout") |
||||||
|
public Back<Boolean> logout(@RequestBody UserLogoutDTO dto) { |
||||||
|
return BackUtils.success(userService.logout(dto)); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-27 13:31 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class AnswerDetailDTO { |
||||||
|
|
||||||
|
/** |
||||||
|
* 回答内容(文字/选项id,多选时以,分隔) |
||||||
|
*/ |
||||||
|
private String content; |
||||||
|
|
||||||
|
/** |
||||||
|
* 得分 |
||||||
|
*/ |
||||||
|
private Integer points; |
||||||
|
|
||||||
|
/** |
||||||
|
* 题目id |
||||||
|
*/ |
||||||
|
private String subjectId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 题目类型:0-单选;1-多选;2-文字 |
||||||
|
*/ |
||||||
|
private Integer subjectType; |
||||||
|
|
||||||
|
/** |
||||||
|
* 题目分值 |
||||||
|
*/ |
||||||
|
private Integer subjectPoints; |
||||||
|
|
||||||
|
/** |
||||||
|
* 权重 |
||||||
|
*/ |
||||||
|
private Double weights; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-27 13:26 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class AnswerSubmitDTO { |
||||||
|
|
||||||
|
/** |
||||||
|
* 二维码id |
||||||
|
*/ |
||||||
|
private String qrId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 问卷Id |
||||||
|
*/ |
||||||
|
private String qnId; |
||||||
|
|
||||||
|
/** |
||||||
|
* openid, 即答卷人 |
||||||
|
*/ |
||||||
|
private String openid; |
||||||
|
|
||||||
|
/** |
||||||
|
* 答题内容 |
||||||
|
*/ |
||||||
|
private List<AnswerDetailDTO> details; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,30 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 21:55 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class UserLoginDTO { |
||||||
|
|
||||||
|
/** |
||||||
|
* userName |
||||||
|
*/ |
||||||
|
private String username; |
||||||
|
|
||||||
|
/** |
||||||
|
* password |
||||||
|
*/ |
||||||
|
private String password; |
||||||
|
|
||||||
|
/** |
||||||
|
* 密码错误次数(暂未使用) |
||||||
|
*/ |
||||||
|
private Integer pswErrorCount; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,21 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.base.PageParams; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 21:50 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class UserLoginOutPageDTO extends PageParams { |
||||||
|
|
||||||
|
/** |
||||||
|
* userId |
||||||
|
*/ |
||||||
|
private String userId; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 21:56 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class UserLogoutDTO { |
||||||
|
|
||||||
|
/** |
||||||
|
* userName |
||||||
|
*/ |
||||||
|
private String username; |
||||||
|
|
||||||
|
/** |
||||||
|
* token |
||||||
|
*/ |
||||||
|
private String token; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.base.PageParams; |
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
import java.time.LocalDateTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 20:50 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class UserPageDTO extends PageParams { |
||||||
|
|
||||||
|
/** |
||||||
|
* id |
||||||
|
*/ |
||||||
|
private String id; |
||||||
|
/** |
||||||
|
* 用户名 |
||||||
|
*/ |
||||||
|
private String username; |
||||||
|
/** |
||||||
|
* 状态;0(默认):正常;4:封号;9:异常; |
||||||
|
*/ |
||||||
|
private Integer status; |
||||||
|
|
||||||
|
/** |
||||||
|
* 注册时间 |
||||||
|
*/ |
||||||
|
private LocalDateTime startTime; |
||||||
|
private LocalDateTime endTime; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
package cn.soul2.jyjc.admin.dto; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 20:50 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class UserSaveDTO { |
||||||
|
|
||||||
|
/** |
||||||
|
* id |
||||||
|
*/ |
||||||
|
private String id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户名 |
||||||
|
*/ |
||||||
|
private String username; |
||||||
|
|
||||||
|
/** |
||||||
|
* 密码 |
||||||
|
*/ |
||||||
|
private String password; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态;0(默认):正常;4:封号;9:异常; |
||||||
|
*/ |
||||||
|
private Integer status; |
||||||
|
|
||||||
|
/** |
||||||
|
* 权限等级,默认200 |
||||||
|
*/ |
||||||
|
private Integer authorityLevel; |
||||||
|
|
||||||
|
/** |
||||||
|
* 密码修改次数 |
||||||
|
*/ |
||||||
|
private Integer pswChange; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,93 @@ |
|||||||
|
package cn.soul2.jyjc.admin.entity; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*; |
||||||
|
import com.baomidou.mybatisplus.extension.activerecord.Model; |
||||||
|
import lombok.Getter; |
||||||
|
import lombok.Setter; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
import java.time.LocalDateTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户表 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-30 14:34:13 |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
@Setter |
||||||
|
@Accessors(chain = true) |
||||||
|
@TableName("tb_user") |
||||||
|
public class UserDO extends Model<UserDO> { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
/** |
||||||
|
* id |
||||||
|
*/ |
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_UUID) |
||||||
|
private String id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户名 |
||||||
|
*/ |
||||||
|
@TableField("username") |
||||||
|
private String username; |
||||||
|
|
||||||
|
/** |
||||||
|
* 密码 |
||||||
|
*/ |
||||||
|
@TableField("password") |
||||||
|
private String password; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态;0(默认):正常;4:封号;9:异常; |
||||||
|
*/ |
||||||
|
@TableField("status") |
||||||
|
private Integer status; |
||||||
|
|
||||||
|
/** |
||||||
|
* 权限等级,默认200 |
||||||
|
*/ |
||||||
|
@TableField("authority_level") |
||||||
|
private Integer authorityLevel; |
||||||
|
|
||||||
|
/** |
||||||
|
* 密码修改次数 |
||||||
|
*/ |
||||||
|
@TableField("psw_change") |
||||||
|
private Integer pswChange; |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新时间 |
||||||
|
*/ |
||||||
|
@TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE) |
||||||
|
private LocalDateTime updatedTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建时间 |
||||||
|
*/ |
||||||
|
@TableField(value = "created_time", fill = FieldFill.INSERT) |
||||||
|
private LocalDateTime createdTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除标记 |
||||||
|
*/ |
||||||
|
@TableField("removed") |
||||||
|
@TableLogic |
||||||
|
private Integer removed; |
||||||
|
|
||||||
|
/** |
||||||
|
* 盐,用于密码加密,未启用 |
||||||
|
*/ |
||||||
|
@TableField("salt") |
||||||
|
private String salt; |
||||||
|
|
||||||
|
@Override |
||||||
|
public Serializable pkVal() { |
||||||
|
return this.id; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
package cn.soul2.jyjc.admin.entity; |
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.*; |
||||||
|
import com.baomidou.mybatisplus.extension.activerecord.Model; |
||||||
|
import lombok.Getter; |
||||||
|
import lombok.Setter; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
import java.io.Serializable; |
||||||
|
import java.time.LocalDateTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户登入登出表 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-30 13:57:00 |
||||||
|
*/ |
||||||
|
@Getter |
||||||
|
@Setter |
||||||
|
@Accessors(chain = true) |
||||||
|
@TableName("tb_user_login_out") |
||||||
|
public class UserLoginOutDO extends Model<UserLoginOutDO> { |
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L; |
||||||
|
|
||||||
|
/** |
||||||
|
* id |
||||||
|
*/ |
||||||
|
@TableId(value = "id", type = IdType.ASSIGN_UUID) |
||||||
|
private String id; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户id |
||||||
|
*/ |
||||||
|
@TableField("user_id") |
||||||
|
private String userId; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户名称 |
||||||
|
*/ |
||||||
|
@TableField("user_name") |
||||||
|
private String userName; |
||||||
|
|
||||||
|
/** |
||||||
|
* 登录时间,登录成功才写入 |
||||||
|
*/ |
||||||
|
@TableField("login_time") |
||||||
|
private LocalDateTime loginTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 登录失效时间 |
||||||
|
*/ |
||||||
|
@TableField("lapse_time") |
||||||
|
private LocalDateTime lapseTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户操作登出时间 |
||||||
|
*/ |
||||||
|
@TableField("logout_time") |
||||||
|
private LocalDateTime logoutTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 密码错误次数 |
||||||
|
*/ |
||||||
|
@TableField("psw_error_count") |
||||||
|
private Integer pswErrorCount; |
||||||
|
|
||||||
|
/** |
||||||
|
* 创建时间 |
||||||
|
*/ |
||||||
|
@TableField(value = "created_time", fill = FieldFill.INSERT) |
||||||
|
private LocalDateTime createdTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* 1=删除;0=未删除 |
||||||
|
*/ |
||||||
|
@TableField("removed") |
||||||
|
@TableLogic |
||||||
|
private Integer removed; |
||||||
|
|
||||||
|
@Override |
||||||
|
public Serializable pkVal() { |
||||||
|
return this.id; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
package cn.soul2.jyjc.admin.interceptor; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.annotation.SkinLogin; |
||||||
|
import cn.soul2.jyjc.admin.config.UserLoginStatusBean; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.web.method.HandlerMethod; |
||||||
|
import org.springframework.web.servlet.HandlerInterceptor; |
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest; |
||||||
|
import javax.servlet.http.HttpServletResponse; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-04-02 15:31 |
||||||
|
*/ |
||||||
|
|
||||||
|
public class TokenInterceptor implements HandlerInterceptor { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private UserLoginStatusBean userLoginStatusBean; |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
||||||
|
// 允许OPTIONS请求通过
|
||||||
|
if (isCorsRequest(request)) { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
// 跳过登录
|
||||||
|
// 如果处理器是一个方法处理器
|
||||||
|
if (handler instanceof HandlerMethod) { |
||||||
|
HandlerMethod handlerMethod = (HandlerMethod) handler; |
||||||
|
// 检查方法上是否存在SkinLogin注解
|
||||||
|
if (handlerMethod.getMethod().isAnnotationPresent(SkinLogin.class)) { |
||||||
|
// 如果存在,绕过拦截器
|
||||||
|
return true; |
||||||
|
} |
||||||
|
} |
||||||
|
// 验证token
|
||||||
|
// 从请求头中获取 token
|
||||||
|
String token = request.getHeader("jyjc-Token"); |
||||||
|
// 检查 token 是否存在并且有效,这里可以根据实际情况自行实现验证逻辑
|
||||||
|
if (token != null && isValidToken(token)) { |
||||||
|
// Token 有效,允许请求通过
|
||||||
|
return true; |
||||||
|
} else { |
||||||
|
// Token 无效,拒绝请求,可以返回特定的响应状态码,例如 401 Unauthorized
|
||||||
|
response.setStatus(40401); |
||||||
|
return false; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private boolean isValidToken(String token) { |
||||||
|
// 实现 token 验证逻辑,例如验证 token 的签名或者在数据库中验证 token 的有效性
|
||||||
|
return userLoginStatusBean.containsToken(token); |
||||||
|
// 返回 true 表示 token 有效,返回 false 表示 token 无效
|
||||||
|
} |
||||||
|
|
||||||
|
private boolean isCorsRequest(HttpServletRequest request) { |
||||||
|
// 检查请求头中是否包含 Origin 字段,如果存在,则认为是跨域请求
|
||||||
|
return request.getHeader("Origin") != null; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package cn.soul2.jyjc.admin.mapper; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.entity.UserLoginOutDO; |
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户登入登出表 Mapper 接口 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-29 20:46:42 |
||||||
|
*/ |
||||||
|
public interface UserLoginOutMapper extends BaseMapper<UserLoginOutDO> { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,16 @@ |
|||||||
|
package cn.soul2.jyjc.admin.mapper; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.entity.UserDO; |
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户表 Mapper 接口 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-29 20:46:42 |
||||||
|
*/ |
||||||
|
public interface UserMapper extends BaseMapper<UserDO> { |
||||||
|
|
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
package cn.soul2.jyjc.admin.repository; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginOutPageDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLogoutDTO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserDO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserLoginOutDO; |
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户登入登出表 服务类 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-29 20:46:42 |
||||||
|
*/ |
||||||
|
public interface IUserLoginOutRepository extends IService<UserLoginOutDO> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 分页查询 |
||||||
|
* |
||||||
|
* @param dto 查询条件 |
||||||
|
* @return {@link IPage}<{@link UserLoginOutDO}> |
||||||
|
*/ |
||||||
|
IPage<UserLoginOutDO> page(UserLoginOutPageDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户登录 |
||||||
|
* |
||||||
|
* @param dto 用户信息 |
||||||
|
* @param user 用户 |
||||||
|
* @return {@link String} |
||||||
|
*/ |
||||||
|
String login(UserLoginDTO dto, UserDO user); |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户登出 |
||||||
|
* |
||||||
|
* @param dto 用户信息 |
||||||
|
* @return {@link String} |
||||||
|
*/ |
||||||
|
String logout(UserLogoutDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户登出 |
||||||
|
* |
||||||
|
* @param userId 用户id |
||||||
|
* @return {@link String} |
||||||
|
*/ |
||||||
|
Boolean logoutByUserId(String userId); |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除目标用户的所有登录记录 |
||||||
|
* |
||||||
|
* @param userId 用户id |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
Boolean removeByUserId(String userId); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
package cn.soul2.jyjc.admin.repository; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.UserPageDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserSaveDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.base.UpdateStatusDTO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserDO; |
||||||
|
import cn.soul2.jyjc.admin.vo.base.VPage; |
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||||
|
import com.baomidou.mybatisplus.extension.service.IService; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户表 服务类 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-29 20:46:42 |
||||||
|
*/ |
||||||
|
public interface IUserRepository extends IService<UserDO> { |
||||||
|
|
||||||
|
/** |
||||||
|
* 分页查询 |
||||||
|
* |
||||||
|
* @param dto 查询条件 |
||||||
|
* @return {@link VPage}<{@link UserDO}> |
||||||
|
*/ |
||||||
|
IPage<UserDO> page(UserPageDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 保存或更新 |
||||||
|
* |
||||||
|
* @param dto 有/无id区分更新/新增 |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
Boolean saveOrUpdate(UserSaveDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 更新状态 |
||||||
|
* |
||||||
|
* @param dto 新状态 |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
Boolean updateStatus(UpdateStatusDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 读取指定名字的用户 |
||||||
|
* |
||||||
|
* @param username 用户名 |
||||||
|
* @return {@link UserDO} |
||||||
|
*/ |
||||||
|
UserDO getOneByUsername(String username); |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
package cn.soul2.jyjc.admin.repository.impl; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.config.UserLoginStatusBean; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginOutPageDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLogoutDTO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserDO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserLoginOutDO; |
||||||
|
import cn.soul2.jyjc.admin.mapper.UserLoginOutMapper; |
||||||
|
import cn.soul2.jyjc.admin.repository.IUserLoginOutRepository; |
||||||
|
import cn.soul2.jyjc.admin.utils.base.PageUtils; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
import java.time.LocalDateTime; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户登入登出表 服务实现类 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-29 20:46:42 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class UserLoginOutRepositoryImpl extends ServiceImpl<UserLoginOutMapper, UserLoginOutDO> implements IUserLoginOutRepository { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private UserLoginStatusBean userLoginStatusBean; |
||||||
|
|
||||||
|
@Override |
||||||
|
public IPage<UserLoginOutDO> page(UserLoginOutPageDTO dto) { |
||||||
|
LambdaQueryWrapper<UserLoginOutDO> query = Wrappers.lambdaQuery(); |
||||||
|
query.eq(StringUtils.isNotBlank(dto.getUserId()), UserLoginOutDO::getUserId, dto.getUserId()) |
||||||
|
.orderByDesc(UserLoginOutDO::getCreatedTime); |
||||||
|
return super.page(PageUtils.build(dto), query); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String login(UserLoginDTO dto, UserDO user) { |
||||||
|
UserLoginOutDO loginOutDO; |
||||||
|
boolean saved; |
||||||
|
LocalDateTime now = LocalDateTime.now(); |
||||||
|
// 判断是否登陆过,在缓存无法读取到目标用户名时即未登录,若登录过则令之前的登录记录失效
|
||||||
|
String token = userLoginStatusBean.getTokenByUsername(dto.getUsername()); |
||||||
|
if (token != null) { |
||||||
|
userLoginStatusBean.logout(token); |
||||||
|
UserLoginOutDO oldLoginOut = super.getById(token); |
||||||
|
oldLoginOut.setLapseTime(now).setLogoutTime(now); |
||||||
|
super.updateById(oldLoginOut); |
||||||
|
} |
||||||
|
loginOutDO = new UserLoginOutDO(); |
||||||
|
loginOutDO.setUserId(user.getId()) |
||||||
|
.setUserName(user.getUsername()) |
||||||
|
.setLoginTime(now) |
||||||
|
.setLapseTime(now.plusHours(2)) |
||||||
|
; |
||||||
|
saved = super.save(loginOutDO); |
||||||
|
if (saved) { |
||||||
|
userLoginStatusBean.login(loginOutDO.getId(), loginOutDO); |
||||||
|
return loginOutDO.getId(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String logout(UserLogoutDTO dto) { |
||||||
|
// 清除缓存内的登录信息
|
||||||
|
Boolean logout = userLoginStatusBean.logout(dto.getToken()); |
||||||
|
// 保存退出登录的时间
|
||||||
|
LocalDateTime now = LocalDateTime.now(); |
||||||
|
UserLoginOutDO oldLoginOut = super.getById(dto.getToken()); |
||||||
|
oldLoginOut.setLogoutTime(now); |
||||||
|
super.updateById(oldLoginOut); |
||||||
|
|
||||||
|
return logout ? dto.getUsername() : null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean logoutByUserId(String userId) { |
||||||
|
return userLoginStatusBean.logoutByUserId(userId); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean removeByUserId(String userId) { |
||||||
|
if (org.apache.commons.lang3.StringUtils.isBlank(userId)) { |
||||||
|
return Boolean.TRUE; |
||||||
|
} |
||||||
|
LambdaUpdateWrapper<UserLoginOutDO> update = Wrappers.lambdaUpdate(); |
||||||
|
update.eq(UserLoginOutDO::getUserId, userId); |
||||||
|
return super.remove(update); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,60 @@ |
|||||||
|
package cn.soul2.jyjc.admin.repository.impl; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.UserPageDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserSaveDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.base.UpdateStatusDTO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserDO; |
||||||
|
import cn.soul2.jyjc.admin.mapper.UserMapper; |
||||||
|
import cn.soul2.jyjc.admin.repository.IUserRepository; |
||||||
|
import cn.soul2.jyjc.admin.utils.base.PageUtils; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
||||||
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
||||||
|
import org.springframework.beans.BeanUtils; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
/** |
||||||
|
* <p> |
||||||
|
* 用户表 服务实现类 |
||||||
|
* </p> |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @since 2024-03-29 20:46:42 |
||||||
|
*/ |
||||||
|
@Service |
||||||
|
public class UserRepositoryImpl extends ServiceImpl<UserMapper, UserDO> implements IUserRepository { |
||||||
|
|
||||||
|
@Override |
||||||
|
public IPage<UserDO> page(UserPageDTO dto) { |
||||||
|
LambdaQueryWrapper<UserDO> query = Wrappers.lambdaQuery(); |
||||||
|
query.eq(dto.getStatus() != null, UserDO::getStatus, dto.getStatus()) |
||||||
|
.like(StringUtils.isNotBlank(dto.getUsername()), UserDO::getUsername, dto.getUsername()) |
||||||
|
.orderByDesc(UserDO::getUpdatedTime); |
||||||
|
return super.page(PageUtils.build(dto), query); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean saveOrUpdate(UserSaveDTO dto) { |
||||||
|
UserDO user = new UserDO(); |
||||||
|
BeanUtils.copyProperties(dto, user); |
||||||
|
return super.saveOrUpdate(user); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean updateStatus(UpdateStatusDTO dto) { |
||||||
|
LambdaUpdateWrapper<UserDO> update = Wrappers.lambdaUpdate(); |
||||||
|
update.set(UserDO::getStatus, dto.getStatus()) |
||||||
|
.eq(UserDO::getId, dto.getId()); |
||||||
|
return super.update(update); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UserDO getOneByUsername(String username) { |
||||||
|
LambdaQueryWrapper<UserDO> query = Wrappers.lambdaQuery(); |
||||||
|
query.eq(UserDO::getUsername, username); |
||||||
|
return super.getOne(query, false); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,20 @@ |
|||||||
|
package cn.soul2.jyjc.admin.service; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.AnswerSubmitDTO; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-27 14:43 |
||||||
|
*/ |
||||||
|
|
||||||
|
public interface IAnswerService { |
||||||
|
|
||||||
|
/** |
||||||
|
* 提交答卷 |
||||||
|
* |
||||||
|
* @param dto 答卷内容 |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
Boolean handleSubmit(AnswerSubmitDTO dto); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
package cn.soul2.jyjc.admin.service; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLogoutDTO; |
||||||
|
import cn.soul2.jyjc.admin.vo.UserVO; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 20:47 |
||||||
|
*/ |
||||||
|
|
||||||
|
public interface IUserService { |
||||||
|
|
||||||
|
/** |
||||||
|
* 注册一个用户 |
||||||
|
* |
||||||
|
* @param dto 用户名和密码 |
||||||
|
* @return {@link UserVO} |
||||||
|
*/ |
||||||
|
UserVO register(UserLoginDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户登录 |
||||||
|
* |
||||||
|
* @param dto 用户名和密码 |
||||||
|
* @return {@link UserVO} |
||||||
|
*/ |
||||||
|
UserVO login(UserLoginDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 用户退出登录 |
||||||
|
* |
||||||
|
* @param dto 登录key |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
Boolean logout(UserLogoutDTO dto); |
||||||
|
|
||||||
|
/** |
||||||
|
* 删除用户并退出登录,同时将登录记录一并删除 |
||||||
|
* |
||||||
|
* @param userId 用户id |
||||||
|
* @return {@link Boolean} |
||||||
|
*/ |
||||||
|
Boolean remove(String userId); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,58 @@ |
|||||||
|
package cn.soul2.jyjc.admin.service.impl; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.AnswerSubmitDTO; |
||||||
|
import cn.soul2.jyjc.admin.entity.AnswerDetailsDO; |
||||||
|
import cn.soul2.jyjc.admin.entity.AnswerSheetDO; |
||||||
|
import cn.soul2.jyjc.admin.repository.IAnswerDetailsRepository; |
||||||
|
import cn.soul2.jyjc.admin.repository.IAnswerSheetRepository; |
||||||
|
import cn.soul2.jyjc.admin.service.IAnswerService; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
import org.springframework.transaction.annotation.Transactional; |
||||||
|
import org.springframework.transaction.interceptor.TransactionAspectSupport; |
||||||
|
|
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-27 14:43 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Service |
||||||
|
public class AnswerServiceImpl implements IAnswerService { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IAnswerSheetRepository sheetRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IAnswerDetailsRepository detailsRepository; |
||||||
|
|
||||||
|
@Override |
||||||
|
@Transactional |
||||||
|
public Boolean handleSubmit(AnswerSubmitDTO dto) { |
||||||
|
AnswerSheetDO sheet = new AnswerSheetDO(); |
||||||
|
sheet.setRespondent(dto.getOpenid()) |
||||||
|
.setQnId(dto.getQnId()) |
||||||
|
.setQrId(dto.getQrId()); |
||||||
|
boolean sheetSaved = sheetRepository.save(sheet); |
||||||
|
if (sheetSaved) { |
||||||
|
List<AnswerDetailsDO> details = dto.getDetails().stream().map(d -> { |
||||||
|
AnswerDetailsDO detail = new AnswerDetailsDO(); |
||||||
|
detail.setAnswerContent(d.getContent()) |
||||||
|
.setAnswerSheetId(sheet.getId()) |
||||||
|
.setSubjectType(d.getSubjectType()) |
||||||
|
.setSubjectId(d.getSubjectId()); |
||||||
|
return detail; |
||||||
|
}).collect(Collectors.toList()); |
||||||
|
boolean detailsSaved = detailsRepository.saveBatch(details); |
||||||
|
if (!detailsSaved) { |
||||||
|
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); |
||||||
|
return Boolean.FALSE; |
||||||
|
} |
||||||
|
} else { |
||||||
|
return Boolean.FALSE; |
||||||
|
} |
||||||
|
return Boolean.TRUE; |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,87 @@ |
|||||||
|
package cn.soul2.jyjc.admin.service.impl; |
||||||
|
|
||||||
|
import cn.soul2.jyjc.admin.dto.UserLoginDTO; |
||||||
|
import cn.soul2.jyjc.admin.dto.UserLogoutDTO; |
||||||
|
import cn.soul2.jyjc.admin.entity.UserDO; |
||||||
|
import cn.soul2.jyjc.admin.repository.IUserLoginOutRepository; |
||||||
|
import cn.soul2.jyjc.admin.repository.IUserRepository; |
||||||
|
import cn.soul2.jyjc.admin.service.IUserService; |
||||||
|
import cn.soul2.jyjc.admin.utils.Md5Utils; |
||||||
|
import cn.soul2.jyjc.admin.vo.UserVO; |
||||||
|
import org.springframework.beans.BeanUtils; |
||||||
|
import org.springframework.beans.factory.annotation.Autowired; |
||||||
|
import org.springframework.stereotype.Service; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-29 20:47 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Service |
||||||
|
public class UserServiceImpl implements IUserService { |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IUserRepository userRepository; |
||||||
|
|
||||||
|
@Autowired |
||||||
|
private IUserLoginOutRepository loginOutRepository; |
||||||
|
|
||||||
|
@Override |
||||||
|
public UserVO register(UserLoginDTO dto) { |
||||||
|
UserVO vo = new UserVO(); |
||||||
|
if (userRepository.getOneByUsername(dto.getUsername()) == null) { |
||||||
|
UserDO user = new UserDO(); |
||||||
|
user.setUsername(dto.getUsername()) |
||||||
|
.setPassword(Md5Utils.md5(dto.getPassword())); |
||||||
|
boolean saved = userRepository.save(user); |
||||||
|
if (!saved) { |
||||||
|
vo.setLoginFail("注册失败!"); |
||||||
|
} else { |
||||||
|
String loginKey = loginOutRepository.login(dto, user); |
||||||
|
if (loginKey != null) { |
||||||
|
BeanUtils.copyProperties(user, vo); |
||||||
|
vo.setToken(loginKey); |
||||||
|
} else { |
||||||
|
vo.setLoginFail("注册成功但登录失败!"); |
||||||
|
} |
||||||
|
} |
||||||
|
} else { |
||||||
|
vo.setLoginFail("用户名已存在!"); |
||||||
|
} |
||||||
|
return vo; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public UserVO login(UserLoginDTO dto) { |
||||||
|
UserVO vo = new UserVO(); |
||||||
|
UserDO user = userRepository.getOneByUsername(dto.getUsername()); |
||||||
|
if (user != null) { |
||||||
|
if (Md5Utils.verify(user.getPassword(), dto.getPassword())) { |
||||||
|
String loginKey = loginOutRepository.login(dto, user); |
||||||
|
if (loginKey != null) { |
||||||
|
BeanUtils.copyProperties(user, vo); |
||||||
|
vo.setToken(loginKey); |
||||||
|
} else { |
||||||
|
vo.setLoginFail("登录失败!"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
vo.setLoginFail("密码错误!"); |
||||||
|
} |
||||||
|
} else { |
||||||
|
vo.setLoginFail("该用户尚未注册!"); |
||||||
|
} |
||||||
|
return vo; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean logout(UserLogoutDTO dto) { |
||||||
|
return loginOutRepository.logout(dto) != null; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Boolean remove(String userId) { |
||||||
|
loginOutRepository.logoutByUserId(userId); |
||||||
|
loginOutRepository.removeByUserId(userId); |
||||||
|
return userRepository.removeById(userId); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
package cn.soul2.jyjc.admin.utils; |
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value; |
||||||
|
|
||||||
|
import javax.crypto.Cipher; |
||||||
|
import javax.crypto.spec.SecretKeySpec; |
||||||
|
import java.util.Base64; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-30 14:02 |
||||||
|
*/ |
||||||
|
|
||||||
|
public class AesUtils { |
||||||
|
|
||||||
|
@Value("${encrypt.keys.aes}") |
||||||
|
private String aesKey; |
||||||
|
|
||||||
|
private static final String AES_ALGORITHM = "AES"; |
||||||
|
|
||||||
|
private SecretKeySpec generateKey(String key) { |
||||||
|
return new SecretKeySpec(key.getBytes(), AES_ALGORITHM); |
||||||
|
} |
||||||
|
|
||||||
|
public String encrypt(String source) throws Exception { |
||||||
|
return encrypt(source, aesKey); |
||||||
|
} |
||||||
|
|
||||||
|
public String decrypt(String encrypted) throws Exception { |
||||||
|
return decrypt(encrypted, aesKey); |
||||||
|
} |
||||||
|
|
||||||
|
private String encrypt(String source, String key) throws Exception { |
||||||
|
Cipher cipher = Cipher.getInstance(AES_ALGORITHM); |
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, generateKey(key)); |
||||||
|
byte[] encryptedBytes = cipher.doFinal(source.getBytes()); |
||||||
|
return Base64.getEncoder().encodeToString(encryptedBytes); |
||||||
|
} |
||||||
|
|
||||||
|
private String decrypt(String encrypted, String key) throws Exception { |
||||||
|
Cipher cipher = Cipher.getInstance(AES_ALGORITHM); |
||||||
|
cipher.init(Cipher.DECRYPT_MODE, generateKey(key)); |
||||||
|
byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encrypted)); |
||||||
|
return new String(decryptedBytes); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
|
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
} |
@ -0,0 +1,33 @@ |
|||||||
|
package cn.soul2.jyjc.admin.utils; |
||||||
|
|
||||||
|
import org.springframework.util.DigestUtils; |
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets; |
||||||
|
import java.util.Objects; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author fuzongyao |
||||||
|
* @date 2021/10/14 11:19 |
||||||
|
* @since 1.0 |
||||||
|
*/ |
||||||
|
public class Md5Utils { |
||||||
|
|
||||||
|
/** |
||||||
|
* 加盐 |
||||||
|
*/ |
||||||
|
private static final String SALT = "4v6dKAOn+tEiVH58/XKeUw=="; |
||||||
|
|
||||||
|
public static String md5(String body) { |
||||||
|
body += SALT; |
||||||
|
return DigestUtils.md5DigestAsHex(body.getBytes(StandardCharsets.UTF_8)).toUpperCase(); |
||||||
|
} |
||||||
|
|
||||||
|
public static boolean verify(String md5, String body) { |
||||||
|
return Objects.equals(md5, md5(body)); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
System.out.println(md5("123456")); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,35 @@ |
|||||||
|
package cn.soul2.jyjc.admin.utils; |
||||||
|
|
||||||
|
import java.security.SecureRandom; |
||||||
|
import java.util.Base64; |
||||||
|
|
||||||
|
/** |
||||||
|
* 盐值生成 |
||||||
|
* |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-30 14:30 |
||||||
|
*/ |
||||||
|
|
||||||
|
public class SaltUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* 生成指定长度的盐值 |
||||||
|
* |
||||||
|
* @param length 盐值长度 |
||||||
|
* @return {@link String} |
||||||
|
*/ |
||||||
|
public static String generateSalt(int length) { |
||||||
|
SecureRandom random = new SecureRandom(); |
||||||
|
byte[] salt = new byte[length]; |
||||||
|
random.nextBytes(salt); |
||||||
|
return Base64.getEncoder().encodeToString(salt); |
||||||
|
} |
||||||
|
|
||||||
|
public static void main(String[] args) { |
||||||
|
// 设置盐值长度
|
||||||
|
int saltLength = 16; |
||||||
|
String salt = generateSalt(saltLength); |
||||||
|
System.out.println("Generated Salt: " + salt); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
package cn.soul2.jyjc.admin.vo; |
||||||
|
|
||||||
|
import lombok.Data; |
||||||
|
import lombok.experimental.Accessors; |
||||||
|
|
||||||
|
/** |
||||||
|
* @author Soul2 |
||||||
|
* @date 2024-03-30 14:40 |
||||||
|
*/ |
||||||
|
|
||||||
|
@Data |
||||||
|
@Accessors(chain = true) |
||||||
|
public class UserVO { |
||||||
|
|
||||||
|
/** |
||||||
|
* username |
||||||
|
*/ |
||||||
|
private String username; |
||||||
|
|
||||||
|
/** |
||||||
|
* token |
||||||
|
* 其实就是'UserLoginOut'表的id |
||||||
|
*/ |
||||||
|
private String token; |
||||||
|
|
||||||
|
/** |
||||||
|
* 权限等级 |
||||||
|
*/ |
||||||
|
private String authorityLevel; |
||||||
|
|
||||||
|
/** |
||||||
|
* 状态;0(默认):正常;4:封号;9:异常; |
||||||
|
*/ |
||||||
|
private Integer status; |
||||||
|
|
||||||
|
private String loginFail; |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue