正在显示
11 个修改的文件
包含
215 行增加
和
24 行删除
| @@ -9,6 +9,7 @@ user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分 | @@ -9,6 +9,7 @@ user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分 | ||
| 9 | user.password.delete=对不起,您的账号已被删除 | 9 | user.password.delete=对不起,您的账号已被删除 |
| 10 | user.blocked=用户已封禁,请联系管理员 | 10 | user.blocked=用户已封禁,请联系管理员 |
| 11 | role.blocked=角色已封禁,请联系管理员 | 11 | role.blocked=角色已封禁,请联系管理员 |
| 12 | +login.blocked=很遗憾,访问IP已被列入系统黑名单 | ||
| 12 | user.logout.success=退出成功 | 13 | user.logout.success=退出成功 |
| 13 | 14 | ||
| 14 | length.not.valid=长度必须在{min}到{max}个字符之间 | 15 | length.not.valid=长度必须在{min}到{max}个字符之间 |
| 1 | +package com.ruoyi.common.exception.user; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 黑名单IP异常类 | ||
| 5 | + * | ||
| 6 | + * @author ruoyi | ||
| 7 | + */ | ||
| 8 | +public class BlackListException extends UserException | ||
| 9 | +{ | ||
| 10 | + private static final long serialVersionUID = 1L; | ||
| 11 | + | ||
| 12 | + public BlackListException() | ||
| 13 | + { | ||
| 14 | + super("login.blocked", null); | ||
| 15 | + } | ||
| 16 | +} |
| 1 | +package com.ruoyi.common.exception.user; | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 用户不存在异常类 | ||
| 5 | + * | ||
| 6 | + * @author ruoyi | ||
| 7 | + */ | ||
| 8 | +public class UserNotExistsException extends UserException | ||
| 9 | +{ | ||
| 10 | + private static final long serialVersionUID = 1L; | ||
| 11 | + | ||
| 12 | + public UserNotExistsException() | ||
| 13 | + { | ||
| 14 | + super("user.not.exists", null); | ||
| 15 | + } | ||
| 16 | +} |
| @@ -3,6 +3,7 @@ package com.ruoyi.common.utils.ip; | @@ -3,6 +3,7 @@ package com.ruoyi.common.utils.ip; | ||
| 3 | import java.net.InetAddress; | 3 | import java.net.InetAddress; |
| 4 | import java.net.UnknownHostException; | 4 | import java.net.UnknownHostException; |
| 5 | import javax.servlet.http.HttpServletRequest; | 5 | import javax.servlet.http.HttpServletRequest; |
| 6 | +import com.ruoyi.common.utils.ServletUtils; | ||
| 6 | import com.ruoyi.common.utils.StringUtils; | 7 | import com.ruoyi.common.utils.StringUtils; |
| 7 | 8 | ||
| 8 | /** | 9 | /** |
| @@ -12,6 +13,23 @@ import com.ruoyi.common.utils.StringUtils; | @@ -12,6 +13,23 @@ import com.ruoyi.common.utils.StringUtils; | ||
| 12 | */ | 13 | */ |
| 13 | public class IpUtils | 14 | public class IpUtils |
| 14 | { | 15 | { |
| 16 | + public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)"; | ||
| 17 | + // 匹配 ip | ||
| 18 | + public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")"; | ||
| 19 | + public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))"; | ||
| 20 | + // 匹配网段 | ||
| 21 | + public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")"; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 获取客户端IP | ||
| 25 | + * | ||
| 26 | + * @return IP地址 | ||
| 27 | + */ | ||
| 28 | + public static String getIpAddr() | ||
| 29 | + { | ||
| 30 | + return getIpAddr(ServletUtils.getRequest()); | ||
| 31 | + } | ||
| 32 | + | ||
| 15 | /** | 33 | /** |
| 16 | * 获取客户端IP | 34 | * 获取客户端IP |
| 17 | * | 35 | * |
| @@ -248,7 +266,7 @@ public class IpUtils | @@ -248,7 +266,7 @@ public class IpUtils | ||
| 248 | } | 266 | } |
| 249 | } | 267 | } |
| 250 | } | 268 | } |
| 251 | - return ip; | 269 | + return StringUtils.substring(ip, 0, 255); |
| 252 | } | 270 | } |
| 253 | 271 | ||
| 254 | /** | 272 | /** |
| @@ -261,4 +279,104 @@ public class IpUtils | @@ -261,4 +279,104 @@ public class IpUtils | ||
| 261 | { | 279 | { |
| 262 | return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); | 280 | return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString); |
| 263 | } | 281 | } |
| 282 | + | ||
| 283 | + /** | ||
| 284 | + * 是否为IP | ||
| 285 | + */ | ||
| 286 | + public static boolean isIP(String ip) | ||
| 287 | + { | ||
| 288 | + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP); | ||
| 289 | + } | ||
| 290 | + | ||
| 291 | + /** | ||
| 292 | + * 是否为IP,或 *为间隔的通配符地址 | ||
| 293 | + */ | ||
| 294 | + public static boolean isIpWildCard(String ip) | ||
| 295 | + { | ||
| 296 | + return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD); | ||
| 297 | + } | ||
| 298 | + | ||
| 299 | + /** | ||
| 300 | + * 检测参数是否在ip通配符里 | ||
| 301 | + */ | ||
| 302 | + public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip) | ||
| 303 | + { | ||
| 304 | + String[] s1 = ipWildCard.split("\\."); | ||
| 305 | + String[] s2 = ip.split("\\."); | ||
| 306 | + boolean isMatchedSeg = true; | ||
| 307 | + for (int i = 0; i < s1.length && !s1[i].equals("*"); i++) | ||
| 308 | + { | ||
| 309 | + if (!s1[i].equals(s2[i])) | ||
| 310 | + { | ||
| 311 | + isMatchedSeg = false; | ||
| 312 | + break; | ||
| 313 | + } | ||
| 314 | + } | ||
| 315 | + return isMatchedSeg; | ||
| 316 | + } | ||
| 317 | + | ||
| 318 | + /** | ||
| 319 | + * 是否为特定格式如:“10.10.10.1-10.10.10.99”的ip段字符串 | ||
| 320 | + */ | ||
| 321 | + public static boolean isIPSegment(String ipSeg) | ||
| 322 | + { | ||
| 323 | + return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG); | ||
| 324 | + } | ||
| 325 | + | ||
| 326 | + /** | ||
| 327 | + * 判断ip是否在指定网段中 | ||
| 328 | + */ | ||
| 329 | + public static boolean ipIsInNetNoCheck(String iparea, String ip) | ||
| 330 | + { | ||
| 331 | + int idx = iparea.indexOf('-'); | ||
| 332 | + String[] sips = iparea.substring(0, idx).split("\\."); | ||
| 333 | + String[] sipe = iparea.substring(idx + 1).split("\\."); | ||
| 334 | + String[] sipt = ip.split("\\."); | ||
| 335 | + long ips = 0L, ipe = 0L, ipt = 0L; | ||
| 336 | + for (int i = 0; i < 4; ++i) | ||
| 337 | + { | ||
| 338 | + ips = ips << 8 | Integer.parseInt(sips[i]); | ||
| 339 | + ipe = ipe << 8 | Integer.parseInt(sipe[i]); | ||
| 340 | + ipt = ipt << 8 | Integer.parseInt(sipt[i]); | ||
| 341 | + } | ||
| 342 | + if (ips > ipe) | ||
| 343 | + { | ||
| 344 | + long t = ips; | ||
| 345 | + ips = ipe; | ||
| 346 | + ipe = t; | ||
| 347 | + } | ||
| 348 | + return ips <= ipt && ipt <= ipe; | ||
| 349 | + } | ||
| 350 | + | ||
| 351 | + /** | ||
| 352 | + * 校验ip是否符合过滤串规则 | ||
| 353 | + * | ||
| 354 | + * @param filter 过滤IP列表,支持后缀'*'通配,支持网段如:`10.10.10.1-10.10.10.99` | ||
| 355 | + * @param ip 校验IP地址 | ||
| 356 | + * @return boolean 结果 | ||
| 357 | + */ | ||
| 358 | + public static boolean isMatchedIp(String filter, String ip) | ||
| 359 | + { | ||
| 360 | + if (StringUtils.isEmpty(filter) && StringUtils.isEmpty(ip)) | ||
| 361 | + { | ||
| 362 | + return false; | ||
| 363 | + } | ||
| 364 | + String[] ips = filter.split(";"); | ||
| 365 | + for (String iStr : ips) | ||
| 366 | + { | ||
| 367 | + if (isIP(iStr) && iStr.equals(ip)) | ||
| 368 | + { | ||
| 369 | + return true; | ||
| 370 | + } | ||
| 371 | + else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip)) | ||
| 372 | + { | ||
| 373 | + return true; | ||
| 374 | + } | ||
| 375 | + else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip)) | ||
| 376 | + { | ||
| 377 | + return true; | ||
| 378 | + } | ||
| 379 | + } | ||
| 380 | + return false; | ||
| 381 | + } | ||
| 264 | } | 382 | } |
| @@ -90,7 +90,7 @@ public class LogAspect | @@ -90,7 +90,7 @@ public class LogAspect | ||
| 90 | SysOperLog operLog = new SysOperLog(); | 90 | SysOperLog operLog = new SysOperLog(); |
| 91 | operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); | 91 | operLog.setStatus(BusinessStatus.SUCCESS.ordinal()); |
| 92 | // 请求的地址 | 92 | // 请求的地址 |
| 93 | - String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); | 93 | + String ip = IpUtils.getIpAddr(); |
| 94 | operLog.setOperIp(ip); | 94 | operLog.setOperIp(ip); |
| 95 | operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); | 95 | operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255)); |
| 96 | if (loginUser != null) | 96 | if (loginUser != null) |
| @@ -16,7 +16,6 @@ import org.springframework.stereotype.Component; | @@ -16,7 +16,6 @@ import org.springframework.stereotype.Component; | ||
| 16 | import com.ruoyi.common.annotation.RateLimiter; | 16 | import com.ruoyi.common.annotation.RateLimiter; |
| 17 | import com.ruoyi.common.enums.LimitType; | 17 | import com.ruoyi.common.enums.LimitType; |
| 18 | import com.ruoyi.common.exception.ServiceException; | 18 | import com.ruoyi.common.exception.ServiceException; |
| 19 | -import com.ruoyi.common.utils.ServletUtils; | ||
| 20 | import com.ruoyi.common.utils.StringUtils; | 19 | import com.ruoyi.common.utils.StringUtils; |
| 21 | import com.ruoyi.common.utils.ip.IpUtils; | 20 | import com.ruoyi.common.utils.ip.IpUtils; |
| 22 | 21 | ||
| @@ -79,7 +78,7 @@ public class RateLimiterAspect | @@ -79,7 +78,7 @@ public class RateLimiterAspect | ||
| 79 | StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); | 78 | StringBuffer stringBuffer = new StringBuffer(rateLimiter.key()); |
| 80 | if (rateLimiter.limitType() == LimitType.IP) | 79 | if (rateLimiter.limitType() == LimitType.IP) |
| 81 | { | 80 | { |
| 82 | - stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-"); | 81 | + stringBuffer.append(IpUtils.getIpAddr()).append("-"); |
| 83 | } | 82 | } |
| 84 | MethodSignature signature = (MethodSignature) point.getSignature(); | 83 | MethodSignature signature = (MethodSignature) point.getSignature(); |
| 85 | Method method = signature.getMethod(); | 84 | Method method = signature.getMethod(); |
| @@ -38,7 +38,7 @@ public class AsyncFactory | @@ -38,7 +38,7 @@ public class AsyncFactory | ||
| 38 | final Object... args) | 38 | final Object... args) |
| 39 | { | 39 | { |
| 40 | final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); | 40 | final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); |
| 41 | - final String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); | 41 | + final String ip = IpUtils.getIpAddr(); |
| 42 | return new TimerTask() | 42 | return new TimerTask() |
| 43 | { | 43 | { |
| 44 | @Override | 44 | @Override |
| @@ -9,16 +9,18 @@ import org.springframework.security.core.Authentication; | @@ -9,16 +9,18 @@ import org.springframework.security.core.Authentication; | ||
| 9 | import org.springframework.stereotype.Component; | 9 | import org.springframework.stereotype.Component; |
| 10 | import com.ruoyi.common.constant.CacheConstants; | 10 | import com.ruoyi.common.constant.CacheConstants; |
| 11 | import com.ruoyi.common.constant.Constants; | 11 | import com.ruoyi.common.constant.Constants; |
| 12 | +import com.ruoyi.common.constant.UserConstants; | ||
| 12 | import com.ruoyi.common.core.domain.entity.SysUser; | 13 | import com.ruoyi.common.core.domain.entity.SysUser; |
| 13 | import com.ruoyi.common.core.domain.model.LoginUser; | 14 | import com.ruoyi.common.core.domain.model.LoginUser; |
| 14 | import com.ruoyi.common.core.redis.RedisCache; | 15 | import com.ruoyi.common.core.redis.RedisCache; |
| 15 | import com.ruoyi.common.exception.ServiceException; | 16 | import com.ruoyi.common.exception.ServiceException; |
| 17 | +import com.ruoyi.common.exception.user.BlackListException; | ||
| 16 | import com.ruoyi.common.exception.user.CaptchaException; | 18 | import com.ruoyi.common.exception.user.CaptchaException; |
| 17 | import com.ruoyi.common.exception.user.CaptchaExpireException; | 19 | import com.ruoyi.common.exception.user.CaptchaExpireException; |
| 20 | +import com.ruoyi.common.exception.user.UserNotExistsException; | ||
| 18 | import com.ruoyi.common.exception.user.UserPasswordNotMatchException; | 21 | import com.ruoyi.common.exception.user.UserPasswordNotMatchException; |
| 19 | import com.ruoyi.common.utils.DateUtils; | 22 | import com.ruoyi.common.utils.DateUtils; |
| 20 | import com.ruoyi.common.utils.MessageUtils; | 23 | import com.ruoyi.common.utils.MessageUtils; |
| 21 | -import com.ruoyi.common.utils.ServletUtils; | ||
| 22 | import com.ruoyi.common.utils.StringUtils; | 24 | import com.ruoyi.common.utils.StringUtils; |
| 23 | import com.ruoyi.common.utils.ip.IpUtils; | 25 | import com.ruoyi.common.utils.ip.IpUtils; |
| 24 | import com.ruoyi.framework.manager.AsyncManager; | 26 | import com.ruoyi.framework.manager.AsyncManager; |
| @@ -61,12 +63,10 @@ public class SysLoginService | @@ -61,12 +63,10 @@ public class SysLoginService | ||
| 61 | */ | 63 | */ |
| 62 | public String login(String username, String password, String code, String uuid) | 64 | public String login(String username, String password, String code, String uuid) |
| 63 | { | 65 | { |
| 64 | - boolean captchaEnabled = configService.selectCaptchaEnabled(); | ||
| 65 | - // 验证码开关 | ||
| 66 | - if (captchaEnabled) | ||
| 67 | - { | ||
| 68 | - validateCaptcha(username, code, uuid); | ||
| 69 | - } | 66 | + // 验证码校验 |
| 67 | + validateCaptcha(username, code, uuid); | ||
| 68 | + // 登录前置校验 | ||
| 69 | + loginPreCheck(username, password); | ||
| 70 | // 用户验证 | 70 | // 用户验证 |
| 71 | Authentication authentication = null; | 71 | Authentication authentication = null; |
| 72 | try | 72 | try |
| @@ -110,18 +110,58 @@ public class SysLoginService | @@ -110,18 +110,58 @@ public class SysLoginService | ||
| 110 | */ | 110 | */ |
| 111 | public void validateCaptcha(String username, String code, String uuid) | 111 | public void validateCaptcha(String username, String code, String uuid) |
| 112 | { | 112 | { |
| 113 | - String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); | ||
| 114 | - String captcha = redisCache.getCacheObject(verifyKey); | ||
| 115 | - redisCache.deleteObject(verifyKey); | ||
| 116 | - if (captcha == null) | 113 | + boolean captchaEnabled = configService.selectCaptchaEnabled(); |
| 114 | + if (captchaEnabled) | ||
| 115 | + { | ||
| 116 | + String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, ""); | ||
| 117 | + String captcha = redisCache.getCacheObject(verifyKey); | ||
| 118 | + redisCache.deleteObject(verifyKey); | ||
| 119 | + if (captcha == null) | ||
| 120 | + { | ||
| 121 | + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); | ||
| 122 | + throw new CaptchaExpireException(); | ||
| 123 | + } | ||
| 124 | + if (!code.equalsIgnoreCase(captcha)) | ||
| 125 | + { | ||
| 126 | + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); | ||
| 127 | + throw new CaptchaException(); | ||
| 128 | + } | ||
| 129 | + } | ||
| 130 | + } | ||
| 131 | + | ||
| 132 | + /** | ||
| 133 | + * 登录前置校验 | ||
| 134 | + * @param username 用户名 | ||
| 135 | + * @param password 用户密码 | ||
| 136 | + */ | ||
| 137 | + public void loginPreCheck(String username, String password) | ||
| 138 | + { | ||
| 139 | + // 用户名或密码为空 错误 | ||
| 140 | + if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) | ||
| 141 | + { | ||
| 142 | + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null"))); | ||
| 143 | + throw new UserNotExistsException(); | ||
| 144 | + } | ||
| 145 | + // 密码如果不在指定范围内 错误 | ||
| 146 | + if (password.length() < UserConstants.PASSWORD_MIN_LENGTH | ||
| 147 | + || password.length() > UserConstants.PASSWORD_MAX_LENGTH) | ||
| 148 | + { | ||
| 149 | + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); | ||
| 150 | + throw new UserPasswordNotMatchException(); | ||
| 151 | + } | ||
| 152 | + // 用户名不在指定范围内 错误 | ||
| 153 | + if (username.length() < UserConstants.USERNAME_MIN_LENGTH | ||
| 154 | + || username.length() > UserConstants.USERNAME_MAX_LENGTH) | ||
| 117 | { | 155 | { |
| 118 | - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"))); | ||
| 119 | - throw new CaptchaExpireException(); | 156 | + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match"))); |
| 157 | + throw new UserPasswordNotMatchException(); | ||
| 120 | } | 158 | } |
| 121 | - if (!code.equalsIgnoreCase(captcha)) | 159 | + // IP黑名单校验 |
| 160 | + String blackStr = configService.selectConfigByKey("sys.login.blackIPList"); | ||
| 161 | + if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) | ||
| 122 | { | 162 | { |
| 123 | - AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error"))); | ||
| 124 | - throw new CaptchaException(); | 163 | + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked"))); |
| 164 | + throw new BlackListException(); | ||
| 125 | } | 165 | } |
| 126 | } | 166 | } |
| 127 | 167 | ||
| @@ -134,7 +174,7 @@ public class SysLoginService | @@ -134,7 +174,7 @@ public class SysLoginService | ||
| 134 | { | 174 | { |
| 135 | SysUser sysUser = new SysUser(); | 175 | SysUser sysUser = new SysUser(); |
| 136 | sysUser.setUserId(userId); | 176 | sysUser.setUserId(userId); |
| 137 | - sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest())); | 177 | + sysUser.setLoginIp(IpUtils.getIpAddr()); |
| 138 | sysUser.setLoginDate(DateUtils.getNowDate()); | 178 | sysUser.setLoginDate(DateUtils.getNowDate()); |
| 139 | userService.updateUserProfile(sysUser); | 179 | userService.updateUserProfile(sysUser); |
| 140 | } | 180 | } |
| @@ -156,7 +156,7 @@ public class TokenService | @@ -156,7 +156,7 @@ public class TokenService | ||
| 156 | public void setUserAgent(LoginUser loginUser) | 156 | public void setUserAgent(LoginUser loginUser) |
| 157 | { | 157 | { |
| 158 | UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); | 158 | UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); |
| 159 | - String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); | 159 | + String ip = IpUtils.getIpAddr(); |
| 160 | loginUser.setIpaddr(ip); | 160 | loginUser.setIpaddr(ip); |
| 161 | loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); | 161 | loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); |
| 162 | loginUser.setBrowser(userAgent.getBrowser().getName()); | 162 | loginUser.setBrowser(userAgent.getBrowser().getName()); |
| @@ -110,7 +110,7 @@ | @@ -110,7 +110,7 @@ | ||
| 110 | <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/> | 110 | <dict-tag :options="dict.type.sys_common_status" :value="scope.row.status"/> |
| 111 | </template> | 111 | </template> |
| 112 | </el-table-column> | 112 | </el-table-column> |
| 113 | - <el-table-column label="操作信息" align="center" prop="msg" /> | 113 | + <el-table-column label="操作信息" align="center" prop="msg" :show-overflow-tooltip="true" /> |
| 114 | <el-table-column label="登录日期" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> | 114 | <el-table-column label="登录日期" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> |
| 115 | <template slot-scope="scope"> | 115 | <template slot-scope="scope"> |
| 116 | <span>{{ parseTime(scope.row.loginTime) }}</span> | 116 | <span>{{ parseTime(scope.row.loginTime) }}</span> |
| @@ -545,6 +545,7 @@ insert into sys_config values(2, '用户管理-账号初始密码', 'sys | @@ -545,6 +545,7 @@ insert into sys_config values(2, '用户管理-账号初始密码', 'sys | ||
| 545 | insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark,浅色主题theme-light' ); | 545 | insert into sys_config values(3, '主框架页-侧边栏主题', 'sys.index.sideTheme', 'theme-dark', 'Y', 'admin', sysdate(), '', null, '深色主题theme-dark,浅色主题theme-light' ); |
| 546 | insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能(true开启,false关闭)'); | 546 | insert into sys_config values(4, '账号自助-验证码开关', 'sys.account.captchaEnabled', 'true', 'Y', 'admin', sysdate(), '', null, '是否开启验证码功能(true开启,false关闭)'); |
| 547 | insert into sys_config values(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)'); | 547 | insert into sys_config values(5, '账号自助-是否开启用户注册功能', 'sys.account.registerUser', 'false', 'Y', 'admin', sysdate(), '', null, '是否开启注册用户功能(true开启,false关闭)'); |
| 548 | +insert into sys_config values(6, '用户登录-黑名单列表', 'sys.login.blackIPList', '', 'Y', 'admin', sysdate(), '', null, '设置登录IP黑名单限制,多个匹配项以;分隔,支持匹配(*通配、网段)'); | ||
| 548 | 549 | ||
| 549 | 550 | ||
| 550 | -- ---------------------------- | 551 | -- ---------------------------- |
-
请 注册 或 登录 后发表评论