fix(ruoyi3.8.9): 后端代码同步

This commit is contained in:
zhuangpeng.li
2025-04-27 11:21:09 +08:00
parent f545198645
commit 5b6ec185c4
47 changed files with 685 additions and 309 deletions

View File

@@ -7,6 +7,7 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.TreeSet;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -87,7 +88,7 @@ public class CacheController
public AjaxResult getCacheKeys(@PathVariable String cacheName)
{
Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
return AjaxResult.success(cacheKeys);
return AjaxResult.success(new TreeSet<>(cacheKeys));
}
@ApiOperation("缓存内容")

View File

@@ -53,26 +53,17 @@ public class SysUserOnlineController extends BaseController
{
LoginUser user = redisCache.getCacheObject(key);
if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
{
if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
{
userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
}
}
else if (StringUtils.isNotEmpty(ipaddr))
{
if (StringUtils.equals(ipaddr, user.getIpaddr()))
{
userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
}
}
else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
{
if (StringUtils.equals(userName, user.getUsername()))
{
userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
}
}
else
{
userOnlineList.add(userOnlineService.loginUserToUserOnline(user));

View File

@@ -93,7 +93,7 @@ public class SysConfigController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysConfig config)
{
if (configService.checkConfigKeyUnique(config))
if (!configService.checkConfigKeyUnique(config))
{
return error("新增参数'" + config.getConfigName() + "'失败,参数键名已存在");
}
@@ -110,7 +110,7 @@ public class SysConfigController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysConfig config)
{
if (configService.checkConfigKeyUnique(config))
if (!configService.checkConfigKeyUnique(config))
{
return error("修改参数'" + config.getConfigName() + "'失败,参数键名已存在");
}

View File

@@ -84,7 +84,7 @@ public class SysDeptController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDept dept)
{
if (deptService.checkDeptNameUnique(dept))
if (!deptService.checkDeptNameUnique(dept))
{
return error("新增部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}
@@ -103,7 +103,7 @@ public class SysDeptController extends BaseController
{
Long deptId = dept.getDeptId();
deptService.checkDeptDataScope(deptId);
if (deptService.checkDeptNameUnique(dept))
if (!deptService.checkDeptNameUnique(dept))
{
return error("修改部门'" + dept.getDeptName() + "'失败,部门名称已存在");
}

View File

@@ -80,7 +80,7 @@ public class SysDictTypeController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysDictType dict)
{
if (dictTypeService.checkDictTypeUnique(dict))
if (!dictTypeService.checkDictTypeUnique(dict))
{
return error("新增字典'" + dict.getDictName() + "'失败,字典类型已存在");
}
@@ -97,7 +97,7 @@ public class SysDictTypeController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysDictType dict)
{
if (dictTypeService.checkDictTypeUnique(dict))
if (!dictTypeService.checkDictTypeUnique(dict))
{
return error("修改字典'" + dict.getDictName() + "'失败,字典类型已存在");
}

View File

@@ -94,7 +94,7 @@ public class SysMenuController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysMenu menu)
{
if (menuService.checkMenuNameUnique(menu))
if (!menuService.checkMenuNameUnique(menu))
{
return error("新增菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}
@@ -115,7 +115,7 @@ public class SysMenuController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysMenu menu)
{
if (menuService.checkMenuNameUnique(menu))
if (!menuService.checkMenuNameUnique(menu))
{
return error("修改菜单'" + menu.getMenuName() + "'失败,菜单名称已存在");
}

View File

@@ -83,11 +83,11 @@ public class SysPostController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysPost post)
{
if (postService.checkPostNameUnique(post))
if (!postService.checkPostNameUnique(post))
{
return error("新增岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (postService.checkPostCodeUnique(post))
else if (!postService.checkPostCodeUnique(post))
{
return error("新增岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}
@@ -104,11 +104,11 @@ public class SysPostController extends BaseController
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysPost post)
{
if (postService.checkPostNameUnique(post))
if (!postService.checkPostNameUnique(post))
{
return error("修改岗位'" + post.getPostName() + "'失败,岗位名称已存在");
}
else if (postService.checkPostCodeUnique(post))
else if (!postService.checkPostCodeUnique(post))
{
return error("修改岗位'" + post.getPostName() + "'失败,岗位编码已存在");
}

View File

@@ -30,6 +30,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
import java.util.Map;
/**
* 个人信息 业务处理
@@ -78,29 +79,22 @@ public class SysProfileController extends BaseController
public AjaxResult updateProfile(@RequestBody SysUser user)
{
LoginUser loginUser = getLoginUser();
SysUser sysUser = loginUser.getUser();
user.setUserName(sysUser.getUserName());
if (StringUtils.isNotEmpty(user.getPhonenumber())
&& userService.checkPhoneUnique(user))
SysUser currentUser = loginUser.getUser();
currentUser.setNickName(user.getNickName());
currentUser.setEmail(user.getEmail());
currentUser.setPhonenumber(user.getPhonenumber());
currentUser.setSex(user.getSex());
if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
{
return error("修改用户'" + user.getUserName() + "'失败,手机号码已存在");
}
if (StringUtils.isNotEmpty(user.getEmail())
&& userService.checkEmailUnique(user))
if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
{
return error("修改用户'" + user.getUserName() + "'失败,邮箱账号已存在");
return error("修改用户'" + loginUser.getUsername() + "'失败,邮箱账号已存在");
}
user.setUserId(sysUser.getUserId());
user.setPassword(null);
user.setAvatar(null);
user.setDeptId(null);
if (userService.updateUserProfile(user) > 0)
if (userService.updateUserProfile(currentUser) > 0)
{
// 更新缓存用户信息
sysUser.setNickName(user.getNickName());
sysUser.setPhonenumber(user.getPhonenumber());
sysUser.setEmail(user.getEmail());
sysUser.setSex(user.getSex());
tokenService.setLoginUser(loginUser);
return success();
}
@@ -113,8 +107,10 @@ public class SysProfileController extends BaseController
@ApiOperation("重置密码")
@Log(title = "个人信息", businessType = BusinessType.UPDATE)
@PutMapping("/updatePwd")
public AjaxResult updatePwd(String oldPassword, String newPassword)
public AjaxResult updatePwd(@RequestBody Map<String, String> params)
{
String oldPassword = params.get("oldPassword");
String newPassword = params.get("newPassword");
LoginUser loginUser = getLoginUser();
String userName = loginUser.getUsername();
String password = loginUser.getPassword();
@@ -126,10 +122,11 @@ public class SysProfileController extends BaseController
{
return error("新密码不能与旧密码相同");
}
if (userService.resetUserPwd(userName, SecurityUtils.encryptPassword(newPassword)) > 0)
newPassword = SecurityUtils.encryptPassword(newPassword);
if (userService.resetUserPwd(userName, newPassword) > 0)
{
// 更新缓存用户密码
loginUser.getUser().setPassword(SecurityUtils.encryptPassword(newPassword));
loginUser.getUser().setPassword(newPassword);
tokenService.setLoginUser(loginUser);
return success();
}

View File

@@ -102,11 +102,11 @@ public class SysRoleController extends BaseController
@PostMapping
public AjaxResult add(@Validated @RequestBody SysRole role)
{
if (roleService.checkRoleNameUnique(role))
if (!roleService.checkRoleNameUnique(role))
{
return error("新增角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (roleService.checkRoleKeyUnique(role))
else if (!roleService.checkRoleKeyUnique(role))
{
return error("新增角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
@@ -126,11 +126,11 @@ public class SysRoleController extends BaseController
{
roleService.checkRoleAllowed(role);
roleService.checkRoleDataScope(role.getRoleId());
if (roleService.checkRoleNameUnique(role))
if (!roleService.checkRoleNameUnique(role))
{
return error("修改角色'" + role.getRoleName() + "'失败,角色名称已存在");
}
else if (roleService.checkRoleKeyUnique(role))
else if (!roleService.checkRoleKeyUnique(role))
{
return error("修改角色'" + role.getRoleName() + "'失败,角色权限已存在");
}
@@ -142,8 +142,8 @@ public class SysRoleController extends BaseController
LoginUser loginUser = getLoginUser();
if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
{
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
tokenService.setLoginUser(loginUser);
}
return success();

View File

@@ -9,6 +9,7 @@ user.password.retry.limit.exceed=密码输入错误{0}次,帐户锁定{1}分
user.password.delete=对不起,您的账号已被删除
user.blocked=用户已封禁,请联系管理员
role.blocked=角色已封禁,请联系管理员
login.blocked=很遗憾访问IP已被列入系统黑名单
user.logout.success=退出成功
length.not.valid=长度必须在{min}到{max}个字符之间

View File

@@ -0,0 +1,24 @@
package com.fastbee.common.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fastbee.common.config.serializer.SensitiveJsonSerializer;
import com.fastbee.common.enums.DesensitizedType;
/**
* 数据脱敏注解
*
* @author ruoyi
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
@JacksonAnnotationsInside
@JsonSerialize(using = SensitiveJsonSerializer.class)
public @interface Sensitive
{
DesensitizedType desensitizedType();
}

View File

@@ -0,0 +1,67 @@
package com.fastbee.common.config.serializer;
import java.io.IOException;
import java.util.Objects;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fastbee.common.annotation.Sensitive;
import com.fastbee.common.core.domain.model.LoginUser;
import com.fastbee.common.enums.DesensitizedType;
import com.fastbee.common.utils.SecurityUtils;
/**
* 数据脱敏序列化过滤
*
* @author ruoyi
*/
public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
{
private DesensitizedType desensitizedType;
@Override
public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
{
if (desensitization())
{
gen.writeString(desensitizedType.desensitizer().apply(value));
}
else
{
gen.writeString(value);
}
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
throws JsonMappingException
{
Sensitive annotation = property.getAnnotation(Sensitive.class);
if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
{
this.desensitizedType = annotation.desensitizedType();
return this;
}
return prov.findValueSerializer(property.getType(), property);
}
/**
* 是否需要脱敏处理
*/
private boolean desensitization()
{
try
{
LoginUser securityUser = SecurityUtils.getLoginUser();
// 管理员不脱敏
return !securityUser.getUser().isAdmin();
}
catch (Exception e)
{
return true;
}
}
}

View File

@@ -21,6 +21,9 @@ public class UserConstants
/** 用户封禁状态 */
public static final String USER_DISABLE = "1";
/** 角色正常状态 */
public static final String ROLE_NORMAL = "0";
/** 角色封禁状态 */
public static final String ROLE_DISABLE = "1";

View File

@@ -1,6 +1,7 @@
package com.fastbee.common.core.domain;
import java.util.HashMap;
import java.util.Objects;
import com.fastbee.common.constant.HttpStatus;
import com.fastbee.common.utils.StringUtils;
@@ -198,6 +199,36 @@ public class AjaxResult extends HashMap<String, Object>
return new AjaxResult(code, msg, null);
}
/**
* 是否为成功消息
*
* @return 结果
*/
public boolean isSuccess()
{
return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
}
/**
* 是否为警告消息
*
* @return 结果
*/
public boolean isWarn()
{
return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
}
/**
* 是否为错误消息
*
* @return 结果
*/
public boolean isError()
{
return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
}
/**
* 方便链式调用
*

View File

@@ -54,6 +54,9 @@ public class SysMenu extends BaseEntity
@ApiModelProperty("路由参数")
private String query;
/** 路由名称默认和路由地址相同的驼峰格式注意因为vue3版本的router会删除名称相同路由为避免名字的冲突特殊情况可以自定义 */
private String routeName;
/** 是否为外链0是 1否 */
@ApiModelProperty("是否为外链0是 1否")
private String isFrame;
@@ -171,6 +174,16 @@ public class SysMenu extends BaseEntity
this.query = query;
}
public String getRouteName()
{
return routeName;
}
public void setRouteName(String routeName)
{
this.routeName = routeName;
}
public String getIsFrame()
{
return isFrame;
@@ -262,6 +275,8 @@ public class SysMenu extends BaseEntity
.append("orderNum", getOrderNum())
.append("path", getPath())
.append("component", getComponent())
.append("query", getQuery())
.append("routeName", getRouteName())
.append("isFrame", getIsFrame())
.append("IsCache", getIsCache())
.append("menuType", getMenuType())

View File

@@ -27,7 +27,7 @@ public class SysUser extends BaseEntity
/** 用户ID */
@ApiModelProperty("用户ID")
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
@Excel(name = "用户序号", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "用户编号")
private Long userId;
/** 部门ID */
@@ -52,7 +52,7 @@ public class SysUser extends BaseEntity
/** 手机号码 */
@ApiModelProperty("手机号码")
@Excel(name = "手机号码")
@Excel(name = "手机号码", cellType = ColumnType.TEXT)
private String phonenumber;
/** 用户性别 */

View File

@@ -13,8 +13,7 @@ import java.util.Set;
*
* @author ruoyi
*/
public class LoginUser implements UserDetails
{
public class LoginUser implements UserDetails {
private static final long serialVersionUID = 1L;
/**
@@ -81,6 +80,29 @@ public class LoginUser implements UserDetails
private Boolean neverExpire = Boolean.FALSE;
public LoginUser() {
}
public LoginUser(SysUser user, Set<String> permissions) {
this.user = user;
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions) {
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, String language, SysUser user, Set<String> permissions) {
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.language = language;
this.permissions = permissions;
}
public Boolean getNeverExpire() {
return neverExpire;
}
@@ -105,33 +127,27 @@ public class LoginUser implements UserDetails
this.language = language;
}
public Long getUserId()
{
public Long getUserId() {
return userId;
}
public void setUserId(Long userId)
{
public void setUserId(Long userId) {
this.userId = userId;
}
public Long getDeptId()
{
public Long getDeptId() {
return deptId;
}
public void setDeptId(Long deptId)
{
public void setDeptId(Long deptId) {
this.deptId = deptId;
}
public String getToken()
{
public String getToken() {
return token;
}
public void setToken(String token)
{
public void setToken(String token) {
this.token = token;
}
@@ -143,43 +159,15 @@ public class LoginUser implements UserDetails
this.requestToken = requestToken;
}
public LoginUser()
{
}
public LoginUser(SysUser user, Set<String> permissions)
{
this.user = user;
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
{
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.permissions = permissions;
}
public LoginUser(Long userId, Long deptId, String language, SysUser user, Set<String> permissions)
{
this.userId = userId;
this.deptId = deptId;
this.user = user;
this.language = language;
this.permissions = permissions;
}
@JSONField(serialize = false)
@Override
public String getPassword()
{
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername()
{
public String getUsername() {
return user.getUserName();
}
@@ -188,8 +176,7 @@ public class LoginUser implements UserDetails
*/
@JSONField(serialize = false)
@Override
public boolean isAccountNonExpired()
{
public boolean isAccountNonExpired() {
return true;
}
@@ -200,8 +187,7 @@ public class LoginUser implements UserDetails
*/
@JSONField(serialize = false)
@Override
public boolean isAccountNonLocked()
{
public boolean isAccountNonLocked() {
return true;
}
@@ -212,8 +198,7 @@ public class LoginUser implements UserDetails
*/
@JSONField(serialize = false)
@Override
public boolean isCredentialsNonExpired()
{
public boolean isCredentialsNonExpired() {
return true;
}
@@ -224,94 +209,76 @@ public class LoginUser implements UserDetails
*/
@JSONField(serialize = false)
@Override
public boolean isEnabled()
{
public boolean isEnabled() {
return true;
}
public Long getLoginTime()
{
public Long getLoginTime() {
return loginTime;
}
public void setLoginTime(Long loginTime)
{
public void setLoginTime(Long loginTime) {
this.loginTime = loginTime;
}
public String getIpaddr()
{
public String getIpaddr() {
return ipaddr;
}
public void setIpaddr(String ipaddr)
{
public void setIpaddr(String ipaddr) {
this.ipaddr = ipaddr;
}
public String getLoginLocation()
{
public String getLoginLocation() {
return loginLocation;
}
public void setLoginLocation(String loginLocation)
{
public void setLoginLocation(String loginLocation) {
this.loginLocation = loginLocation;
}
public String getBrowser()
{
public String getBrowser() {
return browser;
}
public void setBrowser(String browser)
{
public void setBrowser(String browser) {
this.browser = browser;
}
public String getOs()
{
public String getOs() {
return os;
}
public void setOs(String os)
{
public void setOs(String os) {
this.os = os;
}
public Long getExpireTime()
{
public Long getExpireTime() {
return expireTime;
}
public void setExpireTime(Long expireTime)
{
public void setExpireTime(Long expireTime) {
this.expireTime = expireTime;
}
public Set<String> getPermissions()
{
public Set<String> getPermissions() {
return permissions;
}
public void setPermissions(Set<String> permissions)
{
public void setPermissions(Set<String> permissions) {
this.permissions = permissions;
}
public SysUser getUser()
{
public SysUser getUser() {
return user;
}
public void setUser(SysUser user)
{
public void setUser(SysUser user) {
this.user = user;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities()
{
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
}

View File

@@ -0,0 +1,61 @@
package com.fastbee.common.exception.file;
import java.io.PrintStream;
import java.io.PrintWriter;
/**
* 文件上传异常类
*
* @author ruoyi
*/
public class FileUploadException extends Exception
{
private static final long serialVersionUID = 1L;
private final Throwable cause;
public FileUploadException()
{
this(null, null);
}
public FileUploadException(final String msg)
{
this(msg, null);
}
public FileUploadException(String msg, Throwable cause)
{
super(msg);
this.cause = cause;
}
@Override
public void printStackTrace(PrintStream stream)
{
super.printStackTrace(stream);
if (cause != null)
{
stream.println("Caused by:");
cause.printStackTrace(stream);
}
}
@Override
public void printStackTrace(PrintWriter writer)
{
super.printStackTrace(writer);
if (cause != null)
{
writer.println("Caused by:");
cause.printStackTrace(writer);
}
}
@Override
public Throwable getCause()
{
return cause;
}
}

View File

@@ -0,0 +1,16 @@
package com.fastbee.common.exception.user;
/**
* 黑名单IP异常类
*
* @author ruoyi
*/
public class BlackListException extends UserException
{
private static final long serialVersionUID = 1L;
public BlackListException()
{
super("login.blocked", null);
}
}

View File

@@ -0,0 +1,16 @@
package com.fastbee.common.exception.user;
/**
* 用户不存在异常类
*
* @author ruoyi
*/
public class UserNotExistsException extends UserException
{
private static final long serialVersionUID = 1L;
public UserNotExistsException()
{
super("user.not.exists", null);
}
}

View File

@@ -32,10 +32,10 @@ public class XssFilter implements Filter
String tempExcludes = filterConfig.getInitParameter("excludes");
if (StringUtils.isNotEmpty(tempExcludes))
{
String[] url = tempExcludes.split(",");
for (int i = 0; url != null && i < url.length; i++)
String[] urls = tempExcludes.split(",");
for (String url : urls)
{
excludes.add(url[i]);
excludes.add(url);
}
}
}

View File

@@ -108,7 +108,6 @@ public class Arith
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = BigDecimal.ONE;
return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
return b.divide(BigDecimal.ONE, scale, RoundingMode.HALF_UP).doubleValue();
}
}

View File

@@ -379,6 +379,18 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @return list集合
*/
public static final List<String> str2List(String str, String sep)
{
return str2List(str, sep, true, false);
}
/**
* 字符串转list
*

View File

@@ -21,6 +21,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fastbee.common.constant.Constants;
import com.fastbee.common.utils.StringUtils;
import org.springframework.http.MediaType;
/**
* 通用http发送方法
@@ -74,7 +75,7 @@ public class HttpUtils
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
@@ -121,10 +122,23 @@ public class HttpUtils
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 JSON String格式 的形式。
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
{
return sendPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数
* @param contentType 内容类型
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param, String contentType)
{
PrintWriter out = null;
BufferedReader in = null;
@@ -136,9 +150,9 @@ public class HttpUtils
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setRequestProperty("Content-Type", contentType);
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
@@ -190,6 +204,11 @@ public class HttpUtils
}
public static String sendSSLPost(String url, String param)
{
return sendSSLPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
}
public static String sendSSLPost(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
@@ -202,9 +221,9 @@ public class HttpUtils
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("contentType", "utf-8");
conn.setRequestProperty("Content-Type", contentType);
conn.setDoOutput(true);
conn.setDoInput(true);

View File

@@ -51,6 +51,8 @@ public class ExcelUtil<T>
{
private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
public static final String SEPARATOR = ",";
public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
@@ -316,7 +318,7 @@ public class ExcelUtil<T>
throw new IOException("文件sheet不存在");
}
boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
Map<String, PictureData> pictures;
Map<String, List<PictureData>> pictures = null;
if (isXSSFWorkbook)
{
pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
@@ -460,16 +462,15 @@ public class ExcelUtil<T>
}
else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
{
PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
if (image == null)
StringBuilder propertyString = new StringBuilder();
List<PictureData> images = pictures.get(row.getRowNum() + "_" + entry.getKey());
for (PictureData picture : images)
{
val = "";
}
else
{
byte[] data = image.getData();
val = FileUtils.writeImportBytes(data);
byte[] data = picture.getData();
String fileName = FileUtils.writeImportBytes(data);
propertyString.append(fileName).append(SEPARATOR);
}
val = StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
}
ReflectUtils.invokeSetter(entity, propertyName, val);
}
@@ -993,12 +994,15 @@ public class ExcelUtil<T>
else if (ColumnType.IMAGE == attr.cellType())
{
ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
String imagePath = Convert.toStr(value);
if (StringUtils.isNotEmpty(imagePath))
String propertyValue = Convert.toStr(value);
if (StringUtils.isNotEmpty(propertyValue))
{
List<String> imagePaths = StringUtils.str2List(propertyValue, SEPARATOR);
for (String imagePath : imagePaths)
{
byte[] data = ImageUtils.getImage(imagePath);
getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
getDrawingPatriarch(cell.getSheet()).createPicture(anchor, cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
}
}
}
}
@@ -1243,7 +1247,7 @@ public class ExcelUtil<T>
public static String convertByExp(String propertyValue, String converterExp, String separator)
{
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
String[] convertSource = converterExp.split(SEPARATOR);
for (String item : convertSource)
{
String[] itemArray = item.split("=");
@@ -1280,7 +1284,7 @@ public class ExcelUtil<T>
public static String reverseByExp(String propertyValue, String converterExp, String separator)
{
StringBuilder propertyString = new StringBuilder();
String[] convertSource = converterExp.split(",");
String[] convertSource = converterExp.split(SEPARATOR);
for (String item : convertSource)
{
String[] itemArray = item.split("=");
@@ -1706,31 +1710,25 @@ public class ExcelUtil<T>
* @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
public static Map<String, List<PictureData>> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
Map<String, List<PictureData>> sheetIndexPicMap = new HashMap<>();
List<HSSFPictureData> pictures = workbook.getAllPictures();
if (!pictures.isEmpty())
if (!pictures.isEmpty() && sheet.getDrawingPatriarch() != null)
{
for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
{
HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
if (shape instanceof HSSFPicture)
{
HSSFPicture pic = (HSSFPicture) shape;
int pictureIndex = pic.getPictureIndex() - 1;
HSSFPictureData picData = pictures.get(pictureIndex);
HSSFClientAnchor anchor = (HSSFClientAnchor) pic.getAnchor();
String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
sheetIndexPicMap.put(picIndex, picData);
sheetIndexPicMap.computeIfAbsent(picIndex, k -> new ArrayList<>()).add(pic.getPictureData());
}
}
}
return sheetIndexPicMap;
}
else
{
return sheetIndexPicMap;
}
}
/**
* 获取Excel2007图片
@@ -1739,16 +1737,15 @@ public class ExcelUtil<T>
* @param workbook 工作簿对象
* @return Map key:图片单元格索引1_1Stringvalue:图片流PictureData
*/
public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
public static Map<String, List<PictureData>> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
{
Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
Map<String, List<PictureData>> sheetIndexPicMap = new HashMap<>();
for (POIXMLDocumentPart dr : sheet.getRelations())
{
if (dr instanceof XSSFDrawing)
{
XSSFDrawing drawing = (XSSFDrawing) dr;
List<XSSFShape> shapes = drawing.getShapes();
for (XSSFShape shape : shapes)
for (XSSFShape shape : drawing.getShapes())
{
if (shape instanceof XSSFPicture)
{
@@ -1756,7 +1753,7 @@ public class ExcelUtil<T>
XSSFClientAnchor anchor = pic.getPreferredSize();
CTMarker ctMarker = anchor.getFrom();
String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
sheetIndexPicMap.put(picIndex, pic.getPictureData());
sheetIndexPicMap.computeIfAbsent(picIndex, k -> new ArrayList<>()).add(pic.getPictureData());
}
}
}

View File

@@ -1,5 +1,6 @@
package com.fastbee.common.utils.spring;
import org.springframework.aop.framework.Advised;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
@@ -126,7 +127,12 @@ public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationC
@SuppressWarnings("unchecked")
public static <T> T getAopProxy(T invoker)
{
return (T) AopContext.currentProxy();
Object proxy = AopContext.currentProxy();
if (((Advised) proxy).getTargetSource().getTargetClass() == invoker.getClass())
{
return (T) proxy;
}
return invoker;
}
/**

View File

@@ -22,7 +22,7 @@ public class Seq
private static AtomicInteger uploadSeq = new AtomicInteger(1);
// 机器标识
private static String machineCode = "A";
private static final String machineCode = "A";
/**
* 获取通用序列号

View File

@@ -27,8 +27,13 @@ public class XssValidator implements ConstraintValidator<Xss, String>
public static boolean containsHtml(String value)
{
StringBuilder sHtml = new StringBuilder();
Pattern pattern = Pattern.compile(HTML_PATTERN);
Matcher matcher = pattern.matcher(value);
return matcher.matches();
while (matcher.find())
{
sHtml.append(matcher.group());
}
return pattern.matcher(sHtml).matches();
}
}

View File

@@ -7,6 +7,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
import com.fastbee.common.annotation.DataScope;
import com.fastbee.common.constant.UserConstants;
import com.fastbee.common.core.domain.BaseEntity;
import com.fastbee.common.core.domain.entity.SysRole;
import com.fastbee.common.core.domain.entity.SysUser;
@@ -73,8 +74,7 @@ public class DataScopeAspect
if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
{
String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(),
controllerDataScope.userAlias(), permission);
dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
}
}
}
@@ -92,29 +92,42 @@ public class DataScopeAspect
{
StringBuilder sqlString = new StringBuilder();
List<String> conditions = new ArrayList<String>();
List<String> scopeCustomIds = new ArrayList<String>();
user.getRoles().forEach(role -> {
if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
scopeCustomIds.add(Convert.toStr(role.getRoleId()));
}
});
for (SysRole role : user.getRoles())
{
String dataScope = role.getDataScope();
if (!DATA_SCOPE_CUSTOM.equals(dataScope) && conditions.contains(dataScope))
if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
{
continue;
}
if (StringUtils.isNotEmpty(permission) && StringUtils.isNotEmpty(role.getPermissions())
&& !StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
{
continue;
}
if (DATA_SCOPE_ALL.equals(dataScope))
{
sqlString = new StringBuilder();
conditions.add(dataScope);
break;
}
else if (DATA_SCOPE_CUSTOM.equals(dataScope))
{
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias,
role.getRoleId()));
if (scopeCustomIds.size() > 1)
{
// 多个自定数据权限使用in查询避免多次拼接。
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
}
else
{
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
}
}
else if (DATA_SCOPE_DEPT.equals(dataScope))
{
@@ -122,9 +135,7 @@ public class DataScopeAspect
}
else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
{
sqlString.append(StringUtils.format(
" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )",
deptAlias, user.getDeptId(), user.getDeptId()));
sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
}
else if (DATA_SCOPE_SELF.equals(dataScope))
{
@@ -141,6 +152,12 @@ public class DataScopeAspect
conditions.add(dataScope);
}
// 角色都不包含传递过来的权限字符这个时候sqlString也会为空所以要限制一下,不查询任何数据
if (StringUtils.isEmpty(conditions))
{
sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
}
if (StringUtils.isNotBlank(sqlString.toString()))
{
Object params = joinPoint.getArgs()[0];

View File

@@ -79,7 +79,7 @@ public class RateLimiterAspect
StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
if (rateLimiter.limitType() == LimitType.IP)
{
stringBuffer.append(IpUtils.getIpAddr(ServletUtils.getRequest())).append("-");
stringBuffer.append(IpUtils.getIpAddr()).append("-");
}
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();

View File

@@ -0,0 +1,43 @@
package com.fastbee.framework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
import org.springframework.web.servlet.i18n.SessionLocaleResolver;
import com.fastbee.common.constant.Constants;
/**
* 资源文件配置加载
*
* @author ruoyi
*/
@Configuration
public class I18nConfig implements WebMvcConfigurer
{
@Bean
public LocaleResolver localeResolver()
{
SessionLocaleResolver slr = new SessionLocaleResolver();
// 默认语言
slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
return slr;
}
@Bean
public LocaleChangeInterceptor localeChangeInterceptor()
{
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
// 参数名
lci.setParamName("lang");
return lci;
}
@Override
public void addInterceptors(InterceptorRegistry registry)
{
registry.addInterceptor(localeChangeInterceptor());
}
}

View File

@@ -1,6 +1,7 @@
package com.fastbee.framework.config;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
@@ -14,6 +15,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
* @author ruoyi
*/
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport
{
@Bean

View File

@@ -36,7 +36,7 @@ public class ResourcesConfig implements WebMvcConfigurer
/** swagger配置 */
registry.addResourceHandler("/swagger-ui/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());;
.setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
}
/**

View File

@@ -3,6 +3,7 @@ package com.fastbee.framework.config.properties;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import org.apache.commons.lang3.RegExUtils;
@@ -44,12 +45,12 @@ public class PermitAllUrlProperties implements InitializingBean, ApplicationCont
// 获取方法上边的注解 替代path variable 为 *
Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
Optional.ofNullable(method).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()
Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
// 获取类上边的注解, 替代path variable 为 *
Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
Optional.ofNullable(controller).ifPresent(anonymous -> info.getPatternsCondition().getPatterns()
Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
.forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
});
}

View File

@@ -47,8 +47,9 @@ public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
/**
* 验证是否重复提交由子类实现具体的防重复提交的规则
*
* @param request
* @return
* @param request 请求信息
* @param annotation 防重复注解参数
* @return 结果
* @throws Exception
*/
public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);

View File

@@ -38,7 +38,7 @@ public class AsyncFactory
final Object... args)
{
final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
final String ip = IpUtils.getIpAddr(ServletUtils.getRequest());
final String ip = IpUtils.getIpAddr();
return new TimerTask()
{
@Override

View File

@@ -4,6 +4,8 @@ import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.fastbee.common.utils.MessageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.Authentication;
@@ -45,8 +47,8 @@ public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
// 删除用户缓存记录
tokenService.delLoginUser(loginUser.getToken());
// 记录用户退出日志
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, "退出成功"));
AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
}
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success("退出成功")));
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success"))));
}
}

View File

@@ -7,13 +7,17 @@ import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import com.fastbee.common.constant.HttpStatus;
import com.fastbee.common.core.domain.AjaxResult;
import com.fastbee.common.core.text.Convert;
import com.fastbee.common.exception.DemoModeException;
import com.fastbee.common.exception.ServiceException;
import com.fastbee.common.utils.StringUtils;
import com.fastbee.common.utils.html.EscapeUtil;
/**
* 全局异常处理器
@@ -59,6 +63,33 @@ public class GlobalExceptionHandler
return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
}
/**
* 请求路径中缺少必需的路径变量
*/
@ExceptionHandler(MissingPathVariableException.class)
public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
log.error("请求路径中缺少必需的路径变量'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求路径中缺少必需的路径变量[%s]", e.getVariableName()));
}
/**
* 请求参数类型不匹配
*/
@ExceptionHandler(MethodArgumentTypeMismatchException.class)
public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
{
String requestURI = request.getRequestURI();
String value = Convert.toStr(e.getValue());
if (StringUtils.isNotEmpty(value))
{
value = EscapeUtil.clean(value);
}
log.error("请求参数类型不匹配'{}',发生系统异常.", requestURI, e);
return AjaxResult.error(String.format("请求参数类型不匹配,参数[%s]要求类型为:'%s',但输入值为:'%s'", e.getName(), e.getRequiredType().getName(), value));
}
/**
* 拦截未知的运行时异常
*/

View File

@@ -3,6 +3,7 @@ package com.fastbee.framework.web.service;
import java.util.Set;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import com.fastbee.common.constant.Constants;
import com.fastbee.common.core.domain.entity.SysRole;
import com.fastbee.common.core.domain.model.LoginUser;
import com.fastbee.common.utils.SecurityUtils;
@@ -17,16 +18,6 @@ import com.fastbee.framework.security.context.PermissionContextHolder;
@Service("ss")
public class PermissionService
{
/** 所有权限标识 */
private static final String ALL_PERMISSION = "*:*:*";
/** 管理员角色权限标识 */
private static final String SUPER_ADMIN = "admin";
private static final String ROLE_DELIMETER = ",";
private static final String PERMISSION_DELIMETER = ",";
/**
* 验证用户是否具备某权限
*
@@ -78,7 +69,7 @@ public class PermissionService
}
PermissionContextHolder.setContext(permissions);
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER))
for (String permission : permissions.split(Constants.PERMISSION_DELIMETER))
{
if (permission != null && hasPermissions(authorities, permission))
{
@@ -108,7 +99,7 @@ public class PermissionService
for (SysRole sysRole : loginUser.getUser().getRoles())
{
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
if (Constants.SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
{
return true;
}
@@ -144,7 +135,7 @@ public class PermissionService
{
return false;
}
for (String role : roles.split(ROLE_DELIMETER))
for (String role : roles.split(Constants.ROLE_DELIMETER))
{
if (hasRole(role))
{
@@ -163,6 +154,6 @@ public class PermissionService
*/
private boolean hasPermissions(Set<String> permissions, String permission)
{
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
return permissions.contains(Constants.ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}
}

View File

@@ -2,17 +2,15 @@ package com.fastbee.framework.web.service;
import com.fastbee.common.constant.CacheConstants;
import com.fastbee.common.constant.Constants;
import com.fastbee.common.constant.UserConstants;
import com.fastbee.common.core.domain.entity.SysUser;
import com.fastbee.common.core.domain.model.LoginUser;
import com.fastbee.common.core.redis.RedisCache;
import com.fastbee.common.enums.UserStatus;
import com.fastbee.common.exception.ServiceException;
import com.fastbee.common.exception.user.CaptchaException;
import com.fastbee.common.exception.user.CaptchaExpireException;
import com.fastbee.common.exception.user.UserPasswordNotMatchException;
import com.fastbee.common.exception.user.*;
import com.fastbee.common.utils.DateUtils;
import com.fastbee.common.utils.MessageUtils;
import com.fastbee.common.utils.ServletUtils;
import com.fastbee.common.utils.StringUtils;
import com.fastbee.common.utils.ip.IpUtils;
import com.fastbee.framework.manager.AsyncManager;
@@ -70,12 +68,10 @@ public class SysLoginService
*/
public String login(String username, String password, String code, String uuid)
{
boolean captchaEnabled = configService.selectCaptchaEnabled();
// 验证码开关
if (captchaEnabled)
{
// 验证码校验
validateCaptcha(username, code, uuid);
}
// 登录前置校验
loginPreCheck(username, password);
// 用户验证
Authentication authentication = null;
try
@@ -185,21 +181,61 @@ public class SysLoginService
* @return 结果
*/
public void validateCaptcha(String username, String code, String uuid)
{
boolean captchaEnabled = configService.selectCaptchaEnabled();
if (captchaEnabled)
{
String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
String captcha = redisCache.getCacheObject(verifyKey);
redisCache.deleteObject(verifyKey);
if (captcha == null)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
throw new CaptchaExpireException();
}
redisCache.deleteObject(verifyKey);
if (!code.equalsIgnoreCase(captcha))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
throw new CaptchaException();
}
}
}
/**
* 登录前置校验
* @param username 用户名
* @param password 用户密码
*/
public void loginPreCheck(String username, String password)
{
// 用户名或密码为空 错误
if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
throw new UserNotExistsException();
}
// 密码如果不在指定范围内 错误
if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
|| password.length() > UserConstants.PASSWORD_MAX_LENGTH)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException();
}
// 用户名不在指定范围内 错误
if (username.length() < UserConstants.USERNAME_MIN_LENGTH
|| username.length() > UserConstants.USERNAME_MAX_LENGTH)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException();
}
// IP黑名单校验
String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
throw new BlackListException();
}
}
/**
* 记录登录信息
@@ -210,7 +246,7 @@ public class SysLoginService
{
SysUser sysUser = new SysUser();
sysUser.setUserId(userId);
sysUser.setLoginIp(IpUtils.getIpAddr(ServletUtils.getRequest()));
sysUser.setLoginIp(IpUtils.getIpAddr());
sysUser.setLoginDate(DateUtils.getNowDate());
userService.updateUserProfile(sysUser);
}

View File

@@ -5,8 +5,11 @@ import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import com.fastbee.common.constant.UserConstants;
import com.fastbee.common.core.domain.entity.SysRole;
import com.fastbee.common.core.domain.entity.SysUser;
import com.fastbee.common.utils.StringUtils;
import com.fastbee.system.service.ISysMenuService;
import com.fastbee.system.service.ISysRoleService;
@@ -62,16 +65,19 @@ public class SysPermissionService
else
{
List<SysRole> roles = user.getRoles();
if (!roles.isEmpty() && roles.size() > 1)
if (!CollectionUtils.isEmpty(roles))
{
// 多角色设置permissions属性以便数据权限匹配权限
for (SysRole role : roles)
{
if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && !role.isAdmin())
{
Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
role.setPermissions(rolePerms);
perms.addAll(rolePerms);
}
}
}
else
{
perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));

View File

@@ -53,7 +53,7 @@ public class TokenService {
protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
private static final Long MILLIS_MINUTE_TWENTY = 20 * 60 * 1000L;
@Autowired
private RedisCache redisCache;
@@ -160,6 +160,7 @@ public class TokenService {
Map<String, Object> claims = new HashMap<>();
claims.put(Constants.LOGIN_USER_KEY, token);
claims.put(Constants.JWT_USERNAME, loginUser.getUsername());
return createToken(claims);
}
@@ -217,7 +218,7 @@ public class TokenService {
public void verifyToken(LoginUser loginUser) {
long expireTime = loginUser.getExpireTime();
long currentTime = System.currentTimeMillis();
if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
if (expireTime - currentTime <= MILLIS_MINUTE_TWENTY) {
refreshToken(loginUser);
}
}

View File

@@ -11,6 +11,7 @@ import com.fastbee.common.core.domain.entity.SysUser;
import com.fastbee.common.core.domain.model.LoginUser;
import com.fastbee.common.enums.UserStatus;
import com.fastbee.common.exception.ServiceException;
import com.fastbee.common.utils.MessageUtils;
import com.fastbee.common.utils.StringUtils;
import com.fastbee.system.service.ISysUserService;
@@ -40,17 +41,17 @@ public class UserDetailsServiceImpl implements UserDetailsService
if (StringUtils.isNull(user))
{
log.info("登录用户:{} 不存在.", username);
throw new ServiceException("登录用户:" + username + " 不存在");
throw new ServiceException(MessageUtils.message("user.not.exists"));
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
log.info("登录用户:{} 已被删除.", username);
throw new ServiceException("对不起,您的账号:" + username + " 已被删除");
throw new ServiceException(MessageUtils.message("user.password.delete"));
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
log.info("登录用户:{} 已被停用.", username);
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
throw new ServiceException(MessageUtils.message("user.blocked"));
}
passwordService.validate(user);

View File

@@ -16,7 +16,7 @@ public class MqttClientConfig {
public MqttClientConfig() {
this.username = "fastbee";
this.password = "fastbee";
this.hostUrl = "tcp://127.0.0.1:1883";
this.hostUrl = "tcp://127.0.0.1:1884";
this.clientId = UUID.randomUUID().toString();
this.defaultTopic = "test";
this.timeout = 30;

View File

@@ -175,7 +175,7 @@ public class SysMenuServiceImpl implements ISysMenuService
router.setQuery(menu.getQuery());
router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
List<SysMenu> cMenus = menu.getChildren();
if (!cMenus.isEmpty() && cMenus.size() > 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
if (StringUtils.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
{
router.setAlwaysShow(true);
router.setRedirect("noRedirect");
@@ -188,7 +188,7 @@ public class SysMenuServiceImpl implements ISysMenuService
RouterVo children = new RouterVo();
children.setPath(menu.getPath());
children.setComponent(menu.getComponent());
children.setName(StringUtils.capitalize(menu.getPath()));
children.setName(getRouteName(menu.getRouteName(), menu.getPath()));
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
children.setQuery(menu.getQuery());
childrenList.add(children);
@@ -203,7 +203,7 @@ public class SysMenuServiceImpl implements ISysMenuService
String routerPath = innerLinkReplaceEach(menu.getPath());
children.setPath(routerPath);
children.setComponent(UserConstants.INNER_LINK);
children.setName(StringUtils.capitalize(routerPath));
children.setName(getRouteName(menu.getRouteName(), routerPath));
children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
childrenList.add(children);
router.setChildren(childrenList);
@@ -354,13 +354,25 @@ public class SysMenuServiceImpl implements ISysMenuService
*/
public String getRouteName(SysMenu menu)
{
String routerName = StringUtils.capitalize(menu.getPath());
// 非外链并且是一级目录(类型为目录)
if (isMenuFrame(menu))
{
routerName = StringUtils.EMPTY;
return StringUtils.EMPTY;
}
return routerName;
return getRouteName(menu.getRouteName(), menu.getPath());
}
/**
* 获取路由名称,如没有配置路由名称则取路由地址
*
* @param name 路由名称
* @param path 路由地址
* @return 路由名称(驼峰格式)
*/
public String getRouteName(String name, String path)
{
String routerName = StringUtils.isNotEmpty(name) ? name : path;
return StringUtils.capitalize(routerName);
}
/**
@@ -525,7 +537,7 @@ public class SysMenuServiceImpl implements ISysMenuService
*/
public String innerLinkReplaceEach(String path)
{
return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, "." },
new String[] { "", "", "", "/" });
return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, ".", ":" },
new String[] { "", "", "", "/", "/" });
}
}

View File

@@ -2437,7 +2437,11 @@ CREATE TABLE `sys_oper_log` (
`status` int(1) NULL DEFAULT 0 COMMENT '操作状态0正常 1异常',
`error_msg` varchar(2000) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT '' COMMENT '错误消息',
`oper_time` datetime NULL DEFAULT NULL COMMENT '操作时间',
PRIMARY KEY (`oper_id`) USING BTREE
`cost_time` bigint(20) DEFAULT 0 COMMENT '消耗时间',
PRIMARY KEY (`oper_id`) USING BTREE,
KEY idx_sys_oper_log_bt (business_type),
KEY idx_sys_oper_log_s (status),
KEY idx_sys_oper_log_ot (oper_time)
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '操作日志记录' ROW_FORMAT = DYNAMIC;
-- ----------------------------