【feat】 初始化登录管理对象

This commit is contained in:
Kris 2025-12-14 15:41:32 +08:00
parent 5e3e2a4377
commit b628132cff
41 changed files with 5013 additions and 0 deletions

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.datai</groupId>
<artifactId>datai-scene-salesforce</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>datai-salesforce-auth</artifactId>
<properties>
<maven.compiler.source>22</maven.compiler.source>
<maven.compiler.target>22</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-common</artifactId>
</dependency>
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-cache-redis</artifactId>
<version>${datai.version}</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,113 @@
package com.datai.auth.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.datai.common.annotation.Log;
import com.datai.common.core.controller.BaseController;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.enums.BusinessType;
import com.datai.auth.domain.DataiSfFailedLogin;
import com.datai.auth.service.IDataiSfFailedLoginService;
import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
/**
* 失败登录Controller
*
* @author datai
* @date 2025-12-14
*/
@RestController
@RequestMapping("/auth/login")
@Tag(name = "【失败登录】管理")
public class DataiSfFailedLoginController extends BaseController
{
@Autowired
private IDataiSfFailedLoginService dataiSfFailedLoginService;
/**
* 查询失败登录列表
*/
@Operation(summary = "查询失败登录列表")
@PreAuthorize("@ss.hasPermi('auth:login:list')")
@GetMapping("/list")
public TableDataInfo list(DataiSfFailedLogin dataiSfFailedLogin)
{
startPage();
List<DataiSfFailedLogin> list = dataiSfFailedLoginService.selectDataiSfFailedLoginList(dataiSfFailedLogin);
return getDataTable(list);
}
/**
* 导出失败登录列表
*/
@Operation(summary = "导出失败登录列表")
@PreAuthorize("@ss.hasPermi('auth:login:export')")
@Log(title = "失败登录", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DataiSfFailedLogin dataiSfFailedLogin)
{
List<DataiSfFailedLogin> list = dataiSfFailedLoginService.selectDataiSfFailedLoginList(dataiSfFailedLogin);
ExcelUtil<DataiSfFailedLogin> util = new ExcelUtil<DataiSfFailedLogin>(DataiSfFailedLogin.class);
util.exportExcel(response, list, "失败登录数据");
}
/**
* 获取失败登录详细信息
*/
@Operation(summary = "获取失败登录详细信息")
@PreAuthorize("@ss.hasPermi('auth:login:query')")
@GetMapping(value = "/{failedId}")
public AjaxResult getInfo(@PathVariable("failedId") Long failedId)
{
return success(dataiSfFailedLoginService.selectDataiSfFailedLoginByFailedId(failedId));
}
/**
* 新增失败登录
*/
@Operation(summary = "新增失败登录")
@PreAuthorize("@ss.hasPermi('auth:login:add')")
@Log(title = "失败登录", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DataiSfFailedLogin dataiSfFailedLogin)
{
return toAjax(dataiSfFailedLoginService.insertDataiSfFailedLogin(dataiSfFailedLogin));
}
/**
* 修改失败登录
*/
@Operation(summary = "修改失败登录")
@PreAuthorize("@ss.hasPermi('auth:login:edit')")
@Log(title = "失败登录", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DataiSfFailedLogin dataiSfFailedLogin)
{
return toAjax(dataiSfFailedLoginService.updateDataiSfFailedLogin(dataiSfFailedLogin));
}
/**
* 删除失败登录
*/
@Operation(summary = "删除失败登录")
@PreAuthorize("@ss.hasPermi('auth:login:remove')")
@Log(title = "失败登录", businessType = BusinessType.DELETE)
@DeleteMapping("/{failedIds}")
public AjaxResult remove(@PathVariable( name = "failedIds" ) Long[] failedIds)
{
return toAjax(dataiSfFailedLoginService.deleteDataiSfFailedLoginByFailedIds(failedIds));
}
}

View File

@ -0,0 +1,113 @@
package com.datai.auth.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.datai.common.annotation.Log;
import com.datai.common.core.controller.BaseController;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.enums.BusinessType;
import com.datai.auth.domain.DataiSfLoginAudit;
import com.datai.auth.service.IDataiSfLoginAuditService;
import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
/**
* 登录审计日志Controller
*
* @author datai
* @date 2025-12-14
*/
@RestController
@RequestMapping("/auth/audit")
@Tag(name = "【登录审计日志】管理")
public class DataiSfLoginAuditController extends BaseController
{
@Autowired
private IDataiSfLoginAuditService dataiSfLoginAuditService;
/**
* 查询登录审计日志列表
*/
@Operation(summary = "查询登录审计日志列表")
@PreAuthorize("@ss.hasPermi('auth:audit:list')")
@GetMapping("/list")
public TableDataInfo list(DataiSfLoginAudit dataiSfLoginAudit)
{
startPage();
List<DataiSfLoginAudit> list = dataiSfLoginAuditService.selectDataiSfLoginAuditList(dataiSfLoginAudit);
return getDataTable(list);
}
/**
* 导出登录审计日志列表
*/
@Operation(summary = "导出登录审计日志列表")
@PreAuthorize("@ss.hasPermi('auth:audit:export')")
@Log(title = "登录审计日志", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DataiSfLoginAudit dataiSfLoginAudit)
{
List<DataiSfLoginAudit> list = dataiSfLoginAuditService.selectDataiSfLoginAuditList(dataiSfLoginAudit);
ExcelUtil<DataiSfLoginAudit> util = new ExcelUtil<DataiSfLoginAudit>(DataiSfLoginAudit.class);
util.exportExcel(response, list, "登录审计日志数据");
}
/**
* 获取登录审计日志详细信息
*/
@Operation(summary = "获取登录审计日志详细信息")
@PreAuthorize("@ss.hasPermi('auth:audit:query')")
@GetMapping(value = "/{auditId}")
public AjaxResult getInfo(@PathVariable("auditId") Long auditId)
{
return success(dataiSfLoginAuditService.selectDataiSfLoginAuditByAuditId(auditId));
}
/**
* 新增登录审计日志
*/
@Operation(summary = "新增登录审计日志")
@PreAuthorize("@ss.hasPermi('auth:audit:add')")
@Log(title = "登录审计日志", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DataiSfLoginAudit dataiSfLoginAudit)
{
return toAjax(dataiSfLoginAuditService.insertDataiSfLoginAudit(dataiSfLoginAudit));
}
/**
* 修改登录审计日志
*/
@Operation(summary = "修改登录审计日志")
@PreAuthorize("@ss.hasPermi('auth:audit:edit')")
@Log(title = "登录审计日志", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DataiSfLoginAudit dataiSfLoginAudit)
{
return toAjax(dataiSfLoginAuditService.updateDataiSfLoginAudit(dataiSfLoginAudit));
}
/**
* 删除登录审计日志
*/
@Operation(summary = "删除登录审计日志")
@PreAuthorize("@ss.hasPermi('auth:audit:remove')")
@Log(title = "登录审计日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{auditIds}")
public AjaxResult remove(@PathVariable( name = "auditIds" ) Long[] auditIds)
{
return toAjax(dataiSfLoginAuditService.deleteDataiSfLoginAuditByAuditIds(auditIds));
}
}

View File

@ -0,0 +1,113 @@
package com.datai.auth.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.datai.common.annotation.Log;
import com.datai.common.core.controller.BaseController;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.enums.BusinessType;
import com.datai.auth.domain.DataiSfLoginSession;
import com.datai.auth.service.IDataiSfLoginSessionService;
import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
/**
* 登录会话Controller
*
* @author datai
* @date 2025-12-14
*/
@RestController
@RequestMapping("/auth/session")
@Tag(name = "【登录会话】管理")
public class DataiSfLoginSessionController extends BaseController
{
@Autowired
private IDataiSfLoginSessionService dataiSfLoginSessionService;
/**
* 查询登录会话列表
*/
@Operation(summary = "查询登录会话列表")
@PreAuthorize("@ss.hasPermi('auth:session:list')")
@GetMapping("/list")
public TableDataInfo list(DataiSfLoginSession dataiSfLoginSession)
{
startPage();
List<DataiSfLoginSession> list = dataiSfLoginSessionService.selectDataiSfLoginSessionList(dataiSfLoginSession);
return getDataTable(list);
}
/**
* 导出登录会话列表
*/
@Operation(summary = "导出登录会话列表")
@PreAuthorize("@ss.hasPermi('auth:session:export')")
@Log(title = "登录会话", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DataiSfLoginSession dataiSfLoginSession)
{
List<DataiSfLoginSession> list = dataiSfLoginSessionService.selectDataiSfLoginSessionList(dataiSfLoginSession);
ExcelUtil<DataiSfLoginSession> util = new ExcelUtil<DataiSfLoginSession>(DataiSfLoginSession.class);
util.exportExcel(response, list, "登录会话数据");
}
/**
* 获取登录会话详细信息
*/
@Operation(summary = "获取登录会话详细信息")
@PreAuthorize("@ss.hasPermi('auth:session:query')")
@GetMapping(value = "/{sessionId}")
public AjaxResult getInfo(@PathVariable("sessionId") Long sessionId)
{
return success(dataiSfLoginSessionService.selectDataiSfLoginSessionBySessionId(sessionId));
}
/**
* 新增登录会话
*/
@Operation(summary = "新增登录会话")
@PreAuthorize("@ss.hasPermi('auth:session:add')")
@Log(title = "登录会话", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DataiSfLoginSession dataiSfLoginSession)
{
return toAjax(dataiSfLoginSessionService.insertDataiSfLoginSession(dataiSfLoginSession));
}
/**
* 修改登录会话
*/
@Operation(summary = "修改登录会话")
@PreAuthorize("@ss.hasPermi('auth:session:edit')")
@Log(title = "登录会话", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DataiSfLoginSession dataiSfLoginSession)
{
return toAjax(dataiSfLoginSessionService.updateDataiSfLoginSession(dataiSfLoginSession));
}
/**
* 删除登录会话
*/
@Operation(summary = "删除登录会话")
@PreAuthorize("@ss.hasPermi('auth:session:remove')")
@Log(title = "登录会话", businessType = BusinessType.DELETE)
@DeleteMapping("/{sessionIds}")
public AjaxResult remove(@PathVariable( name = "sessionIds" ) Long[] sessionIds)
{
return toAjax(dataiSfLoginSessionService.deleteDataiSfLoginSessionBySessionIds(sessionIds));
}
}

View File

@ -0,0 +1,113 @@
package com.datai.auth.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.datai.common.annotation.Log;
import com.datai.common.core.controller.BaseController;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.enums.BusinessType;
import com.datai.auth.domain.DataiSfLoginStatistics;
import com.datai.auth.service.IDataiSfLoginStatisticsService;
import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
/**
* 登录统计Controller
*
* @author datai
* @date 2025-12-14
*/
@RestController
@RequestMapping("/auth/statistics")
@Tag(name = "【登录统计】管理")
public class DataiSfLoginStatisticsController extends BaseController
{
@Autowired
private IDataiSfLoginStatisticsService dataiSfLoginStatisticsService;
/**
* 查询登录统计列表
*/
@Operation(summary = "查询登录统计列表")
@PreAuthorize("@ss.hasPermi('auth:statistics:list')")
@GetMapping("/list")
public TableDataInfo list(DataiSfLoginStatistics dataiSfLoginStatistics)
{
startPage();
List<DataiSfLoginStatistics> list = dataiSfLoginStatisticsService.selectDataiSfLoginStatisticsList(dataiSfLoginStatistics);
return getDataTable(list);
}
/**
* 导出登录统计列表
*/
@Operation(summary = "导出登录统计列表")
@PreAuthorize("@ss.hasPermi('auth:statistics:export')")
@Log(title = "登录统计", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DataiSfLoginStatistics dataiSfLoginStatistics)
{
List<DataiSfLoginStatistics> list = dataiSfLoginStatisticsService.selectDataiSfLoginStatisticsList(dataiSfLoginStatistics);
ExcelUtil<DataiSfLoginStatistics> util = new ExcelUtil<DataiSfLoginStatistics>(DataiSfLoginStatistics.class);
util.exportExcel(response, list, "登录统计数据");
}
/**
* 获取登录统计详细信息
*/
@Operation(summary = "获取登录统计详细信息")
@PreAuthorize("@ss.hasPermi('auth:statistics:query')")
@GetMapping(value = "/{statId}")
public AjaxResult getInfo(@PathVariable("statId") Long statId)
{
return success(dataiSfLoginStatisticsService.selectDataiSfLoginStatisticsByStatId(statId));
}
/**
* 新增登录统计
*/
@Operation(summary = "新增登录统计")
@PreAuthorize("@ss.hasPermi('auth:statistics:add')")
@Log(title = "登录统计", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DataiSfLoginStatistics dataiSfLoginStatistics)
{
return toAjax(dataiSfLoginStatisticsService.insertDataiSfLoginStatistics(dataiSfLoginStatistics));
}
/**
* 修改登录统计
*/
@Operation(summary = "修改登录统计")
@PreAuthorize("@ss.hasPermi('auth:statistics:edit')")
@Log(title = "登录统计", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DataiSfLoginStatistics dataiSfLoginStatistics)
{
return toAjax(dataiSfLoginStatisticsService.updateDataiSfLoginStatistics(dataiSfLoginStatistics));
}
/**
* 删除登录统计
*/
@Operation(summary = "删除登录统计")
@PreAuthorize("@ss.hasPermi('auth:statistics:remove')")
@Log(title = "登录统计", businessType = BusinessType.DELETE)
@DeleteMapping("/{statIds}")
public AjaxResult remove(@PathVariable( name = "statIds" ) Long[] statIds)
{
return toAjax(dataiSfLoginStatisticsService.deleteDataiSfLoginStatisticsByStatIds(statIds));
}
}

View File

@ -0,0 +1,113 @@
package com.datai.auth.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.datai.common.annotation.Log;
import com.datai.common.core.controller.BaseController;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.enums.BusinessType;
import com.datai.auth.domain.DataiSfTokenBinding;
import com.datai.auth.service.IDataiSfTokenBindingService;
import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
/**
* 令牌绑定Controller
*
* @author datai
* @date 2025-12-14
*/
@RestController
@RequestMapping("/auth/binding")
@Tag(name = "【令牌绑定】管理")
public class DataiSfTokenBindingController extends BaseController
{
@Autowired
private IDataiSfTokenBindingService dataiSfTokenBindingService;
/**
* 查询令牌绑定列表
*/
@Operation(summary = "查询令牌绑定列表")
@PreAuthorize("@ss.hasPermi('auth:binding:list')")
@GetMapping("/list")
public TableDataInfo list(DataiSfTokenBinding dataiSfTokenBinding)
{
startPage();
List<DataiSfTokenBinding> list = dataiSfTokenBindingService.selectDataiSfTokenBindingList(dataiSfTokenBinding);
return getDataTable(list);
}
/**
* 导出令牌绑定列表
*/
@Operation(summary = "导出令牌绑定列表")
@PreAuthorize("@ss.hasPermi('auth:binding:export')")
@Log(title = "令牌绑定", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DataiSfTokenBinding dataiSfTokenBinding)
{
List<DataiSfTokenBinding> list = dataiSfTokenBindingService.selectDataiSfTokenBindingList(dataiSfTokenBinding);
ExcelUtil<DataiSfTokenBinding> util = new ExcelUtil<DataiSfTokenBinding>(DataiSfTokenBinding.class);
util.exportExcel(response, list, "令牌绑定数据");
}
/**
* 获取令牌绑定详细信息
*/
@Operation(summary = "获取令牌绑定详细信息")
@PreAuthorize("@ss.hasPermi('auth:binding:query')")
@GetMapping(value = "/{bindingId}")
public AjaxResult getInfo(@PathVariable("bindingId") Long bindingId)
{
return success(dataiSfTokenBindingService.selectDataiSfTokenBindingByBindingId(bindingId));
}
/**
* 新增令牌绑定
*/
@Operation(summary = "新增令牌绑定")
@PreAuthorize("@ss.hasPermi('auth:binding:add')")
@Log(title = "令牌绑定", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DataiSfTokenBinding dataiSfTokenBinding)
{
return toAjax(dataiSfTokenBindingService.insertDataiSfTokenBinding(dataiSfTokenBinding));
}
/**
* 修改令牌绑定
*/
@Operation(summary = "修改令牌绑定")
@PreAuthorize("@ss.hasPermi('auth:binding:edit')")
@Log(title = "令牌绑定", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DataiSfTokenBinding dataiSfTokenBinding)
{
return toAjax(dataiSfTokenBindingService.updateDataiSfTokenBinding(dataiSfTokenBinding));
}
/**
* 删除令牌绑定
*/
@Operation(summary = "删除令牌绑定")
@PreAuthorize("@ss.hasPermi('auth:binding:remove')")
@Log(title = "令牌绑定", businessType = BusinessType.DELETE)
@DeleteMapping("/{bindingIds}")
public AjaxResult remove(@PathVariable( name = "bindingIds" ) Long[] bindingIds)
{
return toAjax(dataiSfTokenBindingService.deleteDataiSfTokenBindingByBindingIds(bindingIds));
}
}

View File

@ -0,0 +1,113 @@
package com.datai.auth.controller;
import java.util.List;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.datai.common.annotation.Log;
import com.datai.common.core.controller.BaseController;
import com.datai.common.core.domain.AjaxResult;
import com.datai.common.enums.BusinessType;
import com.datai.auth.domain.DataiSfToken;
import com.datai.auth.service.IDataiSfTokenService;
import com.datai.common.utils.poi.ExcelUtil;
import com.datai.common.core.page.TableDataInfo;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
/**
* 令牌Controller
*
* @author datai
* @date 2025-12-14
*/
@RestController
@RequestMapping("/auth/token")
@Tag(name = "【令牌】管理")
public class DataiSfTokenController extends BaseController
{
@Autowired
private IDataiSfTokenService dataiSfTokenService;
/**
* 查询令牌列表
*/
@Operation(summary = "查询令牌列表")
@PreAuthorize("@ss.hasPermi('auth:token:list')")
@GetMapping("/list")
public TableDataInfo list(DataiSfToken dataiSfToken)
{
startPage();
List<DataiSfToken> list = dataiSfTokenService.selectDataiSfTokenList(dataiSfToken);
return getDataTable(list);
}
/**
* 导出令牌列表
*/
@Operation(summary = "导出令牌列表")
@PreAuthorize("@ss.hasPermi('auth:token:export')")
@Log(title = "令牌", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, DataiSfToken dataiSfToken)
{
List<DataiSfToken> list = dataiSfTokenService.selectDataiSfTokenList(dataiSfToken);
ExcelUtil<DataiSfToken> util = new ExcelUtil<DataiSfToken>(DataiSfToken.class);
util.exportExcel(response, list, "令牌数据");
}
/**
* 获取令牌详细信息
*/
@Operation(summary = "获取令牌详细信息")
@PreAuthorize("@ss.hasPermi('auth:token:query')")
@GetMapping(value = "/{tokenId}")
public AjaxResult getInfo(@PathVariable("tokenId") Long tokenId)
{
return success(dataiSfTokenService.selectDataiSfTokenByTokenId(tokenId));
}
/**
* 新增令牌
*/
@Operation(summary = "新增令牌")
@PreAuthorize("@ss.hasPermi('auth:token:add')")
@Log(title = "令牌", businessType = BusinessType.INSERT)
@PostMapping
public AjaxResult add(@RequestBody DataiSfToken dataiSfToken)
{
return toAjax(dataiSfTokenService.insertDataiSfToken(dataiSfToken));
}
/**
* 修改令牌
*/
@Operation(summary = "修改令牌")
@PreAuthorize("@ss.hasPermi('auth:token:edit')")
@Log(title = "令牌", businessType = BusinessType.UPDATE)
@PutMapping
public AjaxResult edit(@RequestBody DataiSfToken dataiSfToken)
{
return toAjax(dataiSfTokenService.updateDataiSfToken(dataiSfToken));
}
/**
* 删除令牌
*/
@Operation(summary = "删除令牌")
@PreAuthorize("@ss.hasPermi('auth:token:remove')")
@Log(title = "令牌", businessType = BusinessType.DELETE)
@DeleteMapping("/{tokenIds}")
public AjaxResult remove(@PathVariable( name = "tokenIds" ) Long[] tokenIds)
{
return toAjax(dataiSfTokenService.deleteDataiSfTokenByTokenIds(tokenIds));
}
}

View File

@ -0,0 +1,233 @@
package com.datai.auth.domain;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
* 失败登录对象 datai_sf_failed_login
*
* @author datai
* @date 2025-12-14
*/
@Schema(description = "失败登录对象")
public class DataiSfFailedLogin extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 记录ID */
@Schema(title = "记录ID")
private Long failedId;
/** 租户编号 */
@Schema(title = "租户编号")
@Excel(name = "租户编号")
private String tenantId;
/** 用户名 */
@Schema(title = "用户名")
@Excel(name = "用户名")
private String username;
/** 登录类型 */
@Schema(title = "登录类型")
@Excel(name = "登录类型")
private String loginType;
/** 失败时间 */
@Schema(title = "失败时间")
@Excel(name = "失败时间")
private LocalDate failedTime;
/** 失败原因 */
@Schema(title = "失败原因")
@Excel(name = "失败原因")
private String failedReason;
/** IP地址 */
@Schema(title = "IP地址")
@Excel(name = "IP地址")
private String ipAddress;
/** 设备信息 */
@Schema(title = "设备信息")
@Excel(name = "设备信息")
private String deviceInfo;
/** 锁定状态 */
@Schema(title = "锁定状态")
@Excel(name = "锁定状态")
private String lockStatus;
/** 锁定时间 */
@Schema(title = "锁定时间")
@Excel(name = "锁定时间")
private LocalDate lockTime;
/** 解锁时间 */
@Schema(title = "解锁时间")
@Excel(name = "解锁时间")
private LocalDate unlockTime;
/** 锁定原因 */
@Schema(title = "锁定原因")
@Excel(name = "锁定原因")
private String lockReason;
public void setFailedId(Long failedId)
{
this.failedId = failedId;
}
public Long getFailedId()
{
return failedId;
}
public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}
public String getTenantId()
{
return tenantId;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public void setLoginType(String loginType)
{
this.loginType = loginType;
}
public String getLoginType()
{
return loginType;
}
public void setFailedTime(LocalDate failedTime)
{
this.failedTime = failedTime;
}
public LocalDate getFailedTime()
{
return failedTime;
}
public void setFailedReason(String failedReason)
{
this.failedReason = failedReason;
}
public String getFailedReason()
{
return failedReason;
}
public void setIpAddress(String ipAddress)
{
this.ipAddress = ipAddress;
}
public String getIpAddress()
{
return ipAddress;
}
public void setDeviceInfo(String deviceInfo)
{
this.deviceInfo = deviceInfo;
}
public String getDeviceInfo()
{
return deviceInfo;
}
public void setLockStatus(String lockStatus)
{
this.lockStatus = lockStatus;
}
public String getLockStatus()
{
return lockStatus;
}
public void setLockTime(LocalDate lockTime)
{
this.lockTime = lockTime;
}
public LocalDate getLockTime()
{
return lockTime;
}
public void setUnlockTime(LocalDate unlockTime)
{
this.unlockTime = unlockTime;
}
public LocalDate getUnlockTime()
{
return unlockTime;
}
public void setLockReason(String lockReason)
{
this.lockReason = lockReason;
}
public String getLockReason()
{
return lockReason;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("failedId", getFailedId())
.append("tenantId", getTenantId())
.append("username", getUsername())
.append("loginType", getLoginType())
.append("failedTime", getFailedTime())
.append("failedReason", getFailedReason())
.append("ipAddress", getIpAddress())
.append("deviceInfo", getDeviceInfo())
.append("lockStatus", getLockStatus())
.append("lockTime", getLockTime())
.append("unlockTime", getUnlockTime())
.append("lockReason", getLockReason())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.toString();
}
}

View File

@ -0,0 +1,267 @@
package com.datai.auth.domain;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
* 登录审计日志对象 datai_sf_login_audit
*
* @author datai
* @date 2025-12-14
*/
@Schema(description = "登录审计日志对象")
public class DataiSfLoginAudit extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 日志ID */
@Schema(title = "日志ID")
private Long auditId;
/** 租户编号 */
@Schema(title = "租户编号")
@Excel(name = "租户编号")
private String tenantId;
/** 用户名 */
@Schema(title = "用户名")
@Excel(name = "用户名")
private String username;
/** 操作类型 */
@Schema(title = "操作类型")
@Excel(name = "操作类型")
private String operationType;
/** 操作结果 */
@Schema(title = "操作结果")
@Excel(name = "操作结果")
private String result;
/** 操作时间 */
@Schema(title = "操作时间")
@Excel(name = "操作时间")
private LocalDate operationTime;
/** IP地址 */
@Schema(title = "IP地址")
@Excel(name = "IP地址")
private String ipAddress;
/** 设备信息 */
@Schema(title = "设备信息")
@Excel(name = "设备信息")
private String deviceInfo;
/** 浏览器信息 */
@Schema(title = "浏览器信息")
@Excel(name = "浏览器信息")
private String browserInfo;
/** 登录类型 */
@Schema(title = "登录类型")
@Excel(name = "登录类型")
private String loginType;
/** 错误信息 */
@Schema(title = "错误信息")
@Excel(name = "错误信息")
private String errorMessage;
/** 会话ID */
@Schema(title = "会话ID")
@Excel(name = "会话ID")
private Long sessionId;
/** 令牌ID */
@Schema(title = "令牌ID")
@Excel(name = "令牌ID")
private Long tokenId;
/** 请求ID */
@Schema(title = "请求ID")
@Excel(name = "请求ID")
private String requestId;
public void setAuditId(Long auditId)
{
this.auditId = auditId;
}
public Long getAuditId()
{
return auditId;
}
public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}
public String getTenantId()
{
return tenantId;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public void setOperationType(String operationType)
{
this.operationType = operationType;
}
public String getOperationType()
{
return operationType;
}
public void setResult(String result)
{
this.result = result;
}
public String getResult()
{
return result;
}
public void setOperationTime(LocalDate operationTime)
{
this.operationTime = operationTime;
}
public LocalDate getOperationTime()
{
return operationTime;
}
public void setIpAddress(String ipAddress)
{
this.ipAddress = ipAddress;
}
public String getIpAddress()
{
return ipAddress;
}
public void setDeviceInfo(String deviceInfo)
{
this.deviceInfo = deviceInfo;
}
public String getDeviceInfo()
{
return deviceInfo;
}
public void setBrowserInfo(String browserInfo)
{
this.browserInfo = browserInfo;
}
public String getBrowserInfo()
{
return browserInfo;
}
public void setLoginType(String loginType)
{
this.loginType = loginType;
}
public String getLoginType()
{
return loginType;
}
public void setErrorMessage(String errorMessage)
{
this.errorMessage = errorMessage;
}
public String getErrorMessage()
{
return errorMessage;
}
public void setSessionId(Long sessionId)
{
this.sessionId = sessionId;
}
public Long getSessionId()
{
return sessionId;
}
public void setTokenId(Long tokenId)
{
this.tokenId = tokenId;
}
public Long getTokenId()
{
return tokenId;
}
public void setRequestId(String requestId)
{
this.requestId = requestId;
}
public String getRequestId()
{
return requestId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("auditId", getAuditId())
.append("tenantId", getTenantId())
.append("username", getUsername())
.append("operationType", getOperationType())
.append("result", getResult())
.append("operationTime", getOperationTime())
.append("ipAddress", getIpAddress())
.append("deviceInfo", getDeviceInfo())
.append("browserInfo", getBrowserInfo())
.append("loginType", getLoginType())
.append("errorMessage", getErrorMessage())
.append("sessionId", getSessionId())
.append("tokenId", getTokenId())
.append("requestId", getRequestId())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.toString();
}
}

View File

@ -0,0 +1,252 @@
package com.datai.auth.domain;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
* 登录会话对象 datai_sf_login_session
*
* @author datai
* @date 2025-12-14
*/
@Schema(description = "登录会话对象")
public class DataiSfLoginSession extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 会话ID */
@Schema(title = "会话ID")
private Long sessionId;
/** 租户编号 */
@Schema(title = "租户编号")
@Excel(name = "租户编号")
private String tenantId;
/** 用户名 */
@Schema(title = "用户名")
@Excel(name = "用户名")
private String username;
/** 登录类型 */
@Schema(title = "登录类型")
@Excel(name = "登录类型")
private String loginType;
/** 会话状态 */
@Schema(title = "会话状态")
@Excel(name = "会话状态")
private String status;
/** 登录时间 */
@Schema(title = "登录时间")
@Excel(name = "登录时间")
private LocalDate loginTime;
/** 过期时间 */
@Schema(title = "过期时间")
@Excel(name = "过期时间")
private LocalDate expireTime;
/** 最后活动时间 */
@Schema(title = "最后活动时间")
@Excel(name = "最后活动时间")
private LocalDate lastActivityTime;
/** 登录IP */
@Schema(title = "登录IP")
@Excel(name = "登录IP")
private String loginIp;
/** 设备信息 */
@Schema(title = "设备信息")
@Excel(name = "设备信息")
private String deviceInfo;
/** 浏览器信息 */
@Schema(title = "浏览器信息")
@Excel(name = "浏览器信息")
private String browserInfo;
/** 会话标识 */
@Schema(title = "会话标识")
@Excel(name = "会话标识")
private String sessionToken;
/** 令牌ID */
@Schema(title = "令牌ID")
@Excel(name = "令牌ID")
private Long tokenId;
public void setSessionId(Long sessionId)
{
this.sessionId = sessionId;
}
public Long getSessionId()
{
return sessionId;
}
public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}
public String getTenantId()
{
return tenantId;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public void setLoginType(String loginType)
{
this.loginType = loginType;
}
public String getLoginType()
{
return loginType;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setLoginTime(LocalDate loginTime)
{
this.loginTime = loginTime;
}
public LocalDate getLoginTime()
{
return loginTime;
}
public void setExpireTime(LocalDate expireTime)
{
this.expireTime = expireTime;
}
public LocalDate getExpireTime()
{
return expireTime;
}
public void setLastActivityTime(LocalDate lastActivityTime)
{
this.lastActivityTime = lastActivityTime;
}
public LocalDate getLastActivityTime()
{
return lastActivityTime;
}
public void setLoginIp(String loginIp)
{
this.loginIp = loginIp;
}
public String getLoginIp()
{
return loginIp;
}
public void setDeviceInfo(String deviceInfo)
{
this.deviceInfo = deviceInfo;
}
public String getDeviceInfo()
{
return deviceInfo;
}
public void setBrowserInfo(String browserInfo)
{
this.browserInfo = browserInfo;
}
public String getBrowserInfo()
{
return browserInfo;
}
public void setSessionToken(String sessionToken)
{
this.sessionToken = sessionToken;
}
public String getSessionToken()
{
return sessionToken;
}
public void setTokenId(Long tokenId)
{
this.tokenId = tokenId;
}
public Long getTokenId()
{
return tokenId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("sessionId", getSessionId())
.append("tenantId", getTenantId())
.append("username", getUsername())
.append("loginType", getLoginType())
.append("status", getStatus())
.append("loginTime", getLoginTime())
.append("expireTime", getExpireTime())
.append("lastActivityTime", getLastActivityTime())
.append("loginIp", getLoginIp())
.append("deviceInfo", getDeviceInfo())
.append("browserInfo", getBrowserInfo())
.append("sessionToken", getSessionToken())
.append("tokenId", getTokenId())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -0,0 +1,184 @@
package com.datai.auth.domain;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
* 登录统计对象 datai_sf_login_statistics
*
* @author datai
* @date 2025-12-14
*/
@Schema(description = "登录统计对象")
public class DataiSfLoginStatistics extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 统计ID */
@Schema(title = "统计ID")
private Long statId;
/** 租户编号 */
@Schema(title = "租户编号")
@Excel(name = "租户编号")
private String tenantId;
/** 统计日期 */
@Schema(title = "统计日期")
@Excel(name = "统计日期")
private LocalDate statDate;
/** 统计小时 */
@Schema(title = "统计小时")
@Excel(name = "统计小时")
private Long statHour;
/** 登录类型 */
@Schema(title = "登录类型")
@Excel(name = "登录类型")
private String loginType;
/** 成功次数 */
@Schema(title = "成功次数")
@Excel(name = "成功次数")
private Long successCount;
/** 失败次数 */
@Schema(title = "失败次数")
@Excel(name = "失败次数")
private Long failedCount;
/** 刷新次数 */
@Schema(title = "刷新次数")
@Excel(name = "刷新次数")
private Long refreshCount;
/** 吊销次数 */
@Schema(title = "吊销次数")
@Excel(name = "吊销次数")
private Long revokeCount;
public void setStatId(Long statId)
{
this.statId = statId;
}
public Long getStatId()
{
return statId;
}
public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}
public String getTenantId()
{
return tenantId;
}
public void setStatDate(LocalDate statDate)
{
this.statDate = statDate;
}
public LocalDate getStatDate()
{
return statDate;
}
public void setStatHour(Long statHour)
{
this.statHour = statHour;
}
public Long getStatHour()
{
return statHour;
}
public void setLoginType(String loginType)
{
this.loginType = loginType;
}
public String getLoginType()
{
return loginType;
}
public void setSuccessCount(Long successCount)
{
this.successCount = successCount;
}
public Long getSuccessCount()
{
return successCount;
}
public void setFailedCount(Long failedCount)
{
this.failedCount = failedCount;
}
public Long getFailedCount()
{
return failedCount;
}
public void setRefreshCount(Long refreshCount)
{
this.refreshCount = refreshCount;
}
public Long getRefreshCount()
{
return refreshCount;
}
public void setRevokeCount(Long revokeCount)
{
this.revokeCount = revokeCount;
}
public Long getRevokeCount()
{
return revokeCount;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("statId", getStatId())
.append("tenantId", getTenantId())
.append("statDate", getStatDate())
.append("statHour", getStatHour())
.append("loginType", getLoginType())
.append("successCount", getSuccessCount())
.append("failedCount", getFailedCount())
.append("refreshCount", getRefreshCount())
.append("revokeCount", getRevokeCount())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -0,0 +1,286 @@
package com.datai.auth.domain;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
* 令牌对象 datai_sf_token
*
* @author datai
* @date 2025-12-14
*/
@Schema(description = "令牌对象")
public class DataiSfToken extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 令牌ID */
@Schema(title = "令牌ID")
private Long tokenId;
/** 租户编号 */
@Schema(title = "租户编号")
@Excel(name = "租户编号")
private String tenantId;
/** 用户名 */
@Schema(title = "用户名")
@Excel(name = "用户名")
private String username;
/** 访问令牌 */
@Schema(title = "访问令牌")
@Excel(name = "访问令牌")
private String accessToken;
/** 刷新令牌 */
@Schema(title = "刷新令牌")
@Excel(name = "刷新令牌")
private String refreshToken;
/** 访问令牌过期时间 */
@Schema(title = "访问令牌过期时间")
@Excel(name = "访问令牌过期时间")
private LocalDate accessTokenExpire;
/** 刷新令牌过期时间 */
@Schema(title = "刷新令牌过期时间")
@Excel(name = "刷新令牌过期时间")
private LocalDate refreshTokenExpire;
/** 令牌状态 */
@Schema(title = "令牌状态")
@Excel(name = "令牌状态")
private String status;
/** 实例URL */
@Schema(title = "实例URL")
@Excel(name = "实例URL")
private String instanceUrl;
/** 登录类型 */
@Schema(title = "登录类型")
@Excel(name = "登录类型")
private String loginType;
/** 客户端ID */
@Schema(title = "客户端ID")
@Excel(name = "客户端ID")
private String clientId;
/** 作用域 */
@Schema(title = "作用域")
@Excel(name = "作用域")
private String scope;
/** 令牌类型 */
@Schema(title = "令牌类型")
@Excel(name = "令牌类型")
private String tokenType;
/** 组织ID */
@Schema(title = "组织ID")
@Excel(name = "组织ID")
private String organizationId;
/** 用户ID */
@Schema(title = "用户ID")
@Excel(name = "用户ID")
private String userId;
public void setTokenId(Long tokenId)
{
this.tokenId = tokenId;
}
public Long getTokenId()
{
return tokenId;
}
public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}
public String getTenantId()
{
return tenantId;
}
public void setUsername(String username)
{
this.username = username;
}
public String getUsername()
{
return username;
}
public void setAccessToken(String accessToken)
{
this.accessToken = accessToken;
}
public String getAccessToken()
{
return accessToken;
}
public void setRefreshToken(String refreshToken)
{
this.refreshToken = refreshToken;
}
public String getRefreshToken()
{
return refreshToken;
}
public void setAccessTokenExpire(LocalDate accessTokenExpire)
{
this.accessTokenExpire = accessTokenExpire;
}
public LocalDate getAccessTokenExpire()
{
return accessTokenExpire;
}
public void setRefreshTokenExpire(LocalDate refreshTokenExpire)
{
this.refreshTokenExpire = refreshTokenExpire;
}
public LocalDate getRefreshTokenExpire()
{
return refreshTokenExpire;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setInstanceUrl(String instanceUrl)
{
this.instanceUrl = instanceUrl;
}
public String getInstanceUrl()
{
return instanceUrl;
}
public void setLoginType(String loginType)
{
this.loginType = loginType;
}
public String getLoginType()
{
return loginType;
}
public void setClientId(String clientId)
{
this.clientId = clientId;
}
public String getClientId()
{
return clientId;
}
public void setScope(String scope)
{
this.scope = scope;
}
public String getScope()
{
return scope;
}
public void setTokenType(String tokenType)
{
this.tokenType = tokenType;
}
public String getTokenType()
{
return tokenType;
}
public void setOrganizationId(String organizationId)
{
this.organizationId = organizationId;
}
public String getOrganizationId()
{
return organizationId;
}
public void setUserId(String userId)
{
this.userId = userId;
}
public String getUserId()
{
return userId;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("tokenId", getTokenId())
.append("tenantId", getTenantId())
.append("username", getUsername())
.append("accessToken", getAccessToken())
.append("refreshToken", getRefreshToken())
.append("accessTokenExpire", getAccessTokenExpire())
.append("refreshTokenExpire", getRefreshTokenExpire())
.append("status", getStatus())
.append("instanceUrl", getInstanceUrl())
.append("loginType", getLoginType())
.append("clientId", getClientId())
.append("scope", getScope())
.append("tokenType", getTokenType())
.append("organizationId", getOrganizationId())
.append("userId", getUserId())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -0,0 +1,184 @@
package com.datai.auth.domain;
import java.time.LocalDate;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.v3.oas.annotations.media.Schema;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import com.datai.common.annotation.Excel;
import com.datai.common.core.domain.BaseEntity;
/**
* 令牌绑定对象 datai_sf_token_binding
*
* @author datai
* @date 2025-12-14
*/
@Schema(description = "令牌绑定对象")
public class DataiSfTokenBinding extends BaseEntity
{
private static final long serialVersionUID = 1L;
/** 绑定ID */
@Schema(title = "绑定ID")
private Long bindingId;
/** 租户编号 */
@Schema(title = "租户编号")
@Excel(name = "租户编号")
private String tenantId;
/** 令牌ID */
@Schema(title = "令牌ID")
@Excel(name = "令牌ID")
private Long tokenId;
/** 绑定类型 */
@Schema(title = "绑定类型")
@Excel(name = "绑定类型")
private String bindingType;
/** 设备ID */
@Schema(title = "设备ID")
@Excel(name = "设备ID")
private String deviceId;
/** 绑定IP */
@Schema(title = "绑定IP")
@Excel(name = "绑定IP")
private String bindingIp;
/** 绑定状态 */
@Schema(title = "绑定状态")
@Excel(name = "绑定状态")
private String status;
/** 绑定时间 */
@Schema(title = "绑定时间")
@Excel(name = "绑定时间")
private LocalDate bindingTime;
/** 过期时间 */
@Schema(title = "过期时间")
@Excel(name = "过期时间")
private LocalDate expireTime;
public void setBindingId(Long bindingId)
{
this.bindingId = bindingId;
}
public Long getBindingId()
{
return bindingId;
}
public void setTenantId(String tenantId)
{
this.tenantId = tenantId;
}
public String getTenantId()
{
return tenantId;
}
public void setTokenId(Long tokenId)
{
this.tokenId = tokenId;
}
public Long getTokenId()
{
return tokenId;
}
public void setBindingType(String bindingType)
{
this.bindingType = bindingType;
}
public String getBindingType()
{
return bindingType;
}
public void setDeviceId(String deviceId)
{
this.deviceId = deviceId;
}
public String getDeviceId()
{
return deviceId;
}
public void setBindingIp(String bindingIp)
{
this.bindingIp = bindingIp;
}
public String getBindingIp()
{
return bindingIp;
}
public void setStatus(String status)
{
this.status = status;
}
public String getStatus()
{
return status;
}
public void setBindingTime(LocalDate bindingTime)
{
this.bindingTime = bindingTime;
}
public LocalDate getBindingTime()
{
return bindingTime;
}
public void setExpireTime(LocalDate expireTime)
{
this.expireTime = expireTime;
}
public LocalDate getExpireTime()
{
return expireTime;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("bindingId", getBindingId())
.append("tenantId", getTenantId())
.append("tokenId", getTokenId())
.append("bindingType", getBindingType())
.append("deviceId", getDeviceId())
.append("bindingIp", getBindingIp())
.append("status", getStatus())
.append("bindingTime", getBindingTime())
.append("expireTime", getExpireTime())
.append("createBy", getCreateBy())
.append("createTime", getCreateTime())
.append("updateBy", getUpdateBy())
.append("updateTime", getUpdateTime())
.toString();
}
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.mapper;
import java.util.List;
import com.datai.auth.domain.DataiSfFailedLogin;
/**
* 失败登录Mapper接口
*
* @author datai
* @date 2025-12-14
*/
public interface DataiSfFailedLoginMapper
{
/**
* 查询失败登录
*
* @param failedId 失败登录主键
* @return 失败登录
*/
public DataiSfFailedLogin selectDataiSfFailedLoginByFailedId(Long failedId);
/**
* 查询失败登录列表
*
* @param dataiSfFailedLogin 失败登录
* @return 失败登录集合
*/
public List<DataiSfFailedLogin> selectDataiSfFailedLoginList(DataiSfFailedLogin dataiSfFailedLogin);
/**
* 新增失败登录
*
* @param dataiSfFailedLogin 失败登录
* @return 结果
*/
public int insertDataiSfFailedLogin(DataiSfFailedLogin dataiSfFailedLogin);
/**
* 修改失败登录
*
* @param dataiSfFailedLogin 失败登录
* @return 结果
*/
public int updateDataiSfFailedLogin(DataiSfFailedLogin dataiSfFailedLogin);
/**
* 删除失败登录
*
* @param failedId 失败登录主键
* @return 结果
*/
public int deleteDataiSfFailedLoginByFailedId(Long failedId);
/**
* 批量删除失败登录
*
* @param failedIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDataiSfFailedLoginByFailedIds(Long[] failedIds);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.mapper;
import java.util.List;
import com.datai.auth.domain.DataiSfLoginAudit;
/**
* 登录审计日志Mapper接口
*
* @author datai
* @date 2025-12-14
*/
public interface DataiSfLoginAuditMapper
{
/**
* 查询登录审计日志
*
* @param auditId 登录审计日志主键
* @return 登录审计日志
*/
public DataiSfLoginAudit selectDataiSfLoginAuditByAuditId(Long auditId);
/**
* 查询登录审计日志列表
*
* @param dataiSfLoginAudit 登录审计日志
* @return 登录审计日志集合
*/
public List<DataiSfLoginAudit> selectDataiSfLoginAuditList(DataiSfLoginAudit dataiSfLoginAudit);
/**
* 新增登录审计日志
*
* @param dataiSfLoginAudit 登录审计日志
* @return 结果
*/
public int insertDataiSfLoginAudit(DataiSfLoginAudit dataiSfLoginAudit);
/**
* 修改登录审计日志
*
* @param dataiSfLoginAudit 登录审计日志
* @return 结果
*/
public int updateDataiSfLoginAudit(DataiSfLoginAudit dataiSfLoginAudit);
/**
* 删除登录审计日志
*
* @param auditId 登录审计日志主键
* @return 结果
*/
public int deleteDataiSfLoginAuditByAuditId(Long auditId);
/**
* 批量删除登录审计日志
*
* @param auditIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDataiSfLoginAuditByAuditIds(Long[] auditIds);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.mapper;
import java.util.List;
import com.datai.auth.domain.DataiSfLoginSession;
/**
* 登录会话Mapper接口
*
* @author datai
* @date 2025-12-14
*/
public interface DataiSfLoginSessionMapper
{
/**
* 查询登录会话
*
* @param sessionId 登录会话主键
* @return 登录会话
*/
public DataiSfLoginSession selectDataiSfLoginSessionBySessionId(Long sessionId);
/**
* 查询登录会话列表
*
* @param dataiSfLoginSession 登录会话
* @return 登录会话集合
*/
public List<DataiSfLoginSession> selectDataiSfLoginSessionList(DataiSfLoginSession dataiSfLoginSession);
/**
* 新增登录会话
*
* @param dataiSfLoginSession 登录会话
* @return 结果
*/
public int insertDataiSfLoginSession(DataiSfLoginSession dataiSfLoginSession);
/**
* 修改登录会话
*
* @param dataiSfLoginSession 登录会话
* @return 结果
*/
public int updateDataiSfLoginSession(DataiSfLoginSession dataiSfLoginSession);
/**
* 删除登录会话
*
* @param sessionId 登录会话主键
* @return 结果
*/
public int deleteDataiSfLoginSessionBySessionId(Long sessionId);
/**
* 批量删除登录会话
*
* @param sessionIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDataiSfLoginSessionBySessionIds(Long[] sessionIds);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.mapper;
import java.util.List;
import com.datai.auth.domain.DataiSfLoginStatistics;
/**
* 登录统计Mapper接口
*
* @author datai
* @date 2025-12-14
*/
public interface DataiSfLoginStatisticsMapper
{
/**
* 查询登录统计
*
* @param statId 登录统计主键
* @return 登录统计
*/
public DataiSfLoginStatistics selectDataiSfLoginStatisticsByStatId(Long statId);
/**
* 查询登录统计列表
*
* @param dataiSfLoginStatistics 登录统计
* @return 登录统计集合
*/
public List<DataiSfLoginStatistics> selectDataiSfLoginStatisticsList(DataiSfLoginStatistics dataiSfLoginStatistics);
/**
* 新增登录统计
*
* @param dataiSfLoginStatistics 登录统计
* @return 结果
*/
public int insertDataiSfLoginStatistics(DataiSfLoginStatistics dataiSfLoginStatistics);
/**
* 修改登录统计
*
* @param dataiSfLoginStatistics 登录统计
* @return 结果
*/
public int updateDataiSfLoginStatistics(DataiSfLoginStatistics dataiSfLoginStatistics);
/**
* 删除登录统计
*
* @param statId 登录统计主键
* @return 结果
*/
public int deleteDataiSfLoginStatisticsByStatId(Long statId);
/**
* 批量删除登录统计
*
* @param statIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDataiSfLoginStatisticsByStatIds(Long[] statIds);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.mapper;
import java.util.List;
import com.datai.auth.domain.DataiSfTokenBinding;
/**
* 令牌绑定Mapper接口
*
* @author datai
* @date 2025-12-14
*/
public interface DataiSfTokenBindingMapper
{
/**
* 查询令牌绑定
*
* @param bindingId 令牌绑定主键
* @return 令牌绑定
*/
public DataiSfTokenBinding selectDataiSfTokenBindingByBindingId(Long bindingId);
/**
* 查询令牌绑定列表
*
* @param dataiSfTokenBinding 令牌绑定
* @return 令牌绑定集合
*/
public List<DataiSfTokenBinding> selectDataiSfTokenBindingList(DataiSfTokenBinding dataiSfTokenBinding);
/**
* 新增令牌绑定
*
* @param dataiSfTokenBinding 令牌绑定
* @return 结果
*/
public int insertDataiSfTokenBinding(DataiSfTokenBinding dataiSfTokenBinding);
/**
* 修改令牌绑定
*
* @param dataiSfTokenBinding 令牌绑定
* @return 结果
*/
public int updateDataiSfTokenBinding(DataiSfTokenBinding dataiSfTokenBinding);
/**
* 删除令牌绑定
*
* @param bindingId 令牌绑定主键
* @return 结果
*/
public int deleteDataiSfTokenBindingByBindingId(Long bindingId);
/**
* 批量删除令牌绑定
*
* @param bindingIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDataiSfTokenBindingByBindingIds(Long[] bindingIds);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.mapper;
import java.util.List;
import com.datai.auth.domain.DataiSfToken;
/**
* 令牌Mapper接口
*
* @author datai
* @date 2025-12-14
*/
public interface DataiSfTokenMapper
{
/**
* 查询令牌
*
* @param tokenId 令牌主键
* @return 令牌
*/
public DataiSfToken selectDataiSfTokenByTokenId(Long tokenId);
/**
* 查询令牌列表
*
* @param dataiSfToken 令牌
* @return 令牌集合
*/
public List<DataiSfToken> selectDataiSfTokenList(DataiSfToken dataiSfToken);
/**
* 新增令牌
*
* @param dataiSfToken 令牌
* @return 结果
*/
public int insertDataiSfToken(DataiSfToken dataiSfToken);
/**
* 修改令牌
*
* @param dataiSfToken 令牌
* @return 结果
*/
public int updateDataiSfToken(DataiSfToken dataiSfToken);
/**
* 删除令牌
*
* @param tokenId 令牌主键
* @return 结果
*/
public int deleteDataiSfTokenByTokenId(Long tokenId);
/**
* 批量删除令牌
*
* @param tokenIds 需要删除的数据主键集合
* @return 结果
*/
public int deleteDataiSfTokenByTokenIds(Long[] tokenIds);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.service;
import java.util.List;
import com.datai.auth.domain.DataiSfFailedLogin;
/**
* 失败登录Service接口
*
* @author datai
* @date 2025-12-14
*/
public interface IDataiSfFailedLoginService
{
/**
* 查询失败登录
*
* @param failedId 失败登录主键
* @return 失败登录
*/
public DataiSfFailedLogin selectDataiSfFailedLoginByFailedId(Long failedId);
/**
* 查询失败登录列表
*
* @param dataiSfFailedLogin 失败登录
* @return 失败登录集合
*/
public List<DataiSfFailedLogin> selectDataiSfFailedLoginList(DataiSfFailedLogin dataiSfFailedLogin);
/**
* 新增失败登录
*
* @param dataiSfFailedLogin 失败登录
* @return 结果
*/
public int insertDataiSfFailedLogin(DataiSfFailedLogin dataiSfFailedLogin);
/**
* 修改失败登录
*
* @param dataiSfFailedLogin 失败登录
* @return 结果
*/
public int updateDataiSfFailedLogin(DataiSfFailedLogin dataiSfFailedLogin);
/**
* 批量删除失败登录
*
* @param failedIds 需要删除的失败登录主键集合
* @return 结果
*/
public int deleteDataiSfFailedLoginByFailedIds(Long[] failedIds);
/**
* 删除失败登录信息
*
* @param failedId 失败登录主键
* @return 结果
*/
public int deleteDataiSfFailedLoginByFailedId(Long failedId);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.service;
import java.util.List;
import com.datai.auth.domain.DataiSfLoginAudit;
/**
* 登录审计日志Service接口
*
* @author datai
* @date 2025-12-14
*/
public interface IDataiSfLoginAuditService
{
/**
* 查询登录审计日志
*
* @param auditId 登录审计日志主键
* @return 登录审计日志
*/
public DataiSfLoginAudit selectDataiSfLoginAuditByAuditId(Long auditId);
/**
* 查询登录审计日志列表
*
* @param dataiSfLoginAudit 登录审计日志
* @return 登录审计日志集合
*/
public List<DataiSfLoginAudit> selectDataiSfLoginAuditList(DataiSfLoginAudit dataiSfLoginAudit);
/**
* 新增登录审计日志
*
* @param dataiSfLoginAudit 登录审计日志
* @return 结果
*/
public int insertDataiSfLoginAudit(DataiSfLoginAudit dataiSfLoginAudit);
/**
* 修改登录审计日志
*
* @param dataiSfLoginAudit 登录审计日志
* @return 结果
*/
public int updateDataiSfLoginAudit(DataiSfLoginAudit dataiSfLoginAudit);
/**
* 批量删除登录审计日志
*
* @param auditIds 需要删除的登录审计日志主键集合
* @return 结果
*/
public int deleteDataiSfLoginAuditByAuditIds(Long[] auditIds);
/**
* 删除登录审计日志信息
*
* @param auditId 登录审计日志主键
* @return 结果
*/
public int deleteDataiSfLoginAuditByAuditId(Long auditId);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.service;
import java.util.List;
import com.datai.auth.domain.DataiSfLoginSession;
/**
* 登录会话Service接口
*
* @author datai
* @date 2025-12-14
*/
public interface IDataiSfLoginSessionService
{
/**
* 查询登录会话
*
* @param sessionId 登录会话主键
* @return 登录会话
*/
public DataiSfLoginSession selectDataiSfLoginSessionBySessionId(Long sessionId);
/**
* 查询登录会话列表
*
* @param dataiSfLoginSession 登录会话
* @return 登录会话集合
*/
public List<DataiSfLoginSession> selectDataiSfLoginSessionList(DataiSfLoginSession dataiSfLoginSession);
/**
* 新增登录会话
*
* @param dataiSfLoginSession 登录会话
* @return 结果
*/
public int insertDataiSfLoginSession(DataiSfLoginSession dataiSfLoginSession);
/**
* 修改登录会话
*
* @param dataiSfLoginSession 登录会话
* @return 结果
*/
public int updateDataiSfLoginSession(DataiSfLoginSession dataiSfLoginSession);
/**
* 批量删除登录会话
*
* @param sessionIds 需要删除的登录会话主键集合
* @return 结果
*/
public int deleteDataiSfLoginSessionBySessionIds(Long[] sessionIds);
/**
* 删除登录会话信息
*
* @param sessionId 登录会话主键
* @return 结果
*/
public int deleteDataiSfLoginSessionBySessionId(Long sessionId);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.service;
import java.util.List;
import com.datai.auth.domain.DataiSfLoginStatistics;
/**
* 登录统计Service接口
*
* @author datai
* @date 2025-12-14
*/
public interface IDataiSfLoginStatisticsService
{
/**
* 查询登录统计
*
* @param statId 登录统计主键
* @return 登录统计
*/
public DataiSfLoginStatistics selectDataiSfLoginStatisticsByStatId(Long statId);
/**
* 查询登录统计列表
*
* @param dataiSfLoginStatistics 登录统计
* @return 登录统计集合
*/
public List<DataiSfLoginStatistics> selectDataiSfLoginStatisticsList(DataiSfLoginStatistics dataiSfLoginStatistics);
/**
* 新增登录统计
*
* @param dataiSfLoginStatistics 登录统计
* @return 结果
*/
public int insertDataiSfLoginStatistics(DataiSfLoginStatistics dataiSfLoginStatistics);
/**
* 修改登录统计
*
* @param dataiSfLoginStatistics 登录统计
* @return 结果
*/
public int updateDataiSfLoginStatistics(DataiSfLoginStatistics dataiSfLoginStatistics);
/**
* 批量删除登录统计
*
* @param statIds 需要删除的登录统计主键集合
* @return 结果
*/
public int deleteDataiSfLoginStatisticsByStatIds(Long[] statIds);
/**
* 删除登录统计信息
*
* @param statId 登录统计主键
* @return 结果
*/
public int deleteDataiSfLoginStatisticsByStatId(Long statId);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.service;
import java.util.List;
import com.datai.auth.domain.DataiSfTokenBinding;
/**
* 令牌绑定Service接口
*
* @author datai
* @date 2025-12-14
*/
public interface IDataiSfTokenBindingService
{
/**
* 查询令牌绑定
*
* @param bindingId 令牌绑定主键
* @return 令牌绑定
*/
public DataiSfTokenBinding selectDataiSfTokenBindingByBindingId(Long bindingId);
/**
* 查询令牌绑定列表
*
* @param dataiSfTokenBinding 令牌绑定
* @return 令牌绑定集合
*/
public List<DataiSfTokenBinding> selectDataiSfTokenBindingList(DataiSfTokenBinding dataiSfTokenBinding);
/**
* 新增令牌绑定
*
* @param dataiSfTokenBinding 令牌绑定
* @return 结果
*/
public int insertDataiSfTokenBinding(DataiSfTokenBinding dataiSfTokenBinding);
/**
* 修改令牌绑定
*
* @param dataiSfTokenBinding 令牌绑定
* @return 结果
*/
public int updateDataiSfTokenBinding(DataiSfTokenBinding dataiSfTokenBinding);
/**
* 批量删除令牌绑定
*
* @param bindingIds 需要删除的令牌绑定主键集合
* @return 结果
*/
public int deleteDataiSfTokenBindingByBindingIds(Long[] bindingIds);
/**
* 删除令牌绑定信息
*
* @param bindingId 令牌绑定主键
* @return 结果
*/
public int deleteDataiSfTokenBindingByBindingId(Long bindingId);
}

View File

@ -0,0 +1,61 @@
package com.datai.auth.service;
import java.util.List;
import com.datai.auth.domain.DataiSfToken;
/**
* 令牌Service接口
*
* @author datai
* @date 2025-12-14
*/
public interface IDataiSfTokenService
{
/**
* 查询令牌
*
* @param tokenId 令牌主键
* @return 令牌
*/
public DataiSfToken selectDataiSfTokenByTokenId(Long tokenId);
/**
* 查询令牌列表
*
* @param dataiSfToken 令牌
* @return 令牌集合
*/
public List<DataiSfToken> selectDataiSfTokenList(DataiSfToken dataiSfToken);
/**
* 新增令牌
*
* @param dataiSfToken 令牌
* @return 结果
*/
public int insertDataiSfToken(DataiSfToken dataiSfToken);
/**
* 修改令牌
*
* @param dataiSfToken 令牌
* @return 结果
*/
public int updateDataiSfToken(DataiSfToken dataiSfToken);
/**
* 批量删除令牌
*
* @param tokenIds 需要删除的令牌主键集合
* @return 结果
*/
public int deleteDataiSfTokenByTokenIds(Long[] tokenIds);
/**
* 删除令牌信息
*
* @param tokenId 令牌主键
* @return 结果
*/
public int deleteDataiSfTokenByTokenId(Long tokenId);
}

View File

@ -0,0 +1,107 @@
package com.datai.auth.service.impl;
import java.util.List;
import com.datai.common.core.domain.model.LoginUser;
import com.datai.common.utils.DateUtils;
import com.datai.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.datai.auth.mapper.DataiSfFailedLoginMapper;
import com.datai.auth.domain.DataiSfFailedLogin;
import com.datai.auth.service.IDataiSfFailedLoginService;
/**
* 失败登录Service业务层处理
*
* @author datai
* @date 2025-12-14
*/
@Service
public class DataiSfFailedLoginServiceImpl implements IDataiSfFailedLoginService {
@Autowired
private DataiSfFailedLoginMapper dataiSfFailedLoginMapper;
/**
* 查询失败登录
*
* @param failedId 失败登录主键
* @return 失败登录
*/
@Override
public DataiSfFailedLogin selectDataiSfFailedLoginByFailedId(Long failedId)
{
return dataiSfFailedLoginMapper.selectDataiSfFailedLoginByFailedId(failedId);
}
/**
* 查询失败登录列表
*
* @param dataiSfFailedLogin 失败登录
* @return 失败登录
*/
@Override
public List<DataiSfFailedLogin> selectDataiSfFailedLoginList(DataiSfFailedLogin dataiSfFailedLogin)
{
return dataiSfFailedLoginMapper.selectDataiSfFailedLoginList(dataiSfFailedLogin);
}
/**
* 新增失败登录
*
* @param dataiSfFailedLogin 失败登录
* @return 结果
*/
@Override
public int insertDataiSfFailedLogin(DataiSfFailedLogin dataiSfFailedLogin)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfFailedLogin.setCreateTime(DateUtils.getNowDate());
dataiSfFailedLogin.setUpdateTime(DateUtils.getNowDate());
dataiSfFailedLogin.setCreateBy(username);
dataiSfFailedLogin.setUpdateBy(username);
return dataiSfFailedLoginMapper.insertDataiSfFailedLogin(dataiSfFailedLogin);
}
/**
* 修改失败登录
*
* @param dataiSfFailedLogin 失败登录
* @return 结果
*/
@Override
public int updateDataiSfFailedLogin(DataiSfFailedLogin dataiSfFailedLogin)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
return dataiSfFailedLoginMapper.updateDataiSfFailedLogin(dataiSfFailedLogin);
}
/**
* 批量删除失败登录
*
* @param failedIds 需要删除的失败登录主键
* @return 结果
*/
@Override
public int deleteDataiSfFailedLoginByFailedIds(Long[] failedIds)
{
return dataiSfFailedLoginMapper.deleteDataiSfFailedLoginByFailedIds(failedIds);
}
/**
* 删除失败登录信息
*
* @param failedId 失败登录主键
* @return 结果
*/
@Override
public int deleteDataiSfFailedLoginByFailedId(Long failedId)
{
return dataiSfFailedLoginMapper.deleteDataiSfFailedLoginByFailedId(failedId);
}
}

View File

@ -0,0 +1,107 @@
package com.datai.auth.service.impl;
import java.util.List;
import com.datai.common.core.domain.model.LoginUser;
import com.datai.common.utils.DateUtils;
import com.datai.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.datai.auth.mapper.DataiSfLoginAuditMapper;
import com.datai.auth.domain.DataiSfLoginAudit;
import com.datai.auth.service.IDataiSfLoginAuditService;
/**
* 登录审计日志Service业务层处理
*
* @author datai
* @date 2025-12-14
*/
@Service
public class DataiSfLoginAuditServiceImpl implements IDataiSfLoginAuditService {
@Autowired
private DataiSfLoginAuditMapper dataiSfLoginAuditMapper;
/**
* 查询登录审计日志
*
* @param auditId 登录审计日志主键
* @return 登录审计日志
*/
@Override
public DataiSfLoginAudit selectDataiSfLoginAuditByAuditId(Long auditId)
{
return dataiSfLoginAuditMapper.selectDataiSfLoginAuditByAuditId(auditId);
}
/**
* 查询登录审计日志列表
*
* @param dataiSfLoginAudit 登录审计日志
* @return 登录审计日志
*/
@Override
public List<DataiSfLoginAudit> selectDataiSfLoginAuditList(DataiSfLoginAudit dataiSfLoginAudit)
{
return dataiSfLoginAuditMapper.selectDataiSfLoginAuditList(dataiSfLoginAudit);
}
/**
* 新增登录审计日志
*
* @param dataiSfLoginAudit 登录审计日志
* @return 结果
*/
@Override
public int insertDataiSfLoginAudit(DataiSfLoginAudit dataiSfLoginAudit)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfLoginAudit.setCreateTime(DateUtils.getNowDate());
dataiSfLoginAudit.setUpdateTime(DateUtils.getNowDate());
dataiSfLoginAudit.setCreateBy(username);
dataiSfLoginAudit.setUpdateBy(username);
return dataiSfLoginAuditMapper.insertDataiSfLoginAudit(dataiSfLoginAudit);
}
/**
* 修改登录审计日志
*
* @param dataiSfLoginAudit 登录审计日志
* @return 结果
*/
@Override
public int updateDataiSfLoginAudit(DataiSfLoginAudit dataiSfLoginAudit)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
return dataiSfLoginAuditMapper.updateDataiSfLoginAudit(dataiSfLoginAudit);
}
/**
* 批量删除登录审计日志
*
* @param auditIds 需要删除的登录审计日志主键
* @return 结果
*/
@Override
public int deleteDataiSfLoginAuditByAuditIds(Long[] auditIds)
{
return dataiSfLoginAuditMapper.deleteDataiSfLoginAuditByAuditIds(auditIds);
}
/**
* 删除登录审计日志信息
*
* @param auditId 登录审计日志主键
* @return 结果
*/
@Override
public int deleteDataiSfLoginAuditByAuditId(Long auditId)
{
return dataiSfLoginAuditMapper.deleteDataiSfLoginAuditByAuditId(auditId);
}
}

View File

@ -0,0 +1,109 @@
package com.datai.auth.service.impl;
import java.util.List;
import com.datai.common.core.domain.model.LoginUser;
import com.datai.common.utils.DateUtils;
import com.datai.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.datai.auth.mapper.DataiSfLoginSessionMapper;
import com.datai.auth.domain.DataiSfLoginSession;
import com.datai.auth.service.IDataiSfLoginSessionService;
/**
* 登录会话Service业务层处理
*
* @author datai
* @date 2025-12-14
*/
@Service
public class DataiSfLoginSessionServiceImpl implements IDataiSfLoginSessionService {
@Autowired
private DataiSfLoginSessionMapper dataiSfLoginSessionMapper;
/**
* 查询登录会话
*
* @param sessionId 登录会话主键
* @return 登录会话
*/
@Override
public DataiSfLoginSession selectDataiSfLoginSessionBySessionId(Long sessionId)
{
return dataiSfLoginSessionMapper.selectDataiSfLoginSessionBySessionId(sessionId);
}
/**
* 查询登录会话列表
*
* @param dataiSfLoginSession 登录会话
* @return 登录会话
*/
@Override
public List<DataiSfLoginSession> selectDataiSfLoginSessionList(DataiSfLoginSession dataiSfLoginSession)
{
return dataiSfLoginSessionMapper.selectDataiSfLoginSessionList(dataiSfLoginSession);
}
/**
* 新增登录会话
*
* @param dataiSfLoginSession 登录会话
* @return 结果
*/
@Override
public int insertDataiSfLoginSession(DataiSfLoginSession dataiSfLoginSession)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfLoginSession.setCreateTime(DateUtils.getNowDate());
dataiSfLoginSession.setUpdateTime(DateUtils.getNowDate());
dataiSfLoginSession.setCreateBy(username);
dataiSfLoginSession.setUpdateBy(username);
return dataiSfLoginSessionMapper.insertDataiSfLoginSession(dataiSfLoginSession);
}
/**
* 修改登录会话
*
* @param dataiSfLoginSession 登录会话
* @return 结果
*/
@Override
public int updateDataiSfLoginSession(DataiSfLoginSession dataiSfLoginSession)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfLoginSession.setUpdateTime(DateUtils.getNowDate());
dataiSfLoginSession.setUpdateBy(username);
return dataiSfLoginSessionMapper.updateDataiSfLoginSession(dataiSfLoginSession);
}
/**
* 批量删除登录会话
*
* @param sessionIds 需要删除的登录会话主键
* @return 结果
*/
@Override
public int deleteDataiSfLoginSessionBySessionIds(Long[] sessionIds)
{
return dataiSfLoginSessionMapper.deleteDataiSfLoginSessionBySessionIds(sessionIds);
}
/**
* 删除登录会话信息
*
* @param sessionId 登录会话主键
* @return 结果
*/
@Override
public int deleteDataiSfLoginSessionBySessionId(Long sessionId)
{
return dataiSfLoginSessionMapper.deleteDataiSfLoginSessionBySessionId(sessionId);
}
}

View File

@ -0,0 +1,109 @@
package com.datai.auth.service.impl;
import java.util.List;
import com.datai.common.core.domain.model.LoginUser;
import com.datai.common.utils.DateUtils;
import com.datai.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.datai.auth.mapper.DataiSfLoginStatisticsMapper;
import com.datai.auth.domain.DataiSfLoginStatistics;
import com.datai.auth.service.IDataiSfLoginStatisticsService;
/**
* 登录统计Service业务层处理
*
* @author datai
* @date 2025-12-14
*/
@Service
public class DataiSfLoginStatisticsServiceImpl implements IDataiSfLoginStatisticsService {
@Autowired
private DataiSfLoginStatisticsMapper dataiSfLoginStatisticsMapper;
/**
* 查询登录统计
*
* @param statId 登录统计主键
* @return 登录统计
*/
@Override
public DataiSfLoginStatistics selectDataiSfLoginStatisticsByStatId(Long statId)
{
return dataiSfLoginStatisticsMapper.selectDataiSfLoginStatisticsByStatId(statId);
}
/**
* 查询登录统计列表
*
* @param dataiSfLoginStatistics 登录统计
* @return 登录统计
*/
@Override
public List<DataiSfLoginStatistics> selectDataiSfLoginStatisticsList(DataiSfLoginStatistics dataiSfLoginStatistics)
{
return dataiSfLoginStatisticsMapper.selectDataiSfLoginStatisticsList(dataiSfLoginStatistics);
}
/**
* 新增登录统计
*
* @param dataiSfLoginStatistics 登录统计
* @return 结果
*/
@Override
public int insertDataiSfLoginStatistics(DataiSfLoginStatistics dataiSfLoginStatistics)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfLoginStatistics.setCreateTime(DateUtils.getNowDate());
dataiSfLoginStatistics.setUpdateTime(DateUtils.getNowDate());
dataiSfLoginStatistics.setCreateBy(username);
dataiSfLoginStatistics.setUpdateBy(username);
return dataiSfLoginStatisticsMapper.insertDataiSfLoginStatistics(dataiSfLoginStatistics);
}
/**
* 修改登录统计
*
* @param dataiSfLoginStatistics 登录统计
* @return 结果
*/
@Override
public int updateDataiSfLoginStatistics(DataiSfLoginStatistics dataiSfLoginStatistics)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfLoginStatistics.setUpdateTime(DateUtils.getNowDate());
dataiSfLoginStatistics.setUpdateBy(username);
return dataiSfLoginStatisticsMapper.updateDataiSfLoginStatistics(dataiSfLoginStatistics);
}
/**
* 批量删除登录统计
*
* @param statIds 需要删除的登录统计主键
* @return 结果
*/
@Override
public int deleteDataiSfLoginStatisticsByStatIds(Long[] statIds)
{
return dataiSfLoginStatisticsMapper.deleteDataiSfLoginStatisticsByStatIds(statIds);
}
/**
* 删除登录统计信息
*
* @param statId 登录统计主键
* @return 结果
*/
@Override
public int deleteDataiSfLoginStatisticsByStatId(Long statId)
{
return dataiSfLoginStatisticsMapper.deleteDataiSfLoginStatisticsByStatId(statId);
}
}

View File

@ -0,0 +1,109 @@
package com.datai.auth.service.impl;
import java.util.List;
import com.datai.common.core.domain.model.LoginUser;
import com.datai.common.utils.DateUtils;
import com.datai.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.datai.auth.mapper.DataiSfTokenBindingMapper;
import com.datai.auth.domain.DataiSfTokenBinding;
import com.datai.auth.service.IDataiSfTokenBindingService;
/**
* 令牌绑定Service业务层处理
*
* @author datai
* @date 2025-12-14
*/
@Service
public class DataiSfTokenBindingServiceImpl implements IDataiSfTokenBindingService {
@Autowired
private DataiSfTokenBindingMapper dataiSfTokenBindingMapper;
/**
* 查询令牌绑定
*
* @param bindingId 令牌绑定主键
* @return 令牌绑定
*/
@Override
public DataiSfTokenBinding selectDataiSfTokenBindingByBindingId(Long bindingId)
{
return dataiSfTokenBindingMapper.selectDataiSfTokenBindingByBindingId(bindingId);
}
/**
* 查询令牌绑定列表
*
* @param dataiSfTokenBinding 令牌绑定
* @return 令牌绑定
*/
@Override
public List<DataiSfTokenBinding> selectDataiSfTokenBindingList(DataiSfTokenBinding dataiSfTokenBinding)
{
return dataiSfTokenBindingMapper.selectDataiSfTokenBindingList(dataiSfTokenBinding);
}
/**
* 新增令牌绑定
*
* @param dataiSfTokenBinding 令牌绑定
* @return 结果
*/
@Override
public int insertDataiSfTokenBinding(DataiSfTokenBinding dataiSfTokenBinding)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfTokenBinding.setCreateTime(DateUtils.getNowDate());
dataiSfTokenBinding.setUpdateTime(DateUtils.getNowDate());
dataiSfTokenBinding.setCreateBy(username);
dataiSfTokenBinding.setUpdateBy(username);
return dataiSfTokenBindingMapper.insertDataiSfTokenBinding(dataiSfTokenBinding);
}
/**
* 修改令牌绑定
*
* @param dataiSfTokenBinding 令牌绑定
* @return 结果
*/
@Override
public int updateDataiSfTokenBinding(DataiSfTokenBinding dataiSfTokenBinding)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfTokenBinding.setUpdateTime(DateUtils.getNowDate());
dataiSfTokenBinding.setUpdateBy(username);
return dataiSfTokenBindingMapper.updateDataiSfTokenBinding(dataiSfTokenBinding);
}
/**
* 批量删除令牌绑定
*
* @param bindingIds 需要删除的令牌绑定主键
* @return 结果
*/
@Override
public int deleteDataiSfTokenBindingByBindingIds(Long[] bindingIds)
{
return dataiSfTokenBindingMapper.deleteDataiSfTokenBindingByBindingIds(bindingIds);
}
/**
* 删除令牌绑定信息
*
* @param bindingId 令牌绑定主键
* @return 结果
*/
@Override
public int deleteDataiSfTokenBindingByBindingId(Long bindingId)
{
return dataiSfTokenBindingMapper.deleteDataiSfTokenBindingByBindingId(bindingId);
}
}

View File

@ -0,0 +1,109 @@
package com.datai.auth.service.impl;
import java.util.List;
import com.datai.common.core.domain.model.LoginUser;
import com.datai.common.utils.DateUtils;
import com.datai.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.datai.auth.mapper.DataiSfTokenMapper;
import com.datai.auth.domain.DataiSfToken;
import com.datai.auth.service.IDataiSfTokenService;
/**
* 令牌Service业务层处理
*
* @author datai
* @date 2025-12-14
*/
@Service
public class DataiSfTokenServiceImpl implements IDataiSfTokenService {
@Autowired
private DataiSfTokenMapper dataiSfTokenMapper;
/**
* 查询令牌
*
* @param tokenId 令牌主键
* @return 令牌
*/
@Override
public DataiSfToken selectDataiSfTokenByTokenId(Long tokenId)
{
return dataiSfTokenMapper.selectDataiSfTokenByTokenId(tokenId);
}
/**
* 查询令牌列表
*
* @param dataiSfToken 令牌
* @return 令牌
*/
@Override
public List<DataiSfToken> selectDataiSfTokenList(DataiSfToken dataiSfToken)
{
return dataiSfTokenMapper.selectDataiSfTokenList(dataiSfToken);
}
/**
* 新增令牌
*
* @param dataiSfToken 令牌
* @return 结果
*/
@Override
public int insertDataiSfToken(DataiSfToken dataiSfToken)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfToken.setCreateTime(DateUtils.getNowDate());
dataiSfToken.setUpdateTime(DateUtils.getNowDate());
dataiSfToken.setCreateBy(username);
dataiSfToken.setUpdateBy(username);
return dataiSfTokenMapper.insertDataiSfToken(dataiSfToken);
}
/**
* 修改令牌
*
* @param dataiSfToken 令牌
* @return 结果
*/
@Override
public int updateDataiSfToken(DataiSfToken dataiSfToken)
{
LoginUser loginUser = SecurityUtils.getLoginUser();
String username = loginUser.getUsername();
dataiSfToken.setUpdateTime(DateUtils.getNowDate());
dataiSfToken.setUpdateBy(username);
return dataiSfTokenMapper.updateDataiSfToken(dataiSfToken);
}
/**
* 批量删除令牌
*
* @param tokenIds 需要删除的令牌主键
* @return 结果
*/
@Override
public int deleteDataiSfTokenByTokenIds(Long[] tokenIds)
{
return dataiSfTokenMapper.deleteDataiSfTokenByTokenIds(tokenIds);
}
/**
* 删除令牌信息
*
* @param tokenId 令牌主键
* @return 结果
*/
@Override
public int deleteDataiSfTokenByTokenId(Long tokenId)
{
return dataiSfTokenMapper.deleteDataiSfTokenByTokenId(tokenId);
}
}

View File

@ -0,0 +1,346 @@
# datai-salesforce-auth - Salesforce登录认证模块
## 1. 模块概述
### 1.1 模块定位
负责Salesforce登录认证和令牌管理是所有需要访问Salesforce API的模块的基础。
### 1.2 核心功能与职责
- 支持多种Salesforce登录方式
- 访问令牌和刷新令牌的管理
- 登录状态的保存和获取
- 登录审计日志记录
- 令牌自动刷新机制
- 登录失败锁定机制
- 增强型令牌管理
- 登录会话管理
- 登录统计与报表
### 1.3 设计思路
采用策略模式设计支持多种登录方式的扩展。使用Redis缓存存储登录状态提高访问性能。实现令牌自动刷新机制确保系统持续可用。引入分层架构将控制器、服务层、策略层和数据访问层分离便于维护和扩展。支持事件驱动设计用于处理登录事件。
## 2. 对外提供的接口/方法列表
### 2.1 登录相关接口
| 接口名称 | 方法签名 | 功能描述 | 参数说明 | 返回值 |
|---------|---------|---------|---------|-------|
| 登录接口 | `SalesforceLoginResult login(SalesforceLoginRequest request)` | 根据不同登录类型执行登录 | request登录请求包含登录类型、用户名、密码等信息 | 登录结果包含访问令牌、实例URL等 |
| 刷新令牌接口 | `SalesforceLoginResult refreshToken(String refreshToken, String loginType)` | 刷新访问令牌 | refreshToken刷新令牌<br>loginType登录类型 | 新的登录结果 |
| 登出接口 | `boolean logout(String accessToken, String loginType)` | 执行登出操作 | accessToken访问令牌<br>loginType登录类型 | 登出是否成功 |
| 获取当前登录状态 | `SalesforceLoginResult getCurrentLoginStatus()` | 获取当前登录状态 | 无 | 当前登录状态 |
| 保存登录状态 | `void saveLoginStatus(SalesforceLoginResult result)` | 保存登录状态到缓存 | result登录结果 | 无 |
### 2.2 登录策略相关接口
| 接口名称 | 方法签名 | 功能描述 | 参数说明 | 返回值 |
|---------|---------|---------|---------|-------|
| 获取登录策略 | `LoginStrategy getLoginStrategy(String loginType)` | 根据登录类型获取对应的登录策略 | loginType登录类型 | 登录策略实现 |
| 获取支持的登录类型 | `List<String> getSupportedLoginTypes()` | 获取所有支持的登录类型 | 无 | 支持的登录类型列表 |
### 2.6 令牌管理相关接口
| 接口名称 | 方法签名 | 功能描述 | 参数说明 | 返回值 |
|---------|---------|---------|---------|-------|
| 验证令牌 | `boolean validateToken(String accessToken)` | 验证令牌有效性 | accessToken访问令牌 | 是否有效 |
| 吊销令牌 | `boolean revokeToken(String accessToken)` | 吊销令牌 | accessToken访问令牌 | 是否吊销成功 |
| 绑定令牌 | `void bindToken(String accessToken, String deviceId, String ip)` | 绑定令牌到设备/IP | accessToken访问令牌<br>deviceId设备ID<br>ipIP地址 | 无 |
| 检查令牌绑定 | `boolean checkTokenBinding(String accessToken, String deviceId, String ip)` | 检查令牌绑定 | accessToken访问令牌<br>deviceId设备ID<br>ipIP地址 | 是否绑定匹配 |
## 3. 内部实现的关键逻辑
### 3.1 登录认证流程
1. 客户端调用登录接口,传入登录请求
2. 登录服务进行请求参数验证
3. 登录服务根据登录类型获取对应的登录策略
4. 执行具体的登录策略调用Salesforce API获取令牌
5. 保存登录会话到数据库和Redis缓存
6. 记录登录审计日志
7. 返回登录结果
### 3.2 令牌刷新流程
1. 系统定期检查登录会话的过期时间
2. 当令牌即将过期时,自动调用刷新令牌接口
3. 根据登录类型获取对应的登录策略
4. 执行令牌刷新操作,获取新的访问令牌
5. 更新登录会话的令牌信息
6. 更新Redis缓存中的登录状态
7. 记录令牌刷新日志
### 3.6 关键类说明
#### SalesforceLoginServiceImpl
- 实现登录认证的核心逻辑
- 管理登录策略的调用
- 处理登录状态的保存与获取
- 记录登录审计日志
#### LoginStrategyFactory
- 登录策略工厂,负责根据登录类型创建对应的登录策略
- 支持策略的动态扩展
#### OAuth2LoginStrategy
- 实现OAuth 2.0登录策略
- 支持OAuth 2.0授权码流程、密码流程和客户端凭证流程
#### SalesforceCliLoginStrategy
- 实现Salesforce CLI登录策略
- 支持通过Salesforce CLI获取和使用访问令牌
#### LegacyCredentialLoginStrategy
- 实现传统账密凭证登录策略
- 支持使用用户名、密码和安全令牌进行登录
- 支持SOAP登录方式
#### TokenManager
- 令牌管理器,负责令牌的验证、吊销、绑定等操作
- 支持令牌绑定设备/IP提高安全性
#### SalesforceConfigCacheManager
- 配置缓存管理器用于获取Salesforce API配置
- 支持配置的动态更新
## 4. 与其他模块的依赖关系
### 4.1 依赖其他模块
| 模块名称 | 依赖类型 | 用途 |
|---------|---------|------|
| datai-salesforce-common | 直接依赖 | 提供通用工具类和API客户端 |
| datai-salesforce-config | 直接依赖 | 获取系统配置 |
| datai-common | 直接依赖 | 提供基础框架支持和工具类 |
| Redis缓存服务 | 外部依赖 | 存储登录状态、会话信息和临时数据 |
| 数据库服务 | 外部依赖 | 存储登录审计日志、会话信息 |
| Nimbus JOSE + JWT | 外部依赖 | JWT处理和验证 |
| Spring Security OAuth2 | 外部依赖 | OAuth 2.0支持 |
### 4.2 被其他模块依赖
| 模块名称 | 依赖类型 | 用途 |
|---------|---------|------|
| datai-salesforce-meta | 直接依赖 | 获取Salesforce API访问权限 |
| datai-salesforce-integration | 直接依赖 | 获取Salesforce API访问权限 |
| datai-salesforce-dataloader | 直接依赖 | 获取Salesforce API访问权限 |
| datai-salesforce-apex-lwc | 直接依赖 | 获取Salesforce API访问权限 |
| datai-salesforce-report | 直接依赖 | 获取Salesforce API访问权限 |
## 5. 数据流转路径说明
### 5.1 登录认证数据流转
```
客户端 → 登录控制器 → 登录服务 → 登录策略 → Salesforce API → 登录结果 → 数据库存储 → Redis缓存 → 客户端
```
### 5.2 令牌刷新数据流转
```
系统定时检查 → 登录会话管理 → 刷新令牌服务 → 登录策略 → Salesforce API → 新令牌 → 数据库更新 → Redis缓存更新 → 登录状态更新
```
### 5.3 登出数据流转
```
客户端 → 登出控制器 → 登出服务 → 登录策略 → Salesforce API可选 → Redis缓存清除 → 数据库更新 → 客户端
```
## 6. 性能与安全考量
### 6.1 性能考量
- 使用Redis缓存登录状态、会话信息和临时数据减少数据库访问
- 登录状态缓存支持可配置的过期时间
- 令牌自动刷新机制,避免频繁手动刷新
- 登录策略的懒加载,提高系统启动速度
- 数据库查询优化,使用索引加速查询
### 6.2 安全考量
- 敏感信息在日志中掩码处理
- 登录审计日志记录所有登录操作
- 访问令牌定期刷新,支持令牌吊销
- Redis缓存中的敏感信息加密存储
- 支持多种认证方式,适应不同安全需求
- 令牌绑定设备/IP提高安全性
- 安全的密码策略和密码存储
- 支持强制密码更改和密码过期
- 支持XSS和CSRF防护
- 支持安全的CORS配置
## 7. 典型使用场景
### 7.1 OAuth 2.0登录场景
```java
// 创建登录请求
SalesforceLoginRequest request = new SalesforceLoginRequest();
request.setLoginType("oauth2");
request.setUsername("user@example.com");
request.setPassword("password123");
request.setClientId("clientId");
request.setClientSecret("clientSecret");
request.setGrantType("password"); // 支持authorization_code, password, client_credentials
// 执行登录
SalesforceLoginResult result = salesforceLoginService.login(request);
// 处理登录结果
if (result.isSuccess()) {
// 登录成功,获取访问令牌
String accessToken = result.getAccessToken();
String instanceUrl = result.getInstanceUrl();
// 使用访问令牌调用Salesforce API
} else {
// 登录失败,处理错误信息
String errorMessage = result.getErrorMessage();
}
```
### 7.2 Salesforce CLI登录场景
```java
// 创建登录请求
SalesforceLoginRequest request = new SalesforceLoginRequest();
request.setLoginType("salesforce_cli");
request.setUsername("user@example.com");
request.setOrgAlias("my-sandbox"); // 可选使用已登录的CLI组织别名
// 执行登录
SalesforceLoginResult result = salesforceLoginService.login(request);
// 处理登录结果
if (result.isSuccess()) {
// 登录成功,获取访问令牌
String accessToken = result.getAccessToken();
String instanceUrl = result.getInstanceUrl();
// 使用访问令牌调用Salesforce API
} else {
// 登录失败,处理错误信息
String errorMessage = result.getErrorMessage();
}
```
### 7.3 传统账密凭证登录场景
```java
// 创建登录请求
SalesforceLoginRequest request = new SalesforceLoginRequest();
request.setLoginType("legacy_credential");
request.setUsername("user@example.com");
request.setPassword("password123");
request.setSecurityToken("securityToken123");
// 执行登录
SalesforceLoginResult result = salesforceLoginService.login(request);
// 处理登录结果
if (result.isSuccess()) {
// 登录成功,获取访问令牌
String accessToken = result.getAccessToken();
String instanceUrl = result.getInstanceUrl();
// 使用访问令牌调用Salesforce API
} else {
// 登录失败,处理错误信息
String errorMessage = result.getErrorMessage();
}
```
### 7.4 令牌管理场景
```java
// 验证令牌
boolean isValid = tokenManager.validateToken(accessToken);
if (isValid) {
// 令牌有效,继续处理
}
// 吊销令牌
boolean revoked = tokenManager.revokeToken(accessToken);
if (revoked) {
// 令牌已吊销
}
// 绑定令牌
String deviceId = "device-123";
String ip = "192.168.1.1";
tokenManager.bindToken(accessToken, deviceId, ip);
// 检查令牌绑定
boolean bound = tokenManager.checkTokenBinding(accessToken, deviceId, ip);
if (bound) {
// 令牌绑定匹配
}
```
## 8. 维护指南
### 8.1 常见问题排查
| 问题 | 可能原因 | 解决方案 |
|------|----------|----------|
| 登录失败 | 登录类型不正确 | 检查登录类型是否在支持列表中 |
| 登录失败 | 用户名密码错误 | 检查用户名密码和安全令牌是否正确 |
| 登录失败 | 客户端ID/Secret错误 | 检查OAuth应用配置是否正确 |
| 令牌刷新失败 | 刷新令牌无效 | 重新登录获取新的刷新令牌 |
| 令牌刷新失败 | Salesforce API连接异常 | 检查网络连接和API配置 |
| 登录状态获取失败 | Redis缓存异常 | 检查Redis服务是否正常运行 |
| 登录状态获取失败 | 登录会话已过期 | 重新登录获取新的会话 |
| 登录被锁定 | 登录失败次数过多 | 等待锁定时间过期或手动解锁 |
### 8.2 日志查看
- 登录相关日志:搜索"SalesforceLoginServiceImpl"关键字
- 登录策略相关日志:搜索"LoginStrategy"关键字
- 令牌管理相关日志:搜索"TokenManager"关键字
- 配置相关日志:搜索"SalesforceConfigCacheManager"关键字
- 登录审计日志:搜索"SalesforceLoginAudit"关键字
### 8.3 监控指标
- 登录成功率:监控登录成功与失败的比例
- 令牌刷新成功率:监控令牌刷新成功与失败的比例
- 登录请求频率:监控单位时间内的登录请求次数
- 缓存命中率:监控登录状态和会话缓存的命中率
- 会话平均时长:监控登录会话的平均持续时间
- 登录失败次数:监控登录失败的次数和趋势
- 令牌吊销数量:监控令牌吊销的数量
- API调用成功率监控与Salesforce API的调用成功率
## 9. 扩展点与自定义
### 9.1 添加新的登录方式
1. 创建新的登录策略类实现LoginStrategy接口
2. 在策略类上添加@Component注解
3. 实现login、refreshToken和logout方法
4. 系统自动识别并加载新的登录策略
### 9.5 自定义配置
可以通过配置文件或数据库配置以下参数:
- Salesforce API版本
- 登录超时时间
- 令牌过期时间
- Redis缓存过期时间
- 登录失败锁定配置(锁定时长、解锁方式等)
- 审计日志保留配置
## 10. 版本历史
| 版本 | 发布日期 | 主要变更 |
|------|---------|---------|
| 1.0.0 | 2025-12-11 | 初始版本支持密码登录、JWT登录、客户端凭证登录 |
| 1.1.0 | 2025-12-11 | 增强版本,添加登录失败锁定、增强型令牌管理、登录会话管理、登录统计与报表功能 |
## 11. 联系方式
- 模块负责人:系统重构小组
- 联系邮箱team@example.com
- 文档更新日期2025-12-11

View File

@ -0,0 +1,129 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.datai.auth.mapper.DataiSfFailedLoginMapper">
<resultMap type="DataiSfFailedLogin" id="DataiSfFailedLoginResult">
<result property="failedId" column="failed_id" />
<result property="tenantId" column="tenant_id" />
<result property="username" column="username" />
<result property="loginType" column="login_type" />
<result property="failedTime" column="failed_time" />
<result property="failedReason" column="failed_reason" />
<result property="ipAddress" column="ip_address" />
<result property="deviceInfo" column="device_info" />
<result property="lockStatus" column="lock_status" />
<result property="lockTime" column="lock_time" />
<result property="unlockTime" column="unlock_time" />
<result property="lockReason" column="lock_reason" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
</resultMap>
<sql id="selectDataiSfFailedLoginVo">
select
dsfl.failed_id,
dsfl.tenant_id,
dsfl.username,
dsfl.login_type,
dsfl.failed_time,
dsfl.failed_reason,
dsfl.ip_address,
dsfl.device_info,
dsfl.lock_status,
dsfl.lock_time,
dsfl.unlock_time,
dsfl.lock_reason,
dsfl.create_by,
dsfl.create_time
from datai_sf_failed_login dsfl
</sql>
<select id="selectDataiSfFailedLoginList" parameterType="DataiSfFailedLogin" resultMap="DataiSfFailedLoginResult">
<include refid="selectDataiSfFailedLoginVo"/>
<where>
<if test="tenantId != null and tenantId != ''"> and dsfl.tenant_id = #{tenantId}</if>
<if test="username != null and username != ''"> and dsfl.username like concat('%', #{username}, '%')</if>
<if test="loginType != null and loginType != ''"> and dsfl.login_type = #{loginType}</if>
<if test="failedTime != null "> and dsfl.failed_time = #{failedTime}</if>
<if test="failedReason != null and failedReason != ''"> and dsfl.failed_reason = #{failedReason}</if>
<if test="ipAddress != null and ipAddress != ''"> and dsfl.ip_address = #{ipAddress}</if>
<if test="deviceInfo != null and deviceInfo != ''"> and dsfl.device_info = #{deviceInfo}</if>
<if test="lockStatus != null and lockStatus != ''"> and dsfl.lock_status = #{lockStatus}</if>
<if test="lockTime != null "> and dsfl.lock_time = #{lockTime}</if>
<if test="unlockTime != null "> and dsfl.unlock_time = #{unlockTime}</if>
<if test="lockReason != null and lockReason != ''"> and dsfl.lock_reason = #{lockReason}</if>
</where>
</select>
<select id="selectDataiSfFailedLoginByFailedId" parameterType="Long" resultMap="DataiSfFailedLoginResult">
<include refid="selectDataiSfFailedLoginVo"/>
where dsfl.failed_id = #{failedId}
</select>
<insert id="insertDataiSfFailedLogin" parameterType="DataiSfFailedLogin" useGeneratedKeys="true" keyProperty="failedId">
insert into datai_sf_failed_login
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="tenantId != null">tenant_id,</if>
<if test="username != null">username,</if>
<if test="loginType != null">login_type,</if>
<if test="failedTime != null">failed_time,</if>
<if test="failedReason != null">failed_reason,</if>
<if test="ipAddress != null">ip_address,</if>
<if test="deviceInfo != null">device_info,</if>
<if test="lockStatus != null and lockStatus != ''">lock_status,</if>
<if test="lockTime != null">lock_time,</if>
<if test="unlockTime != null">unlock_time,</if>
<if test="lockReason != null">lock_reason,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tenantId != null">#{tenantId},</if>
<if test="username != null">#{username},</if>
<if test="loginType != null">#{loginType},</if>
<if test="failedTime != null">#{failedTime},</if>
<if test="failedReason != null">#{failedReason},</if>
<if test="ipAddress != null">#{ipAddress},</if>
<if test="deviceInfo != null">#{deviceInfo},</if>
<if test="lockStatus != null and lockStatus != ''">#{lockStatus},</if>
<if test="lockTime != null">#{lockTime},</if>
<if test="unlockTime != null">#{unlockTime},</if>
<if test="lockReason != null">#{lockReason},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
<update id="updateDataiSfFailedLogin" parameterType="DataiSfFailedLogin">
update datai_sf_failed_login
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="username != null">username = #{username},</if>
<if test="loginType != null">login_type = #{loginType},</if>
<if test="failedTime != null">failed_time = #{failedTime},</if>
<if test="failedReason != null">failed_reason = #{failedReason},</if>
<if test="ipAddress != null">ip_address = #{ipAddress},</if>
<if test="deviceInfo != null">device_info = #{deviceInfo},</if>
<if test="lockStatus != null and lockStatus != ''">lock_status = #{lockStatus},</if>
<if test="lockTime != null">lock_time = #{lockTime},</if>
<if test="unlockTime != null">unlock_time = #{unlockTime},</if>
<if test="lockReason != null">lock_reason = #{lockReason},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
</trim>
where datai_sf_failed_login.failed_id = #{failedId}
</update>
<delete id="deleteDataiSfFailedLoginByFailedId" parameterType="Long">
delete from datai_sf_failed_login where failed_id = #{failedId}
</delete>
<delete id="deleteDataiSfFailedLoginByFailedIds" parameterType="String">
delete from datai_sf_failed_login where failed_id in
<foreach item="failedId" collection="array" open="(" separator="," close=")">
#{failedId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.datai.auth.mapper.DataiSfLoginAuditMapper">
<resultMap type="DataiSfLoginAudit" id="DataiSfLoginAuditResult">
<result property="auditId" column="audit_id" />
<result property="tenantId" column="tenant_id" />
<result property="username" column="username" />
<result property="operationType" column="operation_type" />
<result property="result" column="result" />
<result property="operationTime" column="operation_time" />
<result property="ipAddress" column="ip_address" />
<result property="deviceInfo" column="device_info" />
<result property="browserInfo" column="browser_info" />
<result property="loginType" column="login_type" />
<result property="errorMessage" column="error_message" />
<result property="sessionId" column="session_id" />
<result property="tokenId" column="token_id" />
<result property="requestId" column="request_id" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
</resultMap>
<sql id="selectDataiSfLoginAuditVo">
select
dsla.audit_id,
dsla.tenant_id,
dsla.username,
dsla.operation_type,
dsla.result,
dsla.operation_time,
dsla.ip_address,
dsla.device_info,
dsla.browser_info,
dsla.login_type,
dsla.error_message,
dsla.session_id,
dsla.token_id,
dsla.request_id,
dsla.create_by,
dsla.create_time
from datai_sf_login_audit dsla
</sql>
<select id="selectDataiSfLoginAuditList" parameterType="DataiSfLoginAudit" resultMap="DataiSfLoginAuditResult">
<include refid="selectDataiSfLoginAuditVo"/>
<where>
<if test="tenantId != null and tenantId != ''"> and dsla.tenant_id = #{tenantId}</if>
<if test="username != null and username != ''"> and dsla.username like concat('%', #{username}, '%')</if>
<if test="operationType != null and operationType != ''"> and dsla.operation_type = #{operationType}</if>
<if test="result != null and result != ''"> and dsla.result = #{result}</if>
<if test="operationTime != null "> and dsla.operation_time = #{operationTime}</if>
<if test="ipAddress != null and ipAddress != ''"> and dsla.ip_address = #{ipAddress}</if>
<if test="deviceInfo != null and deviceInfo != ''"> and dsla.device_info = #{deviceInfo}</if>
<if test="browserInfo != null and browserInfo != ''"> and dsla.browser_info = #{browserInfo}</if>
<if test="loginType != null and loginType != ''"> and dsla.login_type = #{loginType}</if>
<if test="errorMessage != null and errorMessage != ''"> and dsla.error_message = #{errorMessage}</if>
<if test="sessionId != null "> and dsla.session_id = #{sessionId}</if>
<if test="tokenId != null "> and dsla.token_id = #{tokenId}</if>
<if test="requestId != null and requestId != ''"> and dsla.request_id = #{requestId}</if>
</where>
</select>
<select id="selectDataiSfLoginAuditByAuditId" parameterType="Long" resultMap="DataiSfLoginAuditResult">
<include refid="selectDataiSfLoginAuditVo"/>
where dsla.audit_id = #{auditId}
</select>
<insert id="insertDataiSfLoginAudit" parameterType="DataiSfLoginAudit" useGeneratedKeys="true" keyProperty="auditId">
insert into datai_sf_login_audit
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="tenantId != null">tenant_id,</if>
<if test="username != null">username,</if>
<if test="operationType != null and operationType != ''">operation_type,</if>
<if test="result != null and result != ''">result,</if>
<if test="operationTime != null">operation_time,</if>
<if test="ipAddress != null">ip_address,</if>
<if test="deviceInfo != null">device_info,</if>
<if test="browserInfo != null">browser_info,</if>
<if test="loginType != null">login_type,</if>
<if test="errorMessage != null">error_message,</if>
<if test="sessionId != null">session_id,</if>
<if test="tokenId != null">token_id,</if>
<if test="requestId != null">request_id,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tenantId != null">#{tenantId},</if>
<if test="username != null">#{username},</if>
<if test="operationType != null and operationType != ''">#{operationType},</if>
<if test="result != null and result != ''">#{result},</if>
<if test="operationTime != null">#{operationTime},</if>
<if test="ipAddress != null">#{ipAddress},</if>
<if test="deviceInfo != null">#{deviceInfo},</if>
<if test="browserInfo != null">#{browserInfo},</if>
<if test="loginType != null">#{loginType},</if>
<if test="errorMessage != null">#{errorMessage},</if>
<if test="sessionId != null">#{sessionId},</if>
<if test="tokenId != null">#{tokenId},</if>
<if test="requestId != null">#{requestId},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
</trim>
</insert>
<update id="updateDataiSfLoginAudit" parameterType="DataiSfLoginAudit">
update datai_sf_login_audit
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="username != null">username = #{username},</if>
<if test="operationType != null and operationType != ''">operation_type = #{operationType},</if>
<if test="result != null and result != ''">result = #{result},</if>
<if test="operationTime != null">operation_time = #{operationTime},</if>
<if test="ipAddress != null">ip_address = #{ipAddress},</if>
<if test="deviceInfo != null">device_info = #{deviceInfo},</if>
<if test="browserInfo != null">browser_info = #{browserInfo},</if>
<if test="loginType != null">login_type = #{loginType},</if>
<if test="errorMessage != null">error_message = #{errorMessage},</if>
<if test="sessionId != null">session_id = #{sessionId},</if>
<if test="tokenId != null">token_id = #{tokenId},</if>
<if test="requestId != null">request_id = #{requestId},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
</trim>
where datai_sf_login_audit.audit_id = #{auditId}
</update>
<delete id="deleteDataiSfLoginAuditByAuditId" parameterType="Long">
delete from datai_sf_login_audit where audit_id = #{auditId}
</delete>
<delete id="deleteDataiSfLoginAuditByAuditIds" parameterType="String">
delete from datai_sf_login_audit where audit_id in
<foreach item="auditId" collection="array" open="(" separator="," close=")">
#{auditId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.datai.auth.mapper.DataiSfLoginSessionMapper">
<resultMap type="DataiSfLoginSession" id="DataiSfLoginSessionResult">
<result property="sessionId" column="session_id" />
<result property="tenantId" column="tenant_id" />
<result property="username" column="username" />
<result property="loginType" column="login_type" />
<result property="status" column="status" />
<result property="loginTime" column="login_time" />
<result property="expireTime" column="expire_time" />
<result property="lastActivityTime" column="last_activity_time" />
<result property="loginIp" column="login_ip" />
<result property="deviceInfo" column="device_info" />
<result property="browserInfo" column="browser_info" />
<result property="sessionToken" column="session_token" />
<result property="tokenId" column="token_id" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectDataiSfLoginSessionVo">
select
dsls.session_id,
dsls.tenant_id,
dsls.username,
dsls.login_type,
dsls.status,
dsls.login_time,
dsls.expire_time,
dsls.last_activity_time,
dsls.login_ip,
dsls.device_info,
dsls.browser_info,
dsls.session_token,
dsls.token_id,
dsls.create_by,
dsls.create_time,
dsls.update_by,
dsls.update_time
from datai_sf_login_session dsls
</sql>
<select id="selectDataiSfLoginSessionList" parameterType="DataiSfLoginSession" resultMap="DataiSfLoginSessionResult">
<include refid="selectDataiSfLoginSessionVo"/>
<where>
<if test="tenantId != null and tenantId != ''"> and dsls.tenant_id = #{tenantId}</if>
<if test="username != null and username != ''"> and dsls.username like concat('%', #{username}, '%')</if>
<if test="loginType != null and loginType != ''"> and dsls.login_type = #{loginType}</if>
<if test="status != null and status != ''"> and dsls.status = #{status}</if>
<if test="loginTime != null "> and dsls.login_time = #{loginTime}</if>
<if test="expireTime != null "> and dsls.expire_time = #{expireTime}</if>
<if test="lastActivityTime != null "> and dsls.last_activity_time = #{lastActivityTime}</if>
<if test="loginIp != null and loginIp != ''"> and dsls.login_ip = #{loginIp}</if>
<if test="deviceInfo != null and deviceInfo != ''"> and dsls.device_info = #{deviceInfo}</if>
<if test="browserInfo != null and browserInfo != ''"> and dsls.browser_info = #{browserInfo}</if>
<if test="sessionToken != null and sessionToken != ''"> and dsls.session_token = #{sessionToken}</if>
<if test="tokenId != null "> and dsls.token_id = #{tokenId}</if>
</where>
</select>
<select id="selectDataiSfLoginSessionBySessionId" parameterType="Long" resultMap="DataiSfLoginSessionResult">
<include refid="selectDataiSfLoginSessionVo"/>
where dsls.session_id = #{sessionId}
</select>
<insert id="insertDataiSfLoginSession" parameterType="DataiSfLoginSession" useGeneratedKeys="true" keyProperty="sessionId">
insert into datai_sf_login_session
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="tenantId != null">tenant_id,</if>
<if test="username != null and username != ''">username,</if>
<if test="loginType != null and loginType != ''">login_type,</if>
<if test="status != null and status != ''">status,</if>
<if test="loginTime != null">login_time,</if>
<if test="expireTime != null">expire_time,</if>
<if test="lastActivityTime != null">last_activity_time,</if>
<if test="loginIp != null">login_ip,</if>
<if test="deviceInfo != null">device_info,</if>
<if test="browserInfo != null">browser_info,</if>
<if test="sessionToken != null">session_token,</if>
<if test="tokenId != null">token_id,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tenantId != null">#{tenantId},</if>
<if test="username != null and username != ''">#{username},</if>
<if test="loginType != null and loginType != ''">#{loginType},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="loginTime != null">#{loginTime},</if>
<if test="expireTime != null">#{expireTime},</if>
<if test="lastActivityTime != null">#{lastActivityTime},</if>
<if test="loginIp != null">#{loginIp},</if>
<if test="deviceInfo != null">#{deviceInfo},</if>
<if test="browserInfo != null">#{browserInfo},</if>
<if test="sessionToken != null">#{sessionToken},</if>
<if test="tokenId != null">#{tokenId},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateDataiSfLoginSession" parameterType="DataiSfLoginSession">
update datai_sf_login_session
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="username != null and username != ''">username = #{username},</if>
<if test="loginType != null and loginType != ''">login_type = #{loginType},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="loginTime != null">login_time = #{loginTime},</if>
<if test="expireTime != null">expire_time = #{expireTime},</if>
<if test="lastActivityTime != null">last_activity_time = #{lastActivityTime},</if>
<if test="loginIp != null">login_ip = #{loginIp},</if>
<if test="deviceInfo != null">device_info = #{deviceInfo},</if>
<if test="browserInfo != null">browser_info = #{browserInfo},</if>
<if test="sessionToken != null">session_token = #{sessionToken},</if>
<if test="tokenId != null">token_id = #{tokenId},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where datai_sf_login_session.session_id = #{sessionId}
</update>
<delete id="deleteDataiSfLoginSessionBySessionId" parameterType="Long">
delete from datai_sf_login_session where session_id = #{sessionId}
</delete>
<delete id="deleteDataiSfLoginSessionBySessionIds" parameterType="String">
delete from datai_sf_login_session where session_id in
<foreach item="sessionId" collection="array" open="(" separator="," close=")">
#{sessionId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.datai.auth.mapper.DataiSfLoginStatisticsMapper">
<resultMap type="DataiSfLoginStatistics" id="DataiSfLoginStatisticsResult">
<result property="statId" column="stat_id" />
<result property="tenantId" column="tenant_id" />
<result property="statDate" column="stat_date" />
<result property="statHour" column="stat_hour" />
<result property="loginType" column="login_type" />
<result property="successCount" column="success_count" />
<result property="failedCount" column="failed_count" />
<result property="refreshCount" column="refresh_count" />
<result property="revokeCount" column="revoke_count" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectDataiSfLoginStatisticsVo">
select
dsls.stat_id,
dsls.tenant_id,
dsls.stat_date,
dsls.stat_hour,
dsls.login_type,
dsls.success_count,
dsls.failed_count,
dsls.refresh_count,
dsls.revoke_count,
dsls.create_by,
dsls.create_time,
dsls.update_by,
dsls.update_time
from datai_sf_login_statistics dsls
</sql>
<select id="selectDataiSfLoginStatisticsList" parameterType="DataiSfLoginStatistics" resultMap="DataiSfLoginStatisticsResult">
<include refid="selectDataiSfLoginStatisticsVo"/>
<where>
<if test="tenantId != null and tenantId != ''"> and dsls.tenant_id = #{tenantId}</if>
<if test="statDate != null "> and dsls.stat_date = #{statDate}</if>
<if test="statHour != null "> and dsls.stat_hour = #{statHour}</if>
<if test="loginType != null and loginType != ''"> and dsls.login_type = #{loginType}</if>
<if test="successCount != null "> and dsls.success_count = #{successCount}</if>
<if test="failedCount != null "> and dsls.failed_count = #{failedCount}</if>
<if test="refreshCount != null "> and dsls.refresh_count = #{refreshCount}</if>
<if test="revokeCount != null "> and dsls.revoke_count = #{revokeCount}</if>
</where>
</select>
<select id="selectDataiSfLoginStatisticsByStatId" parameterType="Long" resultMap="DataiSfLoginStatisticsResult">
<include refid="selectDataiSfLoginStatisticsVo"/>
where dsls.stat_id = #{statId}
</select>
<insert id="insertDataiSfLoginStatistics" parameterType="DataiSfLoginStatistics" useGeneratedKeys="true" keyProperty="statId">
insert into datai_sf_login_statistics
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="tenantId != null">tenant_id,</if>
<if test="statDate != null">stat_date,</if>
<if test="statHour != null">stat_hour,</if>
<if test="loginType != null and loginType != ''">login_type,</if>
<if test="successCount != null">success_count,</if>
<if test="failedCount != null">failed_count,</if>
<if test="refreshCount != null">refresh_count,</if>
<if test="revokeCount != null">revoke_count,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tenantId != null">#{tenantId},</if>
<if test="statDate != null">#{statDate},</if>
<if test="statHour != null">#{statHour},</if>
<if test="loginType != null and loginType != ''">#{loginType},</if>
<if test="successCount != null">#{successCount},</if>
<if test="failedCount != null">#{failedCount},</if>
<if test="refreshCount != null">#{refreshCount},</if>
<if test="revokeCount != null">#{revokeCount},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateDataiSfLoginStatistics" parameterType="DataiSfLoginStatistics">
update datai_sf_login_statistics
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="statDate != null">stat_date = #{statDate},</if>
<if test="statHour != null">stat_hour = #{statHour},</if>
<if test="loginType != null and loginType != ''">login_type = #{loginType},</if>
<if test="successCount != null">success_count = #{successCount},</if>
<if test="failedCount != null">failed_count = #{failedCount},</if>
<if test="refreshCount != null">refresh_count = #{refreshCount},</if>
<if test="revokeCount != null">revoke_count = #{revokeCount},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where datai_sf_login_statistics.stat_id = #{statId}
</update>
<delete id="deleteDataiSfLoginStatisticsByStatId" parameterType="Long">
delete from datai_sf_login_statistics where stat_id = #{statId}
</delete>
<delete id="deleteDataiSfLoginStatisticsByStatIds" parameterType="String">
delete from datai_sf_login_statistics where stat_id in
<foreach item="statId" collection="array" open="(" separator="," close=")">
#{statId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,121 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.datai.auth.mapper.DataiSfTokenBindingMapper">
<resultMap type="DataiSfTokenBinding" id="DataiSfTokenBindingResult">
<result property="bindingId" column="binding_id" />
<result property="tenantId" column="tenant_id" />
<result property="tokenId" column="token_id" />
<result property="bindingType" column="binding_type" />
<result property="deviceId" column="device_id" />
<result property="bindingIp" column="binding_ip" />
<result property="status" column="status" />
<result property="bindingTime" column="binding_time" />
<result property="expireTime" column="expire_time" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectDataiSfTokenBindingVo">
select
dstb.binding_id,
dstb.tenant_id,
dstb.token_id,
dstb.binding_type,
dstb.device_id,
dstb.binding_ip,
dstb.status,
dstb.binding_time,
dstb.expire_time,
dstb.create_by,
dstb.create_time,
dstb.update_by,
dstb.update_time
from datai_sf_token_binding dstb
</sql>
<select id="selectDataiSfTokenBindingList" parameterType="DataiSfTokenBinding" resultMap="DataiSfTokenBindingResult">
<include refid="selectDataiSfTokenBindingVo"/>
<where>
<if test="tenantId != null and tenantId != ''"> and dstb.tenant_id = #{tenantId}</if>
<if test="tokenId != null "> and dstb.token_id = #{tokenId}</if>
<if test="bindingType != null and bindingType != ''"> and dstb.binding_type = #{bindingType}</if>
<if test="deviceId != null and deviceId != ''"> and dstb.device_id = #{deviceId}</if>
<if test="bindingIp != null and bindingIp != ''"> and dstb.binding_ip = #{bindingIp}</if>
<if test="status != null and status != ''"> and dstb.status = #{status}</if>
<if test="bindingTime != null "> and dstb.binding_time = #{bindingTime}</if>
<if test="expireTime != null "> and dstb.expire_time = #{expireTime}</if>
</where>
</select>
<select id="selectDataiSfTokenBindingByBindingId" parameterType="Long" resultMap="DataiSfTokenBindingResult">
<include refid="selectDataiSfTokenBindingVo"/>
where dstb.binding_id = #{bindingId}
</select>
<insert id="insertDataiSfTokenBinding" parameterType="DataiSfTokenBinding" useGeneratedKeys="true" keyProperty="bindingId">
insert into datai_sf_token_binding
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="tenantId != null">tenant_id,</if>
<if test="tokenId != null">token_id,</if>
<if test="bindingType != null and bindingType != ''">binding_type,</if>
<if test="deviceId != null">device_id,</if>
<if test="bindingIp != null">binding_ip,</if>
<if test="status != null and status != ''">status,</if>
<if test="bindingTime != null">binding_time,</if>
<if test="expireTime != null">expire_time,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tenantId != null">#{tenantId},</if>
<if test="tokenId != null">#{tokenId},</if>
<if test="bindingType != null and bindingType != ''">#{bindingType},</if>
<if test="deviceId != null">#{deviceId},</if>
<if test="bindingIp != null">#{bindingIp},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="bindingTime != null">#{bindingTime},</if>
<if test="expireTime != null">#{expireTime},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateDataiSfTokenBinding" parameterType="DataiSfTokenBinding">
update datai_sf_token_binding
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="tokenId != null">token_id = #{tokenId},</if>
<if test="bindingType != null and bindingType != ''">binding_type = #{bindingType},</if>
<if test="deviceId != null">device_id = #{deviceId},</if>
<if test="bindingIp != null">binding_ip = #{bindingIp},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="bindingTime != null">binding_time = #{bindingTime},</if>
<if test="expireTime != null">expire_time = #{expireTime},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where datai_sf_token_binding.binding_id = #{bindingId}
</update>
<delete id="deleteDataiSfTokenBindingByBindingId" parameterType="Long">
delete from datai_sf_token_binding where binding_id = #{bindingId}
</delete>
<delete id="deleteDataiSfTokenBindingByBindingIds" parameterType="String">
delete from datai_sf_token_binding where binding_id in
<foreach item="bindingId" collection="array" open="(" separator="," close=")">
#{bindingId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.datai.auth.mapper.DataiSfTokenMapper">
<resultMap type="DataiSfToken" id="DataiSfTokenResult">
<result property="tokenId" column="token_id" />
<result property="tenantId" column="tenant_id" />
<result property="username" column="username" />
<result property="accessToken" column="access_token" />
<result property="refreshToken" column="refresh_token" />
<result property="accessTokenExpire" column="access_token_expire" />
<result property="refreshTokenExpire" column="refresh_token_expire" />
<result property="status" column="status" />
<result property="instanceUrl" column="instance_url" />
<result property="loginType" column="login_type" />
<result property="clientId" column="client_id" />
<result property="scope" column="scope" />
<result property="tokenType" column="token_type" />
<result property="organizationId" column="organization_id" />
<result property="userId" column="user_id" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="updateBy" column="update_by" />
<result property="updateTime" column="update_time" />
</resultMap>
<sql id="selectDataiSfTokenVo">
select
dst.token_id,
dst.tenant_id,
dst.username,
dst.access_token,
dst.refresh_token,
dst.access_token_expire,
dst.refresh_token_expire,
dst.status,
dst.instance_url,
dst.login_type,
dst.client_id,
dst.scope,
dst.token_type,
dst.organization_id,
dst.user_id,
dst.create_by,
dst.create_time,
dst.update_by,
dst.update_time
from datai_sf_token dst
</sql>
<select id="selectDataiSfTokenList" parameterType="DataiSfToken" resultMap="DataiSfTokenResult">
<include refid="selectDataiSfTokenVo"/>
<where>
<if test="tenantId != null and tenantId != ''"> and dst.tenant_id = #{tenantId}</if>
<if test="username != null and username != ''"> and dst.username like concat('%', #{username}, '%')</if>
<if test="accessToken != null and accessToken != ''"> and dst.access_token = #{accessToken}</if>
<if test="refreshToken != null and refreshToken != ''"> and dst.refresh_token = #{refreshToken}</if>
<if test="accessTokenExpire != null "> and dst.access_token_expire = #{accessTokenExpire}</if>
<if test="refreshTokenExpire != null "> and dst.refresh_token_expire = #{refreshTokenExpire}</if>
<if test="status != null and status != ''"> and dst.status = #{status}</if>
<if test="instanceUrl != null and instanceUrl != ''"> and dst.instance_url = #{instanceUrl}</if>
<if test="loginType != null and loginType != ''"> and dst.login_type = #{loginType}</if>
<if test="clientId != null and clientId != ''"> and dst.client_id = #{clientId}</if>
<if test="scope != null and scope != ''"> and dst.scope = #{scope}</if>
<if test="tokenType != null and tokenType != ''"> and dst.token_type = #{tokenType}</if>
<if test="organizationId != null and organizationId != ''"> and dst.organization_id = #{organizationId}</if>
<if test="userId != null and userId != ''"> and dst.user_id = #{userId}</if>
</where>
</select>
<select id="selectDataiSfTokenByTokenId" parameterType="Long" resultMap="DataiSfTokenResult">
<include refid="selectDataiSfTokenVo"/>
where dst.token_id = #{tokenId}
</select>
<insert id="insertDataiSfToken" parameterType="DataiSfToken" useGeneratedKeys="true" keyProperty="tokenId">
insert into datai_sf_token
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="tenantId != null">tenant_id,</if>
<if test="username != null and username != ''">username,</if>
<if test="accessToken != null and accessToken != ''">access_token,</if>
<if test="refreshToken != null">refresh_token,</if>
<if test="accessTokenExpire != null">access_token_expire,</if>
<if test="refreshTokenExpire != null">refresh_token_expire,</if>
<if test="status != null and status != ''">status,</if>
<if test="instanceUrl != null and instanceUrl != ''">instance_url,</if>
<if test="loginType != null and loginType != ''">login_type,</if>
<if test="clientId != null">client_id,</if>
<if test="scope != null">scope,</if>
<if test="tokenType != null">token_type,</if>
<if test="organizationId != null">organization_id,</if>
<if test="userId != null">user_id,</if>
<if test="createBy != null">create_by,</if>
<if test="createTime != null">create_time,</if>
<if test="updateBy != null">update_by,</if>
<if test="updateTime != null">update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="tenantId != null">#{tenantId},</if>
<if test="username != null and username != ''">#{username},</if>
<if test="accessToken != null and accessToken != ''">#{accessToken},</if>
<if test="refreshToken != null">#{refreshToken},</if>
<if test="accessTokenExpire != null">#{accessTokenExpire},</if>
<if test="refreshTokenExpire != null">#{refreshTokenExpire},</if>
<if test="status != null and status != ''">#{status},</if>
<if test="instanceUrl != null and instanceUrl != ''">#{instanceUrl},</if>
<if test="loginType != null and loginType != ''">#{loginType},</if>
<if test="clientId != null">#{clientId},</if>
<if test="scope != null">#{scope},</if>
<if test="tokenType != null">#{tokenType},</if>
<if test="organizationId != null">#{organizationId},</if>
<if test="userId != null">#{userId},</if>
<if test="createBy != null">#{createBy},</if>
<if test="createTime != null">#{createTime},</if>
<if test="updateBy != null">#{updateBy},</if>
<if test="updateTime != null">#{updateTime},</if>
</trim>
</insert>
<update id="updateDataiSfToken" parameterType="DataiSfToken">
update datai_sf_token
<trim prefix="SET" suffixOverrides=",">
<if test="tenantId != null">tenant_id = #{tenantId},</if>
<if test="username != null and username != ''">username = #{username},</if>
<if test="accessToken != null and accessToken != ''">access_token = #{accessToken},</if>
<if test="refreshToken != null">refresh_token = #{refreshToken},</if>
<if test="accessTokenExpire != null">access_token_expire = #{accessTokenExpire},</if>
<if test="refreshTokenExpire != null">refresh_token_expire = #{refreshTokenExpire},</if>
<if test="status != null and status != ''">status = #{status},</if>
<if test="instanceUrl != null and instanceUrl != ''">instance_url = #{instanceUrl},</if>
<if test="loginType != null and loginType != ''">login_type = #{loginType},</if>
<if test="clientId != null">client_id = #{clientId},</if>
<if test="scope != null">scope = #{scope},</if>
<if test="tokenType != null">token_type = #{tokenType},</if>
<if test="organizationId != null">organization_id = #{organizationId},</if>
<if test="userId != null">user_id = #{userId},</if>
<if test="createBy != null">create_by = #{createBy},</if>
<if test="createTime != null">create_time = #{createTime},</if>
<if test="updateBy != null">update_by = #{updateBy},</if>
<if test="updateTime != null">update_time = #{updateTime},</if>
</trim>
where datai_sf_token.token_id = #{tokenId}
</update>
<delete id="deleteDataiSfTokenByTokenId" parameterType="Long">
delete from datai_sf_token where token_id = #{tokenId}
</delete>
<delete id="deleteDataiSfTokenByTokenIds" parameterType="String">
delete from datai_sf_token where token_id in
<foreach item="tokenId" collection="array" open="(" separator="," close=")">
#{tokenId}
</foreach>
</delete>
</mapper>

View File

@ -0,0 +1,346 @@
-- datai-salesforce-auth 模块数据库表结构
-- 该模块负责Salesforce登录认证和令牌管理是所有需要访问Salesforce API的模块的基础
-- -----------------------------
-- 登录会话表 (datai_sf_login_session)
-- -----------------------------
-- 用途:存储登录会话信息,用于会话管理和令牌刷新
-- 设计考虑:
-- 1. 支持多种登录方式
-- 2. 支持会话状态管理
-- 3. 支持令牌自动刷新
-- 4. 支持多租户隔离
CREATE TABLE `datai_sf_login_session` (
-- 会话ID自增主键唯一标识一个登录会话
`session_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '会话ID',
-- 租户编号,支持多租户隔离
`tenant_id` VARCHAR(32) DEFAULT NULL COMMENT '租户编号',
-- 用户名登录用户的Salesforce用户名
`username` VARCHAR(255) NOT NULL COMMENT '用户名',
-- 登录类型如oauth2、salesforce_cli、legacy_credential等
`login_type` VARCHAR(50) NOT NULL COMMENT '登录类型',
-- 会话状态如ACTIVE、EXPIRED、REVOKED、INVALID
`status` VARCHAR(20) NOT NULL COMMENT '会话状态',
-- 登录时间,会话创建时间
`login_time` DATETIME NOT NULL COMMENT '登录时间',
-- 过期时间,会话过期时间
`expire_time` DATETIME NOT NULL COMMENT '过期时间',
-- 最后活动时间,会话最后活跃时间
`last_activity_time` DATETIME NOT NULL COMMENT '最后活动时间',
-- 登录IP地址用户登录时的IP地址
`login_ip` VARCHAR(50) DEFAULT NULL COMMENT '登录IP',
-- 登录设备信息,用户登录时的设备信息
`device_info` VARCHAR(500) DEFAULT NULL COMMENT '设备信息',
-- 浏览器信息,用户登录时的浏览器信息
`browser_info` VARCHAR(500) DEFAULT NULL COMMENT '浏览器信息',
-- 会话标识,用于标识会话的唯一字符串
`session_token` VARCHAR(255) DEFAULT NULL COMMENT '会话标识',
-- 关联的令牌ID关联到令牌表
`token_id` BIGINT(20) DEFAULT NULL COMMENT '令牌ID',
-- 创建人,记录创建会话的用户
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
-- 创建时间,记录会话创建的时间
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
-- 更新人,记录最后更新会话的用户
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
-- 更新时间,记录会话最后更新的时间
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
-- 主键索引,唯一标识会话记录
PRIMARY KEY (`session_id`),
-- 普通索引,加速按用户名查询会话
KEY `idx_username` (`username`),
-- 普通索引,加速按登录类型查询会话
KEY `idx_login_type` (`login_type`),
-- 普通索引,加速按会话状态查询会话
KEY `idx_status` (`status`),
-- 普通索引,加速按过期时间查询会话
KEY `idx_expire_time` (`expire_time`),
-- 普通索引,加速按租户编号查询会话
KEY `idx_tenant_id` (`tenant_id`),
-- 普通索引加速按令牌ID查询会话
KEY `idx_token_id` (`token_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='登录会话表,存储登录会话信息,用于会话管理和令牌刷新';
-- -----------------------------
-- 令牌表 (datai_sf_token)
-- -----------------------------
-- 用途:存储访问令牌和刷新令牌信息,用于令牌管理和验证
-- 设计考虑:
-- 1. 支持访问令牌和刷新令牌的存储
-- 2. 支持令牌状态管理
-- 3. 支持令牌过期时间管理
-- 4. 支持多租户隔离
CREATE TABLE `datai_sf_token` (
-- 令牌ID自增主键唯一标识一个令牌记录
`token_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '令牌ID',
-- 租户编号,支持多租户隔离
`tenant_id` VARCHAR(32) DEFAULT NULL COMMENT '租户编号',
-- 用户名令牌所属用户的Salesforce用户名
`username` VARCHAR(255) NOT NULL COMMENT '用户名',
-- 访问令牌用于访问Salesforce API
`access_token` VARCHAR(1024) NOT NULL COMMENT '访问令牌',
-- 刷新令牌,用于刷新访问令牌
`refresh_token` VARCHAR(1024) DEFAULT NULL COMMENT '刷新令牌',
-- 访问令牌过期时间
`access_token_expire` DATETIME NOT NULL COMMENT '访问令牌过期时间',
-- 刷新令牌过期时间
`refresh_token_expire` DATETIME DEFAULT NULL COMMENT '刷新令牌过期时间',
-- 令牌状态如ACTIVE、EXPIRED、REVOKED、INVALID
`status` VARCHAR(20) NOT NULL COMMENT '令牌状态',
-- 实例URLSalesforce实例URL
`instance_url` VARCHAR(255) NOT NULL COMMENT '实例URL',
-- 登录类型如oauth2、salesforce_cli、legacy_credential等
`login_type` VARCHAR(50) NOT NULL COMMENT '登录类型',
-- 客户端IDOAuth应用的客户端ID
`client_id` VARCHAR(255) DEFAULT NULL COMMENT '客户端ID',
-- 作用域,令牌的作用域
`scope` VARCHAR(255) DEFAULT NULL COMMENT '作用域',
-- 令牌类型如Bearer
`token_type` VARCHAR(50) DEFAULT NULL COMMENT '令牌类型',
-- 组织IDSalesforce组织ID
`organization_id` VARCHAR(50) DEFAULT NULL COMMENT '组织ID',
-- 用户IDSalesforce用户ID
`user_id` VARCHAR(50) DEFAULT NULL COMMENT '用户ID',
-- 创建人,记录创建令牌的用户
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
-- 创建时间,记录令牌创建的时间
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
-- 更新人,记录最后更新令牌的用户
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
-- 更新时间,记录令牌最后更新的时间
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
-- 主键索引,唯一标识令牌记录
PRIMARY KEY (`token_id`),
-- 普通索引,加速按用户名查询令牌
KEY `idx_username` (`username`),
-- 普通索引,加速按访问令牌查询令牌
KEY `idx_access_token` (`access_token`(255)),
-- 普通索引,加速按刷新令牌查询令牌
KEY `idx_refresh_token` (`refresh_token`(255)),
-- 普通索引,加速按令牌状态查询令牌
KEY `idx_status` (`status`),
-- 普通索引,加速按访问令牌过期时间查询令牌
KEY `idx_access_expire` (`access_token_expire`),
-- 普通索引,加速按刷新令牌过期时间查询令牌
KEY `idx_refresh_expire` (`refresh_token_expire`),
-- 普通索引,加速按租户编号查询令牌
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='令牌表,存储访问令牌和刷新令牌信息,用于令牌管理和验证';
-- -----------------------------
-- 登录审计日志表 (datai_sf_login_audit)
-- -----------------------------
-- 用途:记录登录相关操作,用于审计和安全分析
-- 设计考虑:
-- 1. 支持多种操作类型的记录
-- 2. 支持登录结果的记录
-- 3. 支持详细的操作上下文信息
-- 4. 支持多租户隔离
CREATE TABLE `datai_sf_login_audit` (
-- 日志ID自增主键唯一标识一条审计日志
`audit_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '日志ID',
-- 租户编号,支持多租户隔离
`tenant_id` VARCHAR(32) DEFAULT NULL COMMENT '租户编号',
-- 用户名,操作相关的用户名
`username` VARCHAR(255) DEFAULT NULL COMMENT '用户名',
-- 操作类型如LOGIN、LOGOUT、REFRESH_TOKEN、VALIDATE_TOKEN、REVOKE_TOKEN等
`operation_type` VARCHAR(50) NOT NULL COMMENT '操作类型',
-- 操作结果如SUCCESS、FAILED、REJECTED
`result` VARCHAR(20) NOT NULL COMMENT '操作结果',
-- 操作时间,记录操作执行的时间
`operation_time` DATETIME NOT NULL COMMENT '操作时间',
-- 操作IP地址记录执行操作的客户端IP
`ip_address` VARCHAR(50) DEFAULT NULL COMMENT 'IP地址',
-- 设备信息,记录执行操作的设备信息
`device_info` VARCHAR(500) DEFAULT NULL COMMENT '设备信息',
-- 浏览器信息,记录执行操作的浏览器信息
`browser_info` VARCHAR(500) DEFAULT NULL COMMENT '浏览器信息',
-- 登录类型如oauth2、salesforce_cli、legacy_credential等
`login_type` VARCHAR(50) DEFAULT NULL COMMENT '登录类型',
-- 错误信息,记录操作失败时的错误详情
`error_message` TEXT DEFAULT NULL COMMENT '错误信息',
-- 会话ID关联到登录会话表
`session_id` BIGINT(20) DEFAULT NULL COMMENT '会话ID',
-- 令牌ID关联到令牌表
`token_id` BIGINT(20) DEFAULT NULL COMMENT '令牌ID',
-- 请求ID用于关联同一请求的多个操作日志
`request_id` VARCHAR(36) DEFAULT NULL COMMENT '请求ID',
-- 创建人,记录创建日志的用户
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
-- 创建时间,记录日志创建的时间
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
-- 主键索引,唯一标识审计日志记录
PRIMARY KEY (`audit_id`),
-- 普通索引,加速按用户名查询审计日志
KEY `idx_username` (`username`),
-- 普通索引,加速按操作类型查询审计日志
KEY `idx_operation_type` (`operation_type`),
-- 普通索引,加速按操作结果查询审计日志
KEY `idx_result` (`result`),
-- 普通索引,加速按操作时间查询审计日志
KEY `idx_operation_time` (`operation_time`),
-- 普通索引,加速按登录类型查询审计日志
KEY `idx_login_type` (`login_type`),
-- 普通索引,加速按租户编号查询审计日志
KEY `idx_tenant_id` (`tenant_id`),
-- 普通索引加速按会话ID查询审计日志
KEY `idx_session_id` (`session_id`),
-- 普通索引加速按令牌ID查询审计日志
KEY `idx_token_id` (`token_id`),
-- 普通索引加速按请求ID查询审计日志
KEY `idx_request_id` (`request_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='登录审计日志表,记录登录相关操作,用于审计和安全分析';
-- -----------------------------
-- 令牌绑定表 (datai_sf_token_binding)
-- -----------------------------
-- 用途:记录令牌与设备/IP的绑定关系用于提高安全性
-- 设计考虑:
-- 1. 支持令牌与设备的绑定
-- 2. 支持令牌与IP的绑定
-- 3. 支持绑定状态管理
-- 4. 支持多租户隔离
CREATE TABLE `datai_sf_token_binding` (
-- 绑定ID自增主键唯一标识一个令牌绑定
`binding_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '绑定ID',
-- 租户编号,支持多租户隔离
`tenant_id` VARCHAR(32) DEFAULT NULL COMMENT '租户编号',
-- 令牌ID关联到令牌表
`token_id` BIGINT(20) NOT NULL COMMENT '令牌ID',
-- 绑定类型如DEVICE、IP、DEVICE_IP
`binding_type` VARCHAR(20) NOT NULL COMMENT '绑定类型',
-- 设备ID令牌绑定的设备标识
`device_id` VARCHAR(255) DEFAULT NULL COMMENT '设备ID',
-- 绑定IP地址令牌绑定的IP地址
`binding_ip` VARCHAR(50) DEFAULT NULL COMMENT '绑定IP',
-- 绑定状态如ACTIVE、EXPIRED、REVOKED
`status` VARCHAR(20) NOT NULL COMMENT '绑定状态',
-- 绑定时间,记录令牌绑定的时间
`binding_time` DATETIME NOT NULL COMMENT '绑定时间',
-- 过期时间,记录令牌绑定的过期时间
`expire_time` DATETIME DEFAULT NULL COMMENT '过期时间',
-- 创建人,记录创建令牌绑定的用户
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
-- 创建时间,记录令牌绑定创建的时间
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
-- 更新人,记录最后更新令牌绑定的用户
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
-- 更新时间,记录令牌绑定最后更新的时间
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
-- 主键索引,唯一标识令牌绑定记录
PRIMARY KEY (`binding_id`),
-- 普通索引加速按令牌ID查询令牌绑定
KEY `idx_token_id` (`token_id`),
-- 普通索引,加速按绑定类型查询令牌绑定
KEY `idx_binding_type` (`binding_type`),
-- 普通索引加速按设备ID查询令牌绑定
KEY `idx_device_id` (`device_id`),
-- 普通索引加速按绑定IP查询令牌绑定
KEY `idx_binding_ip` (`binding_ip`),
-- 普通索引,加速按绑定状态查询令牌绑定
KEY `idx_status` (`status`),
-- 普通索引,加速按租户编号查询令牌绑定
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='令牌绑定表,记录令牌与设备/IP的绑定关系用于提高安全性';
-- -----------------------------
-- 失败登录表 (datai_sf_failed_login)
-- -----------------------------
-- 用途:记录登录失败尝试,用于登录锁定和风险检测
-- 设计考虑:
-- 1. 支持记录登录失败原因
-- 2. 支持按用户名和IP统计失败次数
-- 3. 支持登录锁定机制
-- 4. 支持多租户隔离
CREATE TABLE `datai_sf_failed_login` (
-- 记录ID自增主键唯一标识一条失败登录记录
`failed_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '记录ID',
-- 租户编号,支持多租户隔离
`tenant_id` VARCHAR(32) DEFAULT NULL COMMENT '租户编号',
-- 用户名,登录失败的用户名
`username` VARCHAR(255) DEFAULT NULL COMMENT '用户名',
-- 登录类型如password、jwt、client_credentials等
`login_type` VARCHAR(50) DEFAULT NULL COMMENT '登录类型',
-- 失败时间,记录登录失败的时间
`failed_time` DATETIME NOT NULL COMMENT '失败时间',
-- 失败原因,说明登录失败的具体原因
`failed_reason` TEXT DEFAULT NULL COMMENT '失败原因',
-- 操作IP地址记录登录失败的IP地址
`ip_address` VARCHAR(50) DEFAULT NULL COMMENT 'IP地址',
-- 设备信息,记录登录失败的设备信息
`device_info` VARCHAR(500) DEFAULT NULL COMMENT '设备信息',
-- 锁定状态如LOCKED、UNLOCKED
`lock_status` VARCHAR(20) NOT NULL DEFAULT 'UNLOCKED' COMMENT '锁定状态',
-- 锁定时间,记录登录锁定的时间
`lock_time` DATETIME DEFAULT NULL COMMENT '锁定时间',
-- 解锁时间,记录登录解锁的时间
`unlock_time` DATETIME DEFAULT NULL COMMENT '解锁时间',
-- 锁定原因,说明登录锁定的原因
`lock_reason` TEXT DEFAULT NULL COMMENT '锁定原因',
-- 创建人,记录创建失败登录记录的用户
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
-- 创建时间,记录失败登录记录创建的时间
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
-- 主键索引,唯一标识失败登录记录
PRIMARY KEY (`failed_id`),
-- 普通索引,加速按用户名查询失败登录记录
KEY `idx_username` (`username`),
-- 普通索引加速按IP地址查询失败登录记录
KEY `idx_ip_address` (`ip_address`),
-- 普通索引,加速按失败时间查询失败登录记录
KEY `idx_failed_time` (`failed_time`),
-- 普通索引,加速按锁定状态查询失败登录记录
KEY `idx_lock_status` (`lock_status`),
-- 普通索引,加速按租户编号查询失败登录记录
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='失败登录表,记录登录失败尝试,用于登录锁定和风险检测';
-- -----------------------------
-- 登录统计表 (datai_sf_login_statistics)
-- -----------------------------
-- 用途:记录登录统计信息,用于生成报表和分析
-- 设计考虑:
-- 1. 支持按时间维度统计
-- 2. 支持按登录类型统计
-- 3. 支持按成功/失败状态统计
-- 4. 支持多租户隔离
CREATE TABLE `datai_sf_login_statistics` (
-- 统计ID自增主键唯一标识一条统计记录
`stat_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '统计ID',
-- 租户编号,支持多租户隔离
`tenant_id` VARCHAR(32) DEFAULT NULL COMMENT '租户编号',
-- 统计日期,统计数据的日期
`stat_date` DATE NOT NULL COMMENT '统计日期',
-- 统计小时统计数据的小时0-23用于小时级统计
`stat_hour` INT(11) DEFAULT NULL COMMENT '统计小时',
-- 登录类型如oauth2、salesforce_cli、legacy_credential等
`login_type` VARCHAR(50) NOT NULL COMMENT '登录类型',
-- 成功登录次数
`success_count` INT(11) NOT NULL DEFAULT 0 COMMENT '成功次数',
-- 失败登录次数
`failed_count` INT(11) NOT NULL DEFAULT 0 COMMENT '失败次数',
-- 令牌刷新次数
`refresh_count` INT(11) NOT NULL DEFAULT 0 COMMENT '刷新次数',
-- 令牌吊销次数
`revoke_count` INT(11) NOT NULL DEFAULT 0 COMMENT '吊销次数',
-- 创建人,记录创建统计记录的用户
`create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建人',
-- 创建时间,记录统计记录创建的时间
`create_time` DATETIME DEFAULT NULL COMMENT '创建时间',
-- 更新人,记录最后更新统计记录的用户
`update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新人',
-- 更新时间,记录统计记录最后更新的时间
`update_time` DATETIME DEFAULT NULL COMMENT '更新时间',
-- 主键索引,唯一标识统计记录
PRIMARY KEY (`stat_id`),
-- 唯一约束,确保每个统计维度只有一条记录
UNIQUE KEY `uk_stat_dimension` (`tenant_id`,`stat_date`,`stat_hour`,`login_type`),
-- 普通索引,加速按统计日期查询统计记录
KEY `idx_stat_date` (`stat_date`),
-- 普通索引,加速按统计小时查询统计记录
KEY `idx_stat_hour` (`stat_hour`),
-- 普通索引,加速按登录类型查询统计记录
KEY `idx_login_type` (`login_type`),
-- 普通索引,加速按租户编号查询统计记录
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='登录统计表,记录登录统计信息,用于生成报表和分析';

View File

@ -26,6 +26,10 @@
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-config</artifactId>
</dependency>
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-auth</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -19,6 +19,7 @@
<module>datai-salesforce-common</module>
<module>datai-salesforce-config</module>
<module>datai-salesforce-starter</module>
<module>datai-salesforce-auth</module>
</modules>
<dependencyManagement>
@ -33,6 +34,11 @@
<artifactId>datai-salesforce-config</artifactId>
<version>${datai.version}</version>
</dependency>
<dependency>
<groupId>com.datai</groupId>
<artifactId>datai-salesforce-auth</artifactId>
<version>${datai.version}</version>
</dependency>
</dependencies>
</dependencyManagement>