commit
896e88c8e1
@ -46,7 +46,9 @@ user:
|
|||||||
maxRetryCount: 5
|
maxRetryCount: 5
|
||||||
# 密码锁定时间(默认10分钟)
|
# 密码锁定时间(默认10分钟)
|
||||||
lockTime: 10
|
lockTime: 10
|
||||||
|
ip:
|
||||||
|
maxRetryCount: 15
|
||||||
|
lockTime: 15
|
||||||
# Spring配置
|
# Spring配置
|
||||||
spring:
|
spring:
|
||||||
cache:
|
cache:
|
||||||
|
@ -2,7 +2,7 @@ package com.ruoyi.common.constant;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存的key 常量
|
* 缓存的key 常量
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
public class CacheConstants {
|
public class CacheConstants {
|
||||||
@ -41,6 +41,11 @@ public class CacheConstants {
|
|||||||
*/
|
*/
|
||||||
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt";
|
public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录ip错误次数 redis key
|
||||||
|
*/
|
||||||
|
public static final String IP_ERR_CNT_KEY = "ip_err_cnt_key";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 手机号验证码 phone codes
|
* 手机号验证码 phone codes
|
||||||
*/
|
*/
|
||||||
@ -50,4 +55,14 @@ public class CacheConstants {
|
|||||||
* 邮箱验证码
|
* 邮箱验证码
|
||||||
*/
|
*/
|
||||||
public static final String EMAIL_CODES = "email_codes";
|
public static final String EMAIL_CODES = "email_codes";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件的md5 redis key
|
||||||
|
*/
|
||||||
|
public static final String FILE_MD5_PATH_KEY = "file_md5_path";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件路径 redis key
|
||||||
|
*/
|
||||||
|
public static final String FILE_PATH_MD5_KEY = "file_path_md5";
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
package com.ruoyi.common.exception.user;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP 登录重试次数超限异常类
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IpRetryLimitExceedException extends RuntimeException
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public IpRetryLimitExceedException(int retryLimitCount, int lockTime)
|
||||||
|
{
|
||||||
|
super("失败次数过多,你的ip暂时被限制登录.");
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import com.ruoyi.common.constant.Constants;
|
|||||||
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
|
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.StringUtils;
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.sign.Md5Utils;
|
||||||
import com.ruoyi.common.utils.uuid.UUID;
|
import com.ruoyi.common.utils.uuid.UUID;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
@ -96,7 +97,11 @@ public class DiskFileService implements FileService {
|
|||||||
File file = new File(fileAbs);
|
File file = new File(fileAbs);
|
||||||
// 路径为文件且不为空则进行删除
|
// 路径为文件且不为空则进行删除
|
||||||
if (file.isFile() && file.exists()) {
|
if (file.isFile() && file.exists()) {
|
||||||
|
String md5 = Md5Utils.getMd5(file);
|
||||||
flag = file.delete();
|
flag = file.delete();
|
||||||
|
if(flag) {
|
||||||
|
FileOperateUtils.deleteFileAndMd5ByMd5(md5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return flag;
|
return flag;
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package com.ruoyi.common.utils.file;
|
package com.ruoyi.common.utils.file;
|
||||||
|
|
||||||
import com.ruoyi.common.config.RuoYiConfig;
|
import com.ruoyi.common.config.RuoYiConfig;
|
||||||
|
import com.ruoyi.common.constant.CacheConstants;
|
||||||
|
import com.ruoyi.common.utils.CacheUtils;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.utils.sign.Md5Utils;
|
||||||
import com.ruoyi.common.utils.spring.SpringUtils;
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
@ -35,8 +39,15 @@ public class FileOperateUtils {
|
|||||||
*/
|
*/
|
||||||
public static final String upload(MultipartFile file) throws IOException {
|
public static final String upload(MultipartFile file) throws IOException {
|
||||||
try {
|
try {
|
||||||
|
String md5 = Md5Utils.getMd5(file);
|
||||||
|
String pathForMd5 = FileOperateUtils.getFilePathForMd5(md5);
|
||||||
|
if (StringUtils.isNotEmpty(pathForMd5)) {
|
||||||
|
return pathForMd5;
|
||||||
|
}
|
||||||
FileUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
|
FileUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
|
||||||
return fileService.upload(file);
|
String pathFileName = fileService.upload(file);
|
||||||
|
FileOperateUtils.saveFileAndMd5(pathFileName, md5);
|
||||||
|
return pathFileName;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IOException(e.getMessage(), e);
|
throw new IOException(e.getMessage(), e);
|
||||||
}
|
}
|
||||||
@ -52,8 +63,15 @@ public class FileOperateUtils {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static final String upload(String filePath, MultipartFile file, String[] allowedExtension) throws Exception {
|
public static final String upload(String filePath, MultipartFile file, String[] allowedExtension) throws Exception {
|
||||||
|
String md5 = Md5Utils.getMd5(file);
|
||||||
|
String pathForMd5 = FileOperateUtils.getFilePathForMd5(md5);
|
||||||
|
if (StringUtils.isNotEmpty(pathForMd5)) {
|
||||||
|
return pathForMd5;
|
||||||
|
}
|
||||||
FileUtils.assertAllowed(file, allowedExtension);
|
FileUtils.assertAllowed(file, allowedExtension);
|
||||||
return fileService.upload(filePath, file);
|
String pathFileName = fileService.upload(filePath, file);
|
||||||
|
FileOperateUtils.saveFileAndMd5(pathFileName, md5);
|
||||||
|
return pathFileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -67,7 +85,7 @@ public class FileOperateUtils {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public static final String upload(String baseDir, String fileName, MultipartFile file,
|
public static final String upload(String baseDir, String fileName, MultipartFile file,
|
||||||
String[] allowedExtension)
|
String[] allowedExtension)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
try {
|
try {
|
||||||
String filePath = baseDir + File.separator + fileName;
|
String filePath = baseDir + File.separator + fileName;
|
||||||
@ -100,4 +118,46 @@ public class FileOperateUtils {
|
|||||||
public static final boolean deleteFile(String fileUrl) throws Exception {
|
public static final boolean deleteFile(String fileUrl) throws Exception {
|
||||||
return fileService.deleteFile(fileUrl);
|
return fileService.deleteFile(fileUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据md5获取文件的路径
|
||||||
|
*
|
||||||
|
* @param md5 文件的md5
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getFilePathForMd5(String md5) {
|
||||||
|
return CacheUtils.get(CacheConstants.FILE_MD5_PATH_KEY, md5, String.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存文件的md5
|
||||||
|
*
|
||||||
|
* @param path 文件的路径
|
||||||
|
* @param md5 文件的md5
|
||||||
|
*/
|
||||||
|
public static void saveFileAndMd5(String path, String md5) {
|
||||||
|
CacheUtils.put(CacheConstants.FILE_MD5_PATH_KEY, md5, path);
|
||||||
|
CacheUtils.put(CacheConstants.FILE_PATH_MD5_KEY, path, md5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除文件的md5
|
||||||
|
*
|
||||||
|
* @param md5 文件的md5
|
||||||
|
*/
|
||||||
|
public static void deleteFileAndMd5ByMd5(String md5) {
|
||||||
|
String filePathByMd5 = getFilePathForMd5(md5);
|
||||||
|
if (StringUtils.isNotEmpty(filePathByMd5)) {
|
||||||
|
CacheUtils.remove(CacheConstants.FILE_MD5_PATH_KEY, md5);
|
||||||
|
CacheUtils.remove(CacheConstants.FILE_PATH_MD5_KEY, filePathByMd5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteFileAndMd5ByFilePath(String filePath) {
|
||||||
|
String md5ByFilePath = CacheUtils.get(CacheConstants.FILE_PATH_MD5_KEY, filePath, String.class);
|
||||||
|
if (StringUtils.isNotEmpty(md5ByFilePath)) {
|
||||||
|
CacheUtils.remove(CacheConstants.FILE_PATH_MD5_KEY, filePath);
|
||||||
|
CacheUtils.remove(CacheConstants.FILE_MD5_PATH_KEY, md5ByFilePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,21 +1,32 @@
|
|||||||
package com.ruoyi.common.utils.sign;
|
package com.ruoyi.common.utils.sign;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Md5加密方法
|
* Md5加密方法
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
public class Md5Utils {
|
public class Md5Utils {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
|
private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
|
||||||
|
|
||||||
|
private static final ThreadLocal<MessageDigest> md5DigestThreadLocal = ThreadLocal.withInitial(() -> {
|
||||||
|
try {
|
||||||
|
return MessageDigest.getInstance("MD5");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("MD5 algorithm not found", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
private static byte[] md5(String s) {
|
private static byte[] md5(String s) {
|
||||||
MessageDigest algorithm;
|
MessageDigest algorithm;
|
||||||
try {
|
try {
|
||||||
@ -62,4 +73,91 @@ public class Md5Utils {
|
|||||||
public static String encryptMd5(String string, String charSet) throws UnsupportedEncodingException {
|
public static String encryptMd5(String string, String charSet) throws UnsupportedEncodingException {
|
||||||
return DigestUtils.md5Hex(string.getBytes(charSet));
|
return DigestUtils.md5Hex(string.getBytes(charSet));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算文件的md5
|
||||||
|
* @param file 文件,可以是 MultipartFile 或 File
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getMd5(Object file) {
|
||||||
|
try {
|
||||||
|
InputStream inputStream = getInputStream(file);
|
||||||
|
long fileSize = getFileSize(file);
|
||||||
|
// 10MB作为分界点
|
||||||
|
if (fileSize < 10 * 1024 * 1024) {
|
||||||
|
return getMd5ForSmallFile(inputStream);
|
||||||
|
} else {
|
||||||
|
return getMd5ForLargeFile(inputStream);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static InputStream getInputStream(Object file) throws IOException {
|
||||||
|
if (file instanceof MultipartFile) {
|
||||||
|
return ((MultipartFile) file).getInputStream();
|
||||||
|
} else if (file instanceof File) {
|
||||||
|
return new FileInputStream((File) file);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unsupported file type");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getFileSize(Object file) throws IOException {
|
||||||
|
if (file instanceof MultipartFile) {
|
||||||
|
return ((MultipartFile) file).getSize();
|
||||||
|
} else if (file instanceof File) {
|
||||||
|
return ((File) file).length();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Unsupported file type");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算小文件的md5
|
||||||
|
*
|
||||||
|
* @param inputStream 文件输入流
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getMd5ForSmallFile(InputStream inputStream) {
|
||||||
|
try {
|
||||||
|
byte[] uploadBytes = inputStream.readAllBytes();
|
||||||
|
MessageDigest md5 = md5DigestThreadLocal.get();
|
||||||
|
byte[] digest = md5.digest(uploadBytes);
|
||||||
|
String md5Hex = new BigInteger(1, digest).toString(16);
|
||||||
|
while (md5Hex.length() < 32) {
|
||||||
|
md5Hex = "0" + md5Hex;
|
||||||
|
}
|
||||||
|
return md5Hex;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 计算大文件的md5
|
||||||
|
*
|
||||||
|
* @param inputStream 文件输入流
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private static String getMd5ForLargeFile(InputStream inputStream) {
|
||||||
|
try (InputStream is = inputStream) {
|
||||||
|
MessageDigest md = md5DigestThreadLocal.get();
|
||||||
|
byte[] buffer = new byte[81920];
|
||||||
|
int read;
|
||||||
|
while ((read = is.read(buffer)) != -1) {
|
||||||
|
md.update(buffer, 0, read);
|
||||||
|
}
|
||||||
|
byte[] digest = md.digest();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte b : digest) {
|
||||||
|
sb.append(String.format("%02x", b));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ import jakarta.annotation.Resource;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录校验方法
|
* 登录校验方法
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
@ -51,9 +51,12 @@ public class SysLoginService
|
|||||||
@Autowired
|
@Autowired
|
||||||
private ISysConfigService configService;
|
private ISysConfigService configService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private SysPasswordService passwordService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录验证
|
* 登录验证
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param password 密码
|
* @param password 密码
|
||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
@ -66,6 +69,9 @@ public class SysLoginService
|
|||||||
validateCaptcha(username, code, uuid);
|
validateCaptcha(username, code, uuid);
|
||||||
// 登录前置校验
|
// 登录前置校验
|
||||||
loginPreCheck(username, password);
|
loginPreCheck(username, password);
|
||||||
|
String ip = IpUtils.getIpAddr();
|
||||||
|
// 验证 IP 是否被封锁
|
||||||
|
passwordService.validateIp(ip);
|
||||||
// 用户验证
|
// 用户验证
|
||||||
Authentication authentication = null;
|
Authentication authentication = null;
|
||||||
try
|
try
|
||||||
@ -84,6 +90,7 @@ public class SysLoginService
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
passwordService.incrementIpFailCount(ip);
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
|
||||||
throw new ServiceException(e.getMessage());
|
throw new ServiceException(e.getMessage());
|
||||||
}
|
}
|
||||||
@ -101,7 +108,7 @@ public class SysLoginService
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 校验验证码
|
* 校验验证码
|
||||||
*
|
*
|
||||||
* @param username 用户名
|
* @param username 用户名
|
||||||
* @param code 验证码
|
* @param code 验证码
|
||||||
* @param uuid 唯一标识
|
* @param uuid 唯一标识
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package com.ruoyi.framework.web.service;
|
package com.ruoyi.framework.web.service;
|
||||||
|
|
||||||
|
import com.ruoyi.common.exception.user.IpRetryLimitExceedException;
|
||||||
|
import com.ruoyi.common.utils.ip.IpUtils;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.security.core.Authentication;
|
import org.springframework.security.core.Authentication;
|
||||||
@ -17,20 +19,28 @@ import com.ruoyi.framework.manager.AsyncManager;
|
|||||||
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
import com.ruoyi.framework.manager.factory.AsyncFactory;
|
||||||
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
|
import com.ruoyi.framework.security.context.AuthenticationContextHolder;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录密码方法
|
* 登录密码方法
|
||||||
*
|
*
|
||||||
* @author ruoyi
|
* @author ruoyi
|
||||||
*/
|
*/
|
||||||
@Component
|
@Component
|
||||||
public class SysPasswordService
|
public class SysPasswordService
|
||||||
{
|
{
|
||||||
|
|
||||||
@Value(value = "${user.password.maxRetryCount}")
|
@Value(value = "${user.password.maxRetryCount}")
|
||||||
private int maxRetryCount;
|
private int maxRetryCount;
|
||||||
|
|
||||||
@Value(value = "${user.password.lockTime}")
|
@Value(value = "${user.password.lockTime}")
|
||||||
private int lockTime;
|
private int lockTime;
|
||||||
|
|
||||||
|
@Value(value = "${user.ip.maxRetryCount:15}")
|
||||||
|
public int maxIpRetryCount;
|
||||||
|
|
||||||
|
@Value(value = "${user.ip.lockTime:15}")
|
||||||
|
public int ipLockTime;
|
||||||
/**
|
/**
|
||||||
* 登录账户密码错误次数缓存键名
|
* 登录账户密码错误次数缓存键名
|
||||||
*
|
*
|
||||||
@ -41,11 +51,18 @@ public class SysPasswordService
|
|||||||
return CacheUtils.getCache(CacheConstants.PWD_ERR_CNT_KEY);
|
return CacheUtils.getCache(CacheConstants.PWD_ERR_CNT_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Cache getIpCache() {
|
||||||
|
return CacheUtils.getCache(CacheConstants.IP_ERR_CNT_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
public void validate(SysUser user)
|
public void validate(SysUser user)
|
||||||
{
|
{
|
||||||
Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
|
Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
|
||||||
String username = usernamePasswordAuthenticationToken.getName();
|
String username = usernamePasswordAuthenticationToken.getName();
|
||||||
String password = usernamePasswordAuthenticationToken.getCredentials().toString();
|
String password = usernamePasswordAuthenticationToken.getCredentials().toString();
|
||||||
|
|
||||||
|
String ip = IpUtils.getIpAddr();
|
||||||
|
validateIp(ip);
|
||||||
Integer retryCount = getCache().get(username, Integer.class);
|
Integer retryCount = getCache().get(username, Integer.class);
|
||||||
if (retryCount == null)
|
if (retryCount == null)
|
||||||
{
|
{
|
||||||
@ -62,7 +79,7 @@ public class SysPasswordService
|
|||||||
retryCount = retryCount + 1;
|
retryCount = retryCount + 1;
|
||||||
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL,
|
||||||
MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
MessageUtils.message("user.password.retry.limit.count", retryCount)));
|
||||||
getCache().put(username, retryCount);
|
CacheUtils.put(CacheConstants.PWD_ERR_CNT_KEY,username,retryCount,lockTime,TimeUnit.MINUTES);
|
||||||
throw new UserPasswordNotMatchException();
|
throw new UserPasswordNotMatchException();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -71,6 +88,31 @@ public class SysPasswordService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void validateIp(String ip)
|
||||||
|
{
|
||||||
|
Integer ipRetryCount = getIpCache().get(ip, Integer.class);
|
||||||
|
if (ipRetryCount == null)
|
||||||
|
{
|
||||||
|
ipRetryCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ipRetryCount >= maxIpRetryCount)
|
||||||
|
{
|
||||||
|
throw new IpRetryLimitExceedException(maxIpRetryCount, ipLockTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrementIpFailCount(String ip)
|
||||||
|
{
|
||||||
|
Integer ipRetryCount = getIpCache().get(ip, Integer.class);
|
||||||
|
if (ipRetryCount == null)
|
||||||
|
{
|
||||||
|
ipRetryCount = 0;
|
||||||
|
}
|
||||||
|
ipRetryCount += 1;
|
||||||
|
CacheUtils.put(CacheConstants.IP_ERR_CNT_KEY,ip,ipRetryCount,ipLockTime,TimeUnit.MINUTES);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean matches(SysUser user, String rawPassword)
|
public boolean matches(SysUser user, String rawPassword)
|
||||||
{
|
{
|
||||||
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
|
return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
|
||||||
|
@ -3,6 +3,8 @@ package com.ruoyi.middleware.minio.utils;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import com.ruoyi.common.utils.file.FileOperateUtils;
|
||||||
|
import com.ruoyi.common.utils.sign.Md5Utils;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
@ -15,6 +17,8 @@ import com.ruoyi.common.utils.file.FileUtils;
|
|||||||
import com.ruoyi.middleware.minio.config.MinioConfig;
|
import com.ruoyi.middleware.minio.config.MinioConfig;
|
||||||
import com.ruoyi.middleware.minio.domain.MinioFileVO;
|
import com.ruoyi.middleware.minio.domain.MinioFileVO;
|
||||||
|
|
||||||
|
import static com.ruoyi.common.utils.file.FileUtils.getPathFileName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Minio文件操作实现类
|
* Minio文件操作实现类
|
||||||
*/
|
*/
|
||||||
@ -32,6 +36,7 @@ public class MinioFileService implements FileService {
|
|||||||
} else {
|
} else {
|
||||||
relativePath = filePath;
|
relativePath = filePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
return MinioUtil.uploadFile(minioConfig.getMasterClient().getDefaultBuket(), relativePath, file);
|
return MinioUtil.uploadFile(minioConfig.getMasterClient().getDefaultBuket(), relativePath, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,6 +68,7 @@ public class MinioFileService implements FileService {
|
|||||||
public boolean deleteFile(String fileUrl) throws Exception {
|
public boolean deleteFile(String fileUrl) throws Exception {
|
||||||
String filePath = StringUtils.substringAfter(fileUrl, "?fileName=");
|
String filePath = StringUtils.substringAfter(fileUrl, "?fileName=");
|
||||||
MinioUtil.removeFile(minioConfig.getMasterClient().getDefaultBuket(), filePath);
|
MinioUtil.removeFile(minioConfig.getMasterClient().getDefaultBuket(), filePath);
|
||||||
|
FileOperateUtils.deleteFileAndMd5ByFilePath(filePath);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user