Golang Gin MySQL 实现用户 RBAC 权限控制

简介

RBAC(基于角色的访问控制)是一种常见的权限管理方式。在本教程中,我们将使用 Golang 的 Gin 框架和 MySQL 数据库来实现用户的 RBAC。这个过程包括数据库设计、API 路由设计、以及实现角色和权限控制。

流程概述

以下是实现该目标的步骤:

步骤编号 步骤描述
1 设计数据库结构
2 初始化 Golang 项目
3 创建连接 MySQL 数据库
4 实现用户注册和登录 API
5 实现角色和权限的 CRUD 操作
6 实现用户角色分配功能
7 使用中间件实现权限检查

步骤详解

1. 设计数据库结构

首先,我们需要创建以下数据表:

  • Users(用户表)
  • Roles(角色表)
  • Permissions(权限表)
  • RolePermissions(角色权限关联表)
  • UserRoles(用户角色关联表)

在 MySQL 中可以使用以下 SQL 语句创建这些表:

CREATE TABLE Users (
    id INT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(100) NOT NULL UNIQUE,
    password VARCHAR(100) NOT NULL
);

CREATE TABLE Roles (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE Permissions (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL UNIQUE
);

CREATE TABLE RolePermissions (
    role_id INT,
    permission_id INT,
    PRIMARY KEY (role_id, permission_id),
    FOREIGN KEY (role_id) REFERENCES Roles(id),
    FOREIGN KEY (permission_id) REFERENCES Permissions(id)
);

CREATE TABLE UserRoles (
    user_id INT,
    role_id INT,
    PRIMARY KEY (user_id, role_id),
    FOREIGN KEY (user_id) REFERENCES Users(id),
    FOREIGN KEY (role_id) REFERENCES Roles(id)
);

2. 初始化 Golang 项目

在项目目录下创建一个新的 Gin 项目:

go mod init my_rbac
go get github.com/gin-gonic/gin
go get github.com/go-sql-driver/mysql

3. 创建连接 MySQL 数据库

创建数据库连接部分代码,确保能与 MySQL 连接:

package main

import (
    "database/sql"
    "log"
    "github.com/gin-gonic/gin"
    _ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func connectDB() {
    var err error
    dsn := "user:password@tcp(127.0.0.1:3306)/mydatabase"
    db, err = sql.Open("mysql", dsn)
    if err != nil {
        log.Fatal(err)
    }
}

func main() {
    connectDB()
    r := gin.Default()
    r.Run()
}

4. 实现用户注册和登录 API

实现用户注册和登录的 API:

// User structure
type User struct {
    ID       int    `json:"id"`
    Username string `json:"username"`
    Password string `json:"password"`
}

// Register new user
func register(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(400, gin.H{"error": "Bad Request"})
        return
    }
    // Insert user into DB (password hashing omitted for brevity)
    _, err := db.Exec("INSERT INTO Users (username, password) VALUES (?, ?)", user.Username, user.Password)
    if err != nil {
        c.JSON(500, gin.H{"error": "Internal Server Error"})
        return
    }
    c.JSON(200, gin.H{"message": "User registered!"})
}

func login(c *gin.Context) {
    var user User
    if err := c.ShouldBindJSON(&user); err != nil {
        c.JSON(400, gin.H{"error": "Bad Request"})
        return
    }
    // Check user credentials (password hashing omitted for brevity)
    row := db.QueryRow("SELECT id FROM Users WHERE username = ? AND password = ?", user.Username, user.Password)
    if err := row.Scan(&user.ID); err != nil {
        c.JSON(401, gin.H{"error": "Unauthorized"})
        return
    }
    c.JSON(200, gin.H{"message": "Login successful"})
}

5. 实现角色和权限的 CRUD 操作

我们为角色和权限实现基本的 CRUD 操作,可以看着写相应的 API。

(具体实现同样需要使用 SQL 语句进行操作,代码省略。)

6. 实现用户角色分配功能

实现将角色分配给予用户的功能,使用相应的 DB 操作。

7. 使用中间件实现权限检查

中间件方向可以检测用户的权限:

// Middleware for checking permissions
func authorize(permission string) gin.HandlerFunc {
    return func(c *gin.Context) {
        // Check if user has the required permission (simplified)
        c.Next()
    }
}

饼状图

我们可以将权限分布可视化为饼状图,在这里是以 mermaid 格式表示:

pie
    title 权限分配
    "读取数据": 40
    "写入数据": 25
    "删除数据": 20
    "更新数据": 15

状态图

用户的状态转换图可以用状态图表示:

stateDiagram
    [*] --> 注册
    注册 --> 登录
    登录 --> [*]
    登录 --> 错误
    错误 --> 登录

结尾

通过以上步骤,我们实现了一个简单的基于角色的访问控制系统。掌握了 Golang、Gin 框架与 MySQL 的结合使用,对于任何开发者来说都是一个重要的技能。您可以在此基础上扩展更多功能,如 JWT 验证、权限细粒度控制等。这些都是提升系统安全性与公平性的必要手段。希望这篇文章能帮助您在 RBAC 实践中更进一步!