Skip to content

Commit a5ec2c8

Browse files
committed
项目基本搭建
1 parent 907ed38 commit a5ec2c8

File tree

6 files changed

+110
-51
lines changed

6 files changed

+110
-51
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# FFLY Basic
2+
3+
一个基于 Go 语言开发的基础后台管理系统,提供用户管理、角色权限管理、API 日志等基础功能。
4+
5+
## 功能特性
6+
7+
- 用户管理
8+
- 用户注册/登录
9+
- 用户信息管理
10+
- 密码加密存储
11+
- 登录限流保护
12+
13+
- 角色权限管理
14+
- 基于 RBAC 的权限控制
15+
- 角色管理
16+
- 权限分配
17+
- 动态权限验证
18+
19+
- 系统功能
20+
- JWT 认证
21+
- API 访问日志
22+
- Redis 缓存支持
23+
- MySQL 数据存储
24+
25+
## 技术栈
26+
27+
- Go 1.20+
28+
- MySQL 5.7+
29+
- Redis 6.0+
30+
- JWT
31+
- Gin Framework
32+
- GORM
33+
34+
Binary file not shown.

config/config.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ app:
66
jwt_expire: 86400 # 24 hours
77

88
mysql:
9-
host: localhost
9+
host: 192.168.111.132
1010
port: 3306
1111
user: root
1212
password: root
@@ -16,9 +16,9 @@ mysql:
1616
connection_max_lifetime: 60
1717

1818
redis:
19-
host: localhost
19+
host: 192.168.111.132
2020
port: 6379
21-
password: "" # 密码为空
21+
password: "redis123" # 密码为空
2222
db: 0 # 默认数据库
2323
pool_size: 100 # 连接池大小
2424
min_idle_conns: 10 # 最小空闲连接数

internal/service/login.go

Lines changed: 54 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import (
66
"ffly-baisc/internal/model"
77
"ffly-baisc/pkg/auth"
88
"ffly-baisc/pkg/utils"
9+
"fmt"
10+
"time"
911

1012
"gorm.io/gorm"
1113
)
@@ -15,7 +17,40 @@ type LoginService struct {
1517
Password string `json:"password" binding:"required,min=6,max=20"`
1618
}
1719

20+
// LoginLimiter 用户登录限流(一分钟内最多登录5次)
21+
func LoginLimiter(loginService *LoginService) (bool, error) {
22+
// 构造 redis key
23+
key := fmt.Sprintf("login_attempts:%s", loginService.Username)
24+
25+
// 使用 Redis 的 INCR 命令增加计数
26+
count, err := db.DB.Redis.Incr(key).Result()
27+
if err != nil {
28+
return false, err
29+
}
30+
31+
// 如果是第一次登录,则设置过期时间为 1 分钟
32+
if count == 1 {
33+
db.DB.Redis.Expire(key, time.Minute)
34+
}
35+
36+
// 检查是否超过限制
37+
if count > 5 {
38+
return true, fmt.Errorf("登录次数过多,请稍后再试")
39+
}
40+
41+
return false, nil
42+
}
43+
1844
func (service *LoginService) Login() (string, error) {
45+
// 用户登录限流
46+
isLimit, err := LoginLimiter(service)
47+
if err != nil {
48+
return "", err
49+
}
50+
if isLimit {
51+
return "", err
52+
}
53+
1954
// 检查用户名是否存在
2055
var user model.User
2156
if err := db.DB.MySQL.Where("username = ?", service.Username).First(&user).Error; err != nil {
@@ -42,43 +77,32 @@ func (service *LoginService) Login() (string, error) {
4277
}
4378

4479
type RegisterService struct {
45-
Username string `json:"username" binding:"required,min=2,max=20"`
46-
Password string `json:"password" binding:"required,min=6,max=20"`
47-
ConfirmPassword string `json:"confirmPassword" binding:"required,min=6,max=20"`
48-
Nickname string `json:"nickname"`
49-
Email string `json:"email" binding:"omitempty,email"` // omitempty 允许为空
50-
Phone string `json:"phone" binding:"omitempty,e164"` // omitempty 允许为空
80+
Username *string `json:"username" binding:"required,min=2,max=20"`
81+
Password *string `json:"password" binding:"required,min=6,max=20"`
82+
ConfirmPassword *string `json:"confirmPassword" binding:"required,min=6,max=20"`
83+
Nickname *string `json:"nickname"`
84+
Email *string `json:"email" binding:"omitempty,email"` // omitempty 允许为空
85+
Phone *string `json:"phone" binding:"omitempty,e164"` // omitempty 允许为空
5186
}
5287

5388
func (service *RegisterService) Register() error {
54-
// 检查用户名是否存在
55-
var count int64
56-
if err := db.DB.MySQL.Model(&model.User{}).Where("username = ?", service.Username).Count(&count).Error; err != nil {
57-
return err
58-
}
59-
60-
if count > 0 {
61-
return errors.New("用户名已存在")
62-
}
63-
64-
if service.Password != service.ConfirmPassword {
89+
// 密码存在并且检查密码是否一致
90+
if *service.Password != "" && *service.Password != *service.ConfirmPassword {
6591
return errors.New("两次密码输入不一致")
6692
}
6793

68-
// 加密密码
69-
hashedPassword, err := utils.EncodePassword(service.Password)
70-
if err != nil {
71-
return err
72-
}
73-
7494
// 创建用户
75-
user := &model.User{
76-
Username: &service.Username,
77-
Password: &hashedPassword,
78-
Nickname: &service.Nickname,
79-
Email: &service.Email,
80-
Phone: &service.Phone,
95+
userCreateRequest := &model.UserCreateRequest{
96+
Username: service.Username,
97+
Password: service.Password,
98+
Nickname: service.Nickname,
99+
Email: service.Email,
100+
Phone: service.Phone,
101+
}
102+
var userService UserService
103+
if err := userService.CreateUser(userCreateRequest); err != nil {
104+
return err
81105
}
82106

83-
return db.DB.MySQL.Create(user).Error
107+
return nil
84108
}

internal/service/user.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,20 +67,26 @@ func (service *UserService) CreateUser(userCreateRequest *model.UserCreateReques
6767
}
6868
userCreateRequest.Password = &hashedPassword
6969

70+
// 处理 RoleID, 确保不为 nil
71+
var roleID uint
72+
if userCreateRequest.RoleID != nil {
73+
roleID = *userCreateRequest.RoleID
74+
}
75+
userCreateRequest.RoleID = &roleID
76+
77+
fmt.Print(userCreateRequest)
78+
7079
// 创建用户
71-
if err := db.DB.MySQL.Model(&model.User{}).Create(userCreateRequest).Error; err != nil {
80+
if err := tx.Model(&model.User{}).Create(userCreateRequest).Error; err != nil {
7281
tx.Rollback() // 回滚事务
7382
return err
7483
}
7584

76-
// 如果传入 roleID
77-
if userCreateRequest.RoleID != nil {
78-
// 创建用户角色关联
79-
var userRoleService UserRoleService
80-
if err := userRoleService.SaveUserRole(tx, userCreateRequest.ID, *userCreateRequest.RoleID); err != nil {
81-
tx.Rollback() // 回滚事务
82-
return err
83-
}
85+
// 创建用户角色关联
86+
var userRoleService UserRoleService
87+
if err := userRoleService.SaveUserRole(tx, userCreateRequest.ID, *userCreateRequest.RoleID); err != nil {
88+
tx.Rollback() // 回滚事务
89+
return err
8490
}
8591

8692
// 提交事务

schema.sql

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ create table if not exists `users` (
2020
`email` varchar(100) default null comment '邮箱',
2121
`phone` varchar(20) default null comment '手机号',
2222
`status` tinyint unsigned not null default '1' comment '状态 1: 启用 2: 禁用',
23-
`role_id` bigint unsigned not null comment '角色id',
23+
`role_id` bigint unsigned not null default '0' comment '角色id',
2424
`created_at` timestamp not null default current_timestamp comment '创建时间',
2525
`updated_at` timestamp not null default current_timestamp on update current_timestamp comment '更新时间',
2626
`deleted_at` timestamp null default null comment '删除时间',
@@ -135,11 +135,6 @@ create table if not exists `api_logs` (
135135
primary key (`id`)
136136
) engine=innodb auto_increment=1 comment='日志表';
137137

138-
-- -- 修改表
139-
-- alter table `users`
140-
-- add unique key `uk_username` (`username`),
141-
-- add unique key `uk_email` (`email`),
142-
-- add unique key `uk_phone` (`phone`);
143-
144-
-- alter table `permissions`
145-
-- modify column `type` enum('menu', 'button') not null comment '权限类型, menu: 菜单, button: 按钮';
138+
-- 修改表
139+
alter table `users`
140+
modify column `role_id` bigint unsigned not null default '0' comment '角色id';

0 commit comments

Comments
 (0)