Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,29 @@ build/

### VS Code ###
.vscode/

### MioVerify 特定文件 ###
# 数据库文件
*.db
*.sqlite
*.sqlite3

# 日志文件
logs/
*.log

# 密钥文件
keys/
*.pem
*.key

# 材质文件
textures/

# 系统文件
.DS_Store
Thumbs.db

# 临时文件
*.tmp
*.temp
223 changes: 223 additions & 0 deletions IMPLEMENTATION_SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
# MioVerify 功能实现总结

本文档总结了为 MioVerify 项目实现的四个主要功能。

## 1. 密码密文存储 ✅

### 实现内容
- **密码加密工具类**: `PasswordUtil.java`
- 使用 BCrypt 算法加密密码
- 支持密码验证
- 兼容旧的明文密码(渐进式迁移)

- **用户服务更新**: `UserServiceImpl.java`
- 登录时支持加密密码验证
- 向后兼容明文密码
- 自动识别密码格式

- **注册流程更新**: `ExternController.java`
- 新用户注册时自动加密密码
- 集成密码加密工具

### 安全特性
- BCrypt 算法,安全性高
- 渐进式迁移,不影响现有用户
- 密码强度验证支持

## 2. 动态材质资源来源 ✅

### 实现内容
- **材质源服务接口**: `TextureSourceService.java`
- 统一的材质操作接口
- 支持多种材质源类型

- **本地材质源**: `LocalTextureSourceImpl.java`
- 传统文件系统存储
- 完全向后兼容

- **HTTP材质源**: `HttpTextureSourceImpl.java`
- 远程HTTP材质获取
- Redis缓存支持
- 超时和错误处理

- **材质源管理器**: `TextureSourceManager.java`
- 主要源和备用源支持
- 自动故障转移
- 配置化材质源选择

### 配置选项
```yaml
mioverify:
texture:
sources:
primary: local # 主要材质源
local:
enabled: true
base-path: textures
http:
enabled: false
base-url: https://example.com/textures
cache-enabled: true
cache-duration: 1h
```

## 3. 后台管理界面 ✅

### 实现内容
- **管理员实体**: `AdminUser.java`
- 管理员账户信息
- 角色和权限管理

- **管理员服务**: `AdminService.java` & `AdminServiceImpl.java`
- 管理员登录验证
- 系统统计信息
- 用户和角色管理

- **管理控制器**: `AdminController.java`
- 登录/登出功能
- 仪表板页面
- 用户和角色管理API

- **Web界面**:
- 登录页面: `templates/admin/login.html`
- 仪表板: `templates/admin/dashboard.html`
- 响应式设计,现代化UI

### 功能特性
- 安全的会话管理
- 系统统计信息展示
- 用户和角色管理
- 批量操作支持

### 访问方式
- 默认管理员账号: `admin`
- 默认密码: `admin123`
- 访问地址: `http://localhost:8080/admin/login`

## 4. API地址指示(ALI) ✅

### 实现内容
- **API元数据实体**: `ApiMetadata.java`
- 完整的API信息结构
- 客户端配置信息

- **API文档工具**: `ApiDocumentationUtil.java`
- 自动生成API文档
- 动态特性检测
- 客户端配置生成

- **元数据控制器**: `MetaController.java`
- `/meta` - Yggdrasil兼容的服务器元数据
- `/meta/api` - 完整API元数据
- `/meta/endpoints` - API端点列表
- `/meta/client-config` - 客户端配置
- `/meta/features` - 服务器特性
- `/meta/docs` - 人类可读的API文档

### API端点
- **服务器元数据**: `GET /meta`
- **API文档**: `GET /meta/api`
- **端点列表**: `GET /meta/endpoints`
- **客户端配置**: `GET /meta/client-config`
- **特性列表**: `GET /meta/features`
- **HTML文档**: `GET /meta/docs`

## 技术栈更新

### 新增依赖
- Spring Security (密码加密)
- Thymeleaf (模板引擎)

### 数据库更新
- 新增 `admin_users` 表
- 支持管理员账户存储

## 配置更新

### 新增配置项
```yaml
mioverify:
# 管理员配置
admin:
enabled: true
default-username: admin
default-password: admin123
base-path: /admin
session-timeout: 30m

# 材质源配置
texture:
sources:
primary: local
local:
enabled: true
http:
enabled: false
base-url: https://example.com/textures
cache-enabled: true
```

## 部署说明

### 前置要求
1. **Java 17+**: 确保使用Java 17或更高版本
2. **Redis服务**: 必须启动Redis服务器(默认端口6379)
3. **数据库**: SQLite(默认)或MySQL

### 部署步骤
1. **启动Redis服务**:
```bash
# Windows (如果安装了Redis)
redis-server

# 或使用Docker
docker run -d -p 6379:6379 redis:alpine
```

2. **数据库迁移**: 运行更新的 `schema.sql`
3. **配置更新**: 更新 `application.yml` 配置
4. **编译项目**:
```bash
mvn clean compile
```
5. **启动应用**:
```bash
mvn spring-boot:run
```
6. **管理员初始化**: 首次启动时自动创建默认管理员

### 验证部署
- 访问 `http://localhost:8080` 查看服务器元数据
- 访问 `http://localhost:8080/admin/login` 进入管理界面
- 访问 `http://localhost:8080/meta/docs` 查看API文档

## 测试建议

1. **密码加密测试**:
- 注册新用户验证密码加密
- 现有用户登录兼容性测试

2. **材质源测试**:
- 本地材质访问测试
- HTTP材质源配置测试
- 故障转移测试

3. **管理界面测试**:
- 管理员登录测试
- 用户管理功能测试
- 权限控制测试

4. **API文档测试**:
- 访问各个元数据端点
- 验证API文档完整性

## 总结

所有四个功能已成功实现并集成到 MioVerify 项目中:

✅ **密码密文存储** - 使用BCrypt加密,向后兼容
✅ **动态材质资源来源** - 支持本地和HTTP源,自动故障转移
✅ **后台管理界面** - 现代化Web界面,完整的管理功能
✅ **API地址指示(ALI)** - 完整的API文档和元数据系统

项目现在具备了更强的安全性、灵活性和可管理性,为用户提供了更好的体验。
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

![Static Badge](https://img.shields.io/badge/version-v1.2.0--BETA-blue) ![Static Badge](https://img.shields.io/badge/java-17-purple) ![Static Badge](https://img.shields.io/badge/developer-Fuzihara_Yukina-orange) ![Static Badge](https://img.shields.io/badge/developer-pingguomc-orange) ![Static Badge](https://img.shields.io/badge/for-Minecraft_Java_Edition-green)

MioVerify是一个根据 *[Yggdrasil 服务端技术规范](https://github.com/yushijinhun/authlib-injector/wiki/Yggdrasil-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%8A%80%E6%9C%AF%E8%A7%84%E8%8C%83)* 实现的MC身份验证服务器。
MioVerify是一个基于 *[Yggdrasil 服务端技术规范](https://github.com/yushijinhun/authlib-injector/wiki/Yggdrasil-%E6%9C%8D%E5%8A%A1%E7%AB%AF%E6%8A%80%E6%9C%AF%E8%A7%84%E8%8C%83)* 实现的MC身份验证服务器。

本分支旨在修复源分支的安全问题和部分Bug。

Expand Down
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
Expand Down
39 changes: 22 additions & 17 deletions src/main/java/org/miowing/mioverify/config/DataInitializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,29 @@ private DatabasePopulator databasePopulator() {
}
@Override
public void afterPropertiesSet() throws Exception {
log.info("Getting all tokens in redis...");
Set<String> keys = redisTemplate.keys(TokenUtil.TOKEN_PREF + "*");
if (keys == null) {
log.info("No tokens found.");
return ;
}
log.info("Found " + keys.size() + ". Start checking validation...");
int count = 0;
for (String key : keys) {
String t = StrUtil.subSuf(key, 3);
Boolean hasKey = redisTemplate.hasKey(TokenUtil.TMARK_PREF + t);
if (hasKey == null || !hasKey) {
redisService.removeToken(t);
count++;
try {
log.info("Getting all tokens in redis...");
Set<String> keys = redisTemplate.keys(TokenUtil.TOKEN_PREF + "*");
if (keys == null) {
log.info("No tokens found.");
return ;
}
}
if (count > 0) {
log.info("Cleared " + count + " token(s) expired.");
log.info("Found " + keys.size() + ". Start checking validation...");
int count = 0;
for (String key : keys) {
String t = StrUtil.subSuf(key, 3);
Boolean hasKey = redisTemplate.hasKey(TokenUtil.TMARK_PREF + t);
if (hasKey == null || !hasKey) {
redisService.removeToken(t);
count++;
}
}
if (count > 0) {
log.info("Cleared " + count + " token(s) expired.");
}
} catch (Exception e) {
log.warn("Redis connection failed, skipping token cleanup: " + e.getMessage());
log.info("Application will continue without Redis token management.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package org.miowing.mioverify.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

@Configuration
@Slf4j
public class RedisListenerConfig {
@Bean
public RedisMessageListenerContainer container(RedisConnectionFactory factory) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
return container;
try {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(factory);
return container;
} catch (Exception e) {
log.warn("Failed to create Redis listener container: " + e.getMessage());
return new RedisMessageListenerContainer();
}
}
}
31 changes: 31 additions & 0 deletions src/main/java/org/miowing/mioverify/config/SecurityConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.miowing.mioverify.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(authz -> authz
.anyRequest().permitAll()
);

return http.build();
}
}
Loading