新增授权码创建功能

This commit is contained in:
wangli 2026-01-01 00:00:22 +08:00
parent 438e0e7d98
commit c735ffae5e
3 changed files with 82 additions and 17 deletions

View File

@ -107,6 +107,21 @@ public class AdminController {
}
}
/**
* 获取安全认证码
* 仅管理员可访问
*
* @return 包含安全认证码的Map对象
*/
@GetMapping("/secure-auth")
@ResponseBody
@SaCheckRole("admin")
public Map<String, String> getSecureAuth() {
Map<String, String> result = new HashMap<>();
result.put("secureAuth", secureAuth);
return result;
}
/**
* 生成授权码
* 验证安全认证码后生成一个新的登录授权码
@ -117,22 +132,26 @@ public class AdminController {
@PostMapping("/generate-code")
@ResponseBody
public String generateCode(@RequestBody GenerateCodeRequest request) {
if (StringUtils.hasText(request.getAuthCode()) && Objects.equals(request.getAuthCode(), secureAuth)) {
String orderNo = request.getOrderNo();
Integer loginLimit = request.getLoginLimit();
Long expireSeconds = request.getExpireSeconds();
long expireTime = System.currentTimeMillis() + (Objects.isNull(expireSeconds) ? 12 * 60 * 60 * 1000 : expireSeconds);
AES aes = SecureUtil.aes(secureKey.getBytes(StandardCharsets.UTF_8));
String loginCode = aes.encryptHex(String.valueOf(expireTime));
LocalDateTime now = LocalDateTime.now();
LocalDateTime expiresAt = now.plusSeconds(expireSeconds);
String sql = "INSERT INTO auth_codes (code, order_no, login_limit, created_at, expires_at, status) VALUES (?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(sql, loginCode, orderNo, loginLimit, formatter.format(now), formatter.format(expiresAt), 1);
return loginCode;
if (!StringUtils.hasText(request.getAuthCode()) || !Objects.equals(request.getAuthCode(), secureAuth)) {
Map<String, String> result = new HashMap<>();
result.put("code", "403");
result.put("message", "Invalid auth code");
return JSONUtil.toJsonStr(result);
}
String orderNo = request.getOrderNo();
Integer loginLimit = request.getLoginLimit();
Long expireSeconds = request.getExpireSeconds();
long expireTime = System.currentTimeMillis() + (Objects.isNull(expireSeconds) ? 12 * 60 * 60 * 1000 : expireSeconds * 1000);
AES aes = SecureUtil.aes(secureKey.getBytes(StandardCharsets.UTF_8));
String loginCode = aes.encryptHex(String.valueOf(expireTime));
LocalDateTime now = LocalDateTime.now();
LocalDateTime expiresAt = now.plusSeconds(expireSeconds);
String sql = "INSERT INTO auth_codes (code, order_no, login_limit, created_at, expires_at, status) VALUES (?, ?, ?, ?, ?, ?)";
jdbcTemplate.update(sql, loginCode, orderNo, loginLimit, formatter.format(now), formatter.format(expiresAt), 1);
Map<String, String> result = new HashMap<>();
result.put("code", "400");
result.put("msg", "illegal access");
result.put("code", loginCode);
return JSONUtil.toJsonStr(result);
}

View File

@ -28,7 +28,8 @@ public class ThumbnailService {
@Value("${file.path}")
private String rootPath;
private final ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
// 使用固定大小的线程池限制并发数量以避免内存溢出
private final ExecutorService executor = Executors.newFixedThreadPool(2);
/**
* 扫描并生成缩略图

View File

@ -43,6 +43,12 @@
box-shadow: var(--card-shadow);
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
h1 { margin-top: 0; color: #333; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; background: #fff; border-radius: 8px; overflow: hidden; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #ddd; }
@ -53,6 +59,8 @@
.btn { padding: 6px 12px; border: none; border-radius: 4px; cursor: pointer; color: #fff; font-size: 14px; }
.btn-save { background-color: #28a745; }
.btn-save:hover { background-color: #218838; }
.btn-add { background-color: #007bff; }
.btn-add:hover { background-color: #0056b3; }
.pagination { margin-top: 20px; display: flex; justify-content: center; gap: 10px; }
.page-btn { padding: 8px 12px; border: 1px solid #ddd; background: #fff; cursor: pointer; border-radius: 4px; }
.page-btn.active { background-color: #007bff; color: #fff; border-color: #007bff; }
@ -65,7 +73,10 @@
<div class="container">
<a href="/admin" class="back-link">&larr; 返回后台首页</a>
<h1>授权码管理</h1>
<div class="header">
<h1>授权码管理</h1>
<button class="btn btn-add" onclick="addAuthCode()">新增授权码</button>
</div>
<table>
<thead>
@ -89,6 +100,7 @@
<script>
let currentPage = 1;
const pageSize = 10;
let secureAuth = '';
async function loadData(page) {
currentPage = page;
@ -183,7 +195,40 @@
}
}
document.addEventListener('DOMContentLoaded', () => {
async function addAuthCode() {
const orderNo = 'manual-' + Math.random().toString(36).substring(2, 10);
try {
const response = await fetch('/api/admin/generate-code', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
orderNo: orderNo,
loginLimit: 1,
expireSeconds: 86400, // 24 hours
authCode: secureAuth
})
});
const result = await response.json();
if (result.code) {
alert('新增成功,授权码: ' + result.code);
loadData(1); // Reload to show the new code
} else {
alert('新增失败: ' + (result.message || '未知错误'));
}
} catch (e) {
alert('网络错误');
}
}
document.addEventListener('DOMContentLoaded', async () => {
try {
const response = await fetch('/api/admin/secure-auth');
const data = await response.json();
secureAuth = data.secureAuth;
} catch (e) {
console.error('Failed to fetch secure auth:', e);
}
loadData(1);
particlesJS('particles-js', {
"particles": {