forked from dyf/fys-Multi-tenant
Merge branch 'main' into dyf-device
# Conflicts: # fys-modules/pom.xml # pom.xml
This commit is contained in:
@ -72,7 +72,7 @@
|
||||
</dependency>
|
||||
|
||||
<!-- 设备管理模块 -->
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>com.fuyuanshen</groupId>
|
||||
<artifactId>fys-equipment</artifactId>
|
||||
</dependency>
|
||||
@ -105,6 +105,13 @@
|
||||
<artifactId>fys-workflow</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- app模块 -->
|
||||
<dependency>
|
||||
<groupId>com.fuyuanshen</groupId>
|
||||
<artifactId>fys-app</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
|
@ -0,0 +1,161 @@
|
||||
package com.fuyuanshen.app.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fuyuanshen.app.model.AppSmsLoginBody;
|
||||
import com.fuyuanshen.app.service.AppLoginService;
|
||||
import com.fuyuanshen.common.core.constant.SystemConstants;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.core.domain.model.RegisterBody;
|
||||
import com.fuyuanshen.common.core.domain.model.SmsLoginBody;
|
||||
import com.fuyuanshen.common.core.utils.*;
|
||||
import com.fuyuanshen.common.encrypt.annotation.ApiEncrypt;
|
||||
import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.satoken.utils.LoginHelper;
|
||||
import com.fuyuanshen.common.tenant.helper.TenantHelper;
|
||||
import com.fuyuanshen.system.domain.bo.SysTenantBo;
|
||||
import com.fuyuanshen.system.domain.vo.SysClientVo;
|
||||
import com.fuyuanshen.system.domain.vo.SysTenantVo;
|
||||
import com.fuyuanshen.system.service.ISysClientService;
|
||||
import com.fuyuanshen.system.service.ISysConfigService;
|
||||
import com.fuyuanshen.system.service.ISysTenantService;
|
||||
import com.fuyuanshen.web.domain.vo.LoginTenantVo;
|
||||
import com.fuyuanshen.web.domain.vo.LoginVo;
|
||||
import com.fuyuanshen.web.domain.vo.TenantListVo;
|
||||
import com.fuyuanshen.web.service.IAuthStrategy;
|
||||
import com.fuyuanshen.web.service.SysRegisterService;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* APP认证
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@Slf4j
|
||||
@SaIgnore
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/app/auth")
|
||||
public class AppAuthController {
|
||||
|
||||
private final AppLoginService loginService;
|
||||
private final SysRegisterService registerService;
|
||||
private final ISysConfigService configService;
|
||||
private final ISysTenantService tenantService;
|
||||
private final ISysClientService clientService;
|
||||
|
||||
|
||||
/**
|
||||
* 登录方法
|
||||
*
|
||||
* @return 结果
|
||||
*/
|
||||
// @ApiEncrypt
|
||||
@PostMapping("/login")
|
||||
public R<LoginVo> login(@RequestBody AppSmsLoginBody appSmsLoginBody) {
|
||||
// SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
|
||||
LoginHelper.getLoginUser();
|
||||
ValidatorUtils.validate(appSmsLoginBody);
|
||||
SmsLoginBody loginBody = new SmsLoginBody();
|
||||
loginBody.setPhonenumber(appSmsLoginBody.getPhonenumber());
|
||||
loginBody.setSmsCode(appSmsLoginBody.getSmsCode());
|
||||
loginBody.setTenantId(appSmsLoginBody.getTenantId());
|
||||
loginBody.setClientId("ca839698e245d60aa2f0e59bd52b34f8");
|
||||
loginBody.setGrantType("appSms");
|
||||
// 授权类型和客户端id
|
||||
String clientId = loginBody.getClientId();
|
||||
String grantType = loginBody.getGrantType();
|
||||
SysClientVo client = clientService.queryByClientId(clientId);
|
||||
// 查询不到 client 或 client 内不包含 grantType
|
||||
if (ObjectUtil.isNull(client) || !StringUtils.contains(client.getGrantType(), grantType)) {
|
||||
log.info("客户端id: {} 认证类型:{} 异常!.", clientId, grantType);
|
||||
return R.fail(MessageUtils.message("auth.grant.type.error"));
|
||||
} else if (!SystemConstants.NORMAL.equals(client.getStatus())) {
|
||||
return R.fail(MessageUtils.message("auth.grant.type.blocked"));
|
||||
}
|
||||
// 校验租户
|
||||
loginService.checkTenant(loginBody.getTenantId());
|
||||
// 登录
|
||||
String body = JsonUtils.toJsonString(loginBody);
|
||||
LoginVo loginVo = IAuthStrategy.login(body, client, grantType);
|
||||
return R.ok(loginVo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
@PostMapping("/logout")
|
||||
public R<Void> logout() {
|
||||
// loginService.logout();
|
||||
return R.ok("退出成功");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户注册
|
||||
*/
|
||||
@ApiEncrypt
|
||||
@PostMapping("/register")
|
||||
public R<Void> register(@Validated @RequestBody RegisterBody user) {
|
||||
if (!configService.selectRegisterEnabled(user.getTenantId())) {
|
||||
return R.fail("当前系统没有开启注册功能!");
|
||||
}
|
||||
registerService.register(user);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录页面租户下拉框
|
||||
*
|
||||
* @return 租户列表
|
||||
*/
|
||||
@GetMapping("/tenant/list")
|
||||
public R<LoginTenantVo> tenantList(HttpServletRequest request) throws Exception {
|
||||
// 返回对象
|
||||
LoginTenantVo result = new LoginTenantVo();
|
||||
boolean enable = TenantHelper.isEnable();
|
||||
result.setTenantEnabled(enable);
|
||||
// 如果未开启租户这直接返回
|
||||
if (!enable) {
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
List<SysTenantVo> tenantList = tenantService.queryList(new SysTenantBo());
|
||||
List<TenantListVo> voList = MapstructUtils.convert(tenantList, TenantListVo.class);
|
||||
try {
|
||||
// 如果只超管返回所有租户
|
||||
if (LoginHelper.isSuperAdmin()) {
|
||||
result.setVoList(voList);
|
||||
return R.ok(result);
|
||||
}
|
||||
} catch (NotLoginException ignored) {
|
||||
}
|
||||
|
||||
// 获取域名
|
||||
String host;
|
||||
String referer = request.getHeader("referer");
|
||||
if (StringUtils.isNotBlank(referer)) {
|
||||
// 这里从referer中取值是为了本地使用hosts添加虚拟域名,方便本地环境调试
|
||||
host = referer.split("//")[1].split("/")[0];
|
||||
} else {
|
||||
host = new URL(request.getRequestURL().toString()).getHost();
|
||||
}
|
||||
// 根据域名进行筛选
|
||||
List<TenantListVo> list = StreamUtils.filter(voList, vo ->
|
||||
StringUtils.equalsIgnoreCase(vo.getDomain(), host));
|
||||
result.setVoList(CollUtil.isNotEmpty(list) ? list : voList);
|
||||
return R.ok(result);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
package com.fuyuanshen.app.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import com.fuyuanshen.app.domain.bo.AppUserBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppUserVo;
|
||||
import com.fuyuanshen.app.domain.vo.DeviceVo;
|
||||
import com.fuyuanshen.app.service.DeviceService;
|
||||
import com.fuyuanshen.app.service.IAppUserService;
|
||||
import com.fuyuanshen.common.core.domain.R;
|
||||
import com.fuyuanshen.common.core.validate.AddGroup;
|
||||
import com.fuyuanshen.common.core.validate.EditGroup;
|
||||
import com.fuyuanshen.common.excel.utils.ExcelUtil;
|
||||
import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit;
|
||||
import com.fuyuanshen.common.log.annotation.Log;
|
||||
import com.fuyuanshen.common.log.enums.BusinessType;
|
||||
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
import com.fuyuanshen.common.web.core.BaseController;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* APP 设备信息管理
|
||||
* @date 2025-06-27
|
||||
*/
|
||||
@Validated
|
||||
@RequiredArgsConstructor
|
||||
@RestController
|
||||
@RequestMapping("/app/device")
|
||||
public class AppDeviceController extends BaseController {
|
||||
|
||||
private final DeviceService deviceService;
|
||||
|
||||
/**
|
||||
* 查询设备信息列表
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public TableDataInfo<DeviceVo> list(AppUserBo bo, PageQuery pageQuery) {
|
||||
return deviceService.queryPageList(bo, pageQuery);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.fuyuanshen.app.domain.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class DeviceVo {
|
||||
|
||||
private String deviceId;
|
||||
|
||||
private String deviceName;
|
||||
|
||||
private String deviceType;
|
||||
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package com.fuyuanshen.app.model;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class AppSmsLoginBody {
|
||||
/**
|
||||
* 手机号
|
||||
*/
|
||||
@NotBlank(message = "{user.phonenumber.not.blank}")
|
||||
private String phonenumber;
|
||||
|
||||
/**
|
||||
* 短信code
|
||||
*/
|
||||
@NotBlank(message = "{sms.code.not.blank}")
|
||||
private String smsCode;
|
||||
|
||||
/**
|
||||
* 租户ID
|
||||
*/
|
||||
@NotBlank(message = "租户ID不能为空")
|
||||
private String tenantId;
|
||||
}
|
@ -0,0 +1,188 @@
|
||||
package com.fuyuanshen.app.service;
|
||||
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fuyuanshen.app.domain.vo.AppRoleVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppUserVo;
|
||||
import com.fuyuanshen.common.core.constant.Constants;
|
||||
import com.fuyuanshen.common.core.constant.SystemConstants;
|
||||
import com.fuyuanshen.common.core.constant.TenantConstants;
|
||||
import com.fuyuanshen.common.core.domain.dto.RoleDTO;
|
||||
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
|
||||
import com.fuyuanshen.common.core.enums.LoginType;
|
||||
import com.fuyuanshen.common.core.exception.user.UserException;
|
||||
import com.fuyuanshen.common.core.utils.MessageUtils;
|
||||
import com.fuyuanshen.common.core.utils.ServletUtils;
|
||||
import com.fuyuanshen.common.core.utils.SpringUtils;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.log.event.LogininforEvent;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.common.satoken.utils.LoginHelper;
|
||||
import com.fuyuanshen.common.tenant.exception.TenantException;
|
||||
import com.fuyuanshen.common.tenant.helper.TenantHelper;
|
||||
import com.fuyuanshen.system.domain.vo.SysTenantVo;
|
||||
import com.fuyuanshen.system.service.ISysTenantService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Service
|
||||
public class AppLoginService {
|
||||
|
||||
@Value("${user.password.maxRetryCount}")
|
||||
private Integer maxRetryCount;
|
||||
|
||||
@Value("${user.password.lockTime}")
|
||||
private Integer lockTime;
|
||||
|
||||
private final ISysTenantService tenantService;
|
||||
private final IAppRoleService roleService;
|
||||
|
||||
|
||||
/**
|
||||
* 登录账户密码错误次数 redis key
|
||||
*/
|
||||
String PWD_ERR_CNT_KEY = "app_pwd_err_cnt:";
|
||||
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
*/
|
||||
/*public void logout() {
|
||||
try {
|
||||
AppLoginUser loginUser = AppLoginHelper.getLoginUser();
|
||||
if (ObjectUtil.isNull(loginUser)) {
|
||||
return;
|
||||
}
|
||||
if (TenantHelper.isEnable() && LoginHelper.isSuperAdmin()) {
|
||||
// 超级管理员 登出清除动态租户
|
||||
TenantHelper.clearDynamic();
|
||||
}
|
||||
recordLogininfor(loginUser.getTenantId(), loginUser.getUsername(), Constants.LOGOUT, MessageUtils.message("user.logout.success"));
|
||||
} catch (NotLoginException ignored) {
|
||||
} finally {
|
||||
try {
|
||||
StpUtil.logout();
|
||||
} catch (NotLoginException ignored) {
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 记录登录信息
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
* @param username 用户名
|
||||
* @param status 状态
|
||||
* @param message 消息内容
|
||||
*/
|
||||
public void recordLogininfor(String tenantId, String username, String status, String message) {
|
||||
LogininforEvent logininforEvent = new LogininforEvent();
|
||||
logininforEvent.setTenantId(tenantId);
|
||||
logininforEvent.setUsername(username);
|
||||
logininforEvent.setStatus(status);
|
||||
logininforEvent.setMessage(message);
|
||||
logininforEvent.setRequest(ServletUtils.getRequest());
|
||||
SpringUtils.context().publishEvent(logininforEvent);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建登录用户
|
||||
*/
|
||||
public AppLoginUser buildLoginUser(AppUserVo user) {
|
||||
AppLoginUser loginUser = new AppLoginUser();
|
||||
Long userId = user.getUserId();
|
||||
loginUser.setTenantId(user.getTenantId());
|
||||
loginUser.setUserId(userId);
|
||||
loginUser.setDeptId(user.getDeptId());
|
||||
loginUser.setUsername(user.getUserName());
|
||||
loginUser.setNickname(user.getNickName());
|
||||
loginUser.setUserType(user.getUserType());
|
||||
Set<String> perms = new HashSet<>();
|
||||
loginUser.setMenuPermission(perms);
|
||||
loginUser.setRolePermission(perms);
|
||||
loginUser.setRoles(new ArrayList<>());
|
||||
/* List<AppRoleVo> roles = appRoleService.selectRolesByUserId(userId);
|
||||
loginUser.setRoles(BeanUtil.copyToList(roles, RoleDTO.class));*/
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录校验
|
||||
*/
|
||||
public void checkLogin(LoginType loginType, String tenantId, String username, Supplier<Boolean> supplier) {
|
||||
String errorKey = PWD_ERR_CNT_KEY + username;
|
||||
String loginFail = Constants.LOGIN_FAIL;
|
||||
|
||||
// 获取用户登录错误次数,默认为0 (可自定义限制策略 例如: key + username + ip)
|
||||
int errorNumber = ObjectUtil.defaultIfNull(RedisUtils.getCacheObject(errorKey), 0);
|
||||
// 锁定时间内登录 则踢出
|
||||
if (errorNumber >= maxRetryCount) {
|
||||
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||
}
|
||||
|
||||
if (supplier.get()) {
|
||||
// 错误次数递增
|
||||
errorNumber++;
|
||||
RedisUtils.setCacheObject(errorKey, errorNumber, Duration.ofMinutes(lockTime));
|
||||
// 达到规定错误次数 则锁定登录
|
||||
if (errorNumber >= maxRetryCount) {
|
||||
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitExceed(), maxRetryCount, lockTime));
|
||||
throw new UserException(loginType.getRetryLimitExceed(), maxRetryCount, lockTime);
|
||||
} else {
|
||||
// 未达到规定错误次数
|
||||
recordLogininfor(tenantId, username, loginFail, MessageUtils.message(loginType.getRetryLimitCount(), errorNumber));
|
||||
throw new UserException(loginType.getRetryLimitCount(), errorNumber);
|
||||
}
|
||||
}
|
||||
|
||||
// 登录成功 清空错误次数
|
||||
RedisUtils.deleteObject(errorKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验租户
|
||||
*
|
||||
* @param tenantId 租户ID
|
||||
*/
|
||||
public void checkTenant(String tenantId) {
|
||||
if (!TenantHelper.isEnable()) {
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isBlank(tenantId)) {
|
||||
throw new TenantException("tenant.number.not.blank");
|
||||
}
|
||||
if (TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) {
|
||||
return;
|
||||
}
|
||||
SysTenantVo tenant = tenantService.queryByTenantId(tenantId);
|
||||
if (ObjectUtil.isNull(tenant)) {
|
||||
log.info("登录租户:{} 不存在.", tenantId);
|
||||
throw new TenantException("tenant.not.exists");
|
||||
} else if (SystemConstants.DISABLE.equals(tenant.getStatus())) {
|
||||
log.info("登录租户:{} 已被停用.", tenantId);
|
||||
throw new TenantException("tenant.blocked");
|
||||
} else if (ObjectUtil.isNotNull(tenant.getExpireTime())
|
||||
&& new Date().after(tenant.getExpireTime())) {
|
||||
log.info("登录租户:{} 已超过有效期.", tenantId);
|
||||
throw new TenantException("tenant.expired");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
package com.fuyuanshen.app.service;
|
||||
|
||||
import cn.dev33.satoken.exception.NotLoginException;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.fuyuanshen.app.domain.bo.AppUserBo;
|
||||
import com.fuyuanshen.app.domain.vo.AppRoleVo;
|
||||
import com.fuyuanshen.app.domain.vo.AppUserVo;
|
||||
import com.fuyuanshen.app.domain.vo.DeviceVo;
|
||||
import com.fuyuanshen.common.core.constant.Constants;
|
||||
import com.fuyuanshen.common.core.constant.SystemConstants;
|
||||
import com.fuyuanshen.common.core.constant.TenantConstants;
|
||||
import com.fuyuanshen.common.core.domain.dto.RoleDTO;
|
||||
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
|
||||
import com.fuyuanshen.common.core.domain.model.LoginUser;
|
||||
import com.fuyuanshen.common.core.enums.LoginType;
|
||||
import com.fuyuanshen.common.core.exception.user.UserException;
|
||||
import com.fuyuanshen.common.core.utils.MessageUtils;
|
||||
import com.fuyuanshen.common.core.utils.ServletUtils;
|
||||
import com.fuyuanshen.common.core.utils.SpringUtils;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.log.event.LogininforEvent;
|
||||
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
|
||||
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.common.satoken.utils.LoginHelper;
|
||||
import com.fuyuanshen.common.tenant.exception.TenantException;
|
||||
import com.fuyuanshen.common.tenant.helper.TenantHelper;
|
||||
import com.fuyuanshen.system.domain.vo.SysTenantVo;
|
||||
import com.fuyuanshen.system.service.ISysTenantService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 登录校验方法
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@RequiredArgsConstructor
|
||||
@Slf4j
|
||||
@Service
|
||||
public class DeviceService {
|
||||
|
||||
|
||||
public TableDataInfo<DeviceVo> queryPageList(AppUserBo bo, PageQuery pageQuery) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package com.fuyuanshen.web.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.stp.parameter.SaLoginParameter;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.fuyuanshen.app.domain.AppUser;
|
||||
import com.fuyuanshen.app.domain.vo.AppUserVo;
|
||||
import com.fuyuanshen.app.mapper.AppUserMapper;
|
||||
import com.fuyuanshen.app.service.AppLoginService;
|
||||
import com.fuyuanshen.common.core.constant.Constants;
|
||||
import com.fuyuanshen.common.core.constant.GlobalConstants;
|
||||
import com.fuyuanshen.common.core.constant.SystemConstants;
|
||||
import com.fuyuanshen.common.core.domain.model.AppLoginUser;
|
||||
import com.fuyuanshen.common.core.domain.model.SmsLoginBody;
|
||||
import com.fuyuanshen.common.core.enums.LoginType;
|
||||
import com.fuyuanshen.common.core.exception.user.CaptchaExpireException;
|
||||
import com.fuyuanshen.common.core.exception.user.UserException;
|
||||
import com.fuyuanshen.common.core.utils.MessageUtils;
|
||||
import com.fuyuanshen.common.core.utils.ServletUtils;
|
||||
import com.fuyuanshen.common.core.utils.StringUtils;
|
||||
import com.fuyuanshen.common.core.utils.ValidatorUtils;
|
||||
import com.fuyuanshen.common.json.utils.JsonUtils;
|
||||
import com.fuyuanshen.common.redis.utils.RedisUtils;
|
||||
import com.fuyuanshen.common.satoken.utils.AppLoginHelper;
|
||||
import com.fuyuanshen.common.tenant.helper.TenantHelper;
|
||||
import com.fuyuanshen.system.domain.vo.SysClientVo;
|
||||
import com.fuyuanshen.web.domain.vo.LoginVo;
|
||||
import com.fuyuanshen.web.service.IAuthStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.client.RestClient;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 短信认证策略
|
||||
*
|
||||
* @author Michelle.Chung
|
||||
*/
|
||||
@Slf4j
|
||||
@Service("appSms" + IAuthStrategy.BASE_NAME)
|
||||
@RequiredArgsConstructor
|
||||
public class AppSmsAuthStrategy implements IAuthStrategy {
|
||||
|
||||
private final AppLoginService loginService;
|
||||
private final AppUserMapper appUserMapper;
|
||||
private final RestClient.Builder builder;
|
||||
|
||||
@Override
|
||||
public LoginVo login(String body, SysClientVo client) {
|
||||
SmsLoginBody loginBody = JsonUtils.parseObject(body, SmsLoginBody.class);
|
||||
ValidatorUtils.validate(loginBody);
|
||||
String tenantId = loginBody.getTenantId();
|
||||
String phonenumber = loginBody.getPhonenumber();
|
||||
String smsCode = loginBody.getSmsCode();
|
||||
AppLoginUser loginUser = TenantHelper.dynamic(tenantId, () -> {
|
||||
loginService.checkLogin(LoginType.SMS, tenantId, phonenumber, () -> !validateSmsCode(tenantId, phonenumber, smsCode));
|
||||
AppUserVo user = loadUserByPhonenumber(phonenumber);
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
//新增Appuser
|
||||
addAppUser(tenantId, phonenumber);
|
||||
|
||||
user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhonenumber, phonenumber));
|
||||
// loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists", phonenumber));
|
||||
// throw new UserException("user.not.exists", phonenumber);
|
||||
}
|
||||
|
||||
// 此处可根据登录用户的数据不同 自行创建 loginUser 属性不够用继承扩展就行了
|
||||
return loginService.buildLoginUser(user);
|
||||
});
|
||||
loginUser.setClientKey(client.getClientKey());
|
||||
loginUser.setDeviceType(client.getDeviceType());
|
||||
SaLoginParameter model = new SaLoginParameter();
|
||||
model.setDeviceType(client.getDeviceType());
|
||||
// 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
|
||||
// 例如: 后台用户30分钟过期 app用户1天过期
|
||||
model.setTimeout(client.getTimeout());
|
||||
model.setActiveTimeout(client.getActiveTimeout());
|
||||
model.setExtra(AppLoginHelper.CLIENT_KEY, client.getClientId());
|
||||
// 生成token
|
||||
AppLoginHelper.login(loginUser, model);
|
||||
|
||||
LoginVo loginVo = new LoginVo();
|
||||
loginVo.setAccessToken(StpUtil.getTokenValue());
|
||||
loginVo.setExpireIn(StpUtil.getTokenTimeout());
|
||||
loginVo.setClientId(client.getClientId());
|
||||
return loginVo;
|
||||
}
|
||||
|
||||
private void addAppUser(String tenantId, String phonenumber) {
|
||||
AppUser appUser = new AppUser();
|
||||
appUser.setPhonenumber(phonenumber);
|
||||
appUser.setUserName(phonenumber);
|
||||
appUser.setStatus("0");
|
||||
appUser.setLoginDate(new Date());
|
||||
appUser.setLoginIp(ServletUtils.getClientIP());
|
||||
appUser.setTenantId(tenantId);
|
||||
appUserMapper.insert(appUser);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 校验短信验证码
|
||||
*/
|
||||
private boolean validateSmsCode(String tenantId, String phonenumber, String smsCode) {
|
||||
String code = RedisUtils.getCacheObject(GlobalConstants.CAPTCHA_CODE_KEY + phonenumber);
|
||||
if (StringUtils.isBlank(code)) {
|
||||
loginService.recordLogininfor(tenantId, phonenumber, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire"));
|
||||
throw new CaptchaExpireException();
|
||||
}
|
||||
return code.equals(smsCode);
|
||||
}
|
||||
|
||||
private AppUserVo loadUserByPhonenumber(String phonenumber) {
|
||||
AppUserVo user = appUserMapper.selectVoOne(new LambdaQueryWrapper<AppUser>().eq(AppUser::getPhonenumber, phonenumber));
|
||||
if (ObjectUtil.isNull(user)) {
|
||||
log.info("登录用户:{} 不存在.", phonenumber);
|
||||
// throw new UserException("user.not.exists", phonenumber);
|
||||
// 新增AppUser用户
|
||||
return null;
|
||||
} else if (SystemConstants.DISABLE.equals(user.getStatus())) {
|
||||
log.info("登录用户:{} 已被停用.", phonenumber);
|
||||
throw new UserException("user.blocked", phonenumber);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
}
|
@ -49,9 +49,9 @@ spring:
|
||||
driverClassName: com.mysql.cj.jdbc.Driver
|
||||
# jdbc 所有参数配置参考 https://lionli.blog.csdn.net/article/details/122018562
|
||||
# rewriteBatchedStatements=true 批处理优化 大幅提升批量插入更新删除性能(对数据库有性能损耗 使用批量操作应考虑性能问题)
|
||||
url: jdbc:mysql://localhost:3306/fys-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
url: jdbc:mysql://120.79.224.186:3366/fys-vue?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
|
||||
username: root
|
||||
password: root
|
||||
password: 1fys@QWER..
|
||||
# # 从库数据源
|
||||
# slave:
|
||||
# lazy: true
|
||||
@ -98,13 +98,13 @@ spring:
|
||||
spring.data:
|
||||
redis:
|
||||
# 地址
|
||||
host: 123.207.99.140
|
||||
host: 120.79.224.186
|
||||
# 端口,默认为6379
|
||||
port: 6379
|
||||
port: 26379
|
||||
# 数据库索引
|
||||
database: 2
|
||||
# redis 密码必须配置
|
||||
password: ccxx11234
|
||||
password: 1fys@QWER..
|
||||
# 连接超时时间
|
||||
timeout: 10s
|
||||
# 是否开启ssl
|
||||
|
@ -127,6 +127,9 @@ tenant:
|
||||
- sys_user_role
|
||||
- sys_client
|
||||
- sys_oss_config
|
||||
- app_menu
|
||||
- app_user_role
|
||||
- app_role_menu
|
||||
|
||||
# MyBatisPlus配置
|
||||
# https://baomidou.com/config/
|
||||
|
Reference in New Issue
Block a user