基于Golang开发一个轻量级登录库/框架

基于Golang开发一个轻量级登录库/框架的完整攻略如下:

1. 确定需求

在开始开发之前,需要确定产品的需求。这个登录库需要实现的功能包括:

  • 注册用户账号
  • 用户登录验证
  • 用户信息查询
  • 用户权限控制
  • 登出

2. 选择框架

选择适合自己的框架是开发的基础,对于Golang而言,一般会使用gin框架,因为gin拥有出色的性能和灵活的中间件机制。

3. 数据库设计

设计数据库,此处我们使用MySQL数据库,设计用户表(User)和用户角色表(Role)。

CREATE TABLE `User` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(64) NOT NULL,
  `password` varchar(64) NOT NULL,
  `created_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `username_UNIQUE` (`username`)
) ENGINE=InnoDB;

CREATE TABLE `Role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `name_UNIQUE` (`name`)
) ENGINE=InnoDB;

4. 开发登录模块

注册用户账号

在handlers目录下创建一个user.go文件,实现注册用户的逻辑:

type UserController struct {
    UserService userService.UserService
}

func (controller *UserController) Register(c *gin.Context) {
    var user models.User
    c.BindJSON(&user)
    // 调用UserService的Register方法
    err := controller.UserService.Register(user)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "error": err.Error(),
        })
        return
    }
    c.JSON(http.StatusOK, gin.H{
        "message": "register successfully",
    })
}

用户登录验证

继续在handlers目录下user.go文件中编写用户登录逻辑:

func (controller *UserController) Login(c *gin.Context) {
    var user models.User
    c.BindJSON(&user)

    if controller.UserService.Login(user) {
        //在登录验证成功后创建一个jwttoken,返回给客户端
        tokenString, _ := middlewares.CreateToken(user.UserName)
        c.JSON(http.StatusOK, gin.H{
            "token": tokenString,
        })
    } else {
        c.JSON(http.StatusUnauthorized, nil)
    }
}

用户信息查询

实现用户信息查询:

func (controller *UserController) GetUser(c *gin.Context) {
    //从jwt中获取用户名
    userName := utils.GetUserNameFromToken(c.Request.Header["Authorization"][0])

    user, err := controller.UserService.GetUser(userName)
    if err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{
            "error": err.Error(),
        })
        return
    }
    c.JSON(http.StatusOK, user)
}

用户权限控制

在实现权限控制前,需要在UserRole表中添加用户和角色的关联关系。

//获取指定用户的角色列表
func (controller *UserController) GetUserRoles(userId int) ([]string, error) {
    roles, err := controller.UserService.GetUserRoles(userId)
    if err != nil {
        return nil, err
    }
    roleNames := make([]string, len(roles))
    for i, role := range roles {
        roleNames[i] = role.Name
    }
    return roleNames, nil
}

然后在最外层middlewares中实现基于Token的身份验证和权限控制:

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        tokenString := c.Request.Header["Authorization"][0]
        claims, err := utils.ParseToken(tokenString)
        if err != nil {
            c.JSON(http.StatusUnauthorized, nil)
            c.Abort()
            return
        } else if time.Now().Unix() > claims.ExpiresAt {
            c.JSON(http.StatusUnauthorized, gin.H{
                "message": "token expired",
            })
            c.Abort()
            return
        }
        c.Set("userName", claims.Username)
        c.Next()
    }
}

func PermissionMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        userName := c.GetString("userName")
        if !userService.HasPermission(userName, c.FullPath()) {
            c.JSON(http.StatusForbidden, gin.H{
                "message": "Permission denied",
            })
            c.Abort()
            return
        }
        c.Next()
    }
}

登出

移除Token即可。

func (controller *UserController) Logout(c *gin.Context) {
    //Todo: 移除Token即可
    c.JSON(http.StatusOK, gin.H{
        "message": "Logout successfully",
    })
}

5. 示例说明

我们将实现一个简单的web应用来演示该登录框架,该应用中包含一个index页面和admin页面,index页面任何人都可以浏览,但是只有管理员才能够访问admin页面。

index页面

func IndexHTMLHandler(c *gin.Context) {
    indexHTML := `
<html>
<head>
    <meta charset="UTF-8">
    <title>Index Page</title>
</head>
<body>
    <h1>Welcome to Index Page, everybody!</h1>
</body>
</html>`
    c.Data(http.StatusOK, "text/html; charset=utf8", []byte(indexHTML))
}

admin页面

func AdminHTMLHandler(c *gin.Context) {
    adminHTML := `
<html>
<head>
    <meta charset="UTF-8">
    <title>Admin Page</title>
</head>
<body>
    <h1>Welcome to Admin Page, administrator!</h1>
</body>
</html>`
    c.Data(http.StatusOK, "text/html; charset=utf8", []byte(adminHTML))
}

登录页面

使用html页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login Page</title>
</head>
<body>
    <form action="" id="login">
        <div>
            <label for="username">用户名:</label>
            <input type="text" id="username" name="username" require>
        </div>
        <div>
            <label for="password">密码:</label>
            <input type="password" id="password" name="password" require>
        </div>
        <button type="submit">登录</button>
    </form>

    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <script>
        $(document).ready(function() {
            $('#login').submit(function(e) {
                e.preventDefault();
                $.ajax({
                    url: '/login',
                    type: 'POST',
                    data: JSON.stringify({
                        'username': $('#username').val(),
                        'password': $('#password').val()
                    }),
                    contentType: "application/json",
                    dataType: "json",
                    success: function(data) {
                        localStorage.setItem("token", data.token);
                        window.location.href = '/';
                    },
                    error: function(request, status, error) {
                        alert("登录失败,请检查用户名和密码!");
                    }
                });
            });
        });
    </script>
</body>
</html>

实现

func setupRouter() *gin.Engine {
    router := gin.Default()

    userController := &controllers.UserController{UserService: &userService.UserServiceImpl{}}

    //注册路由
    router.POST("/register", userController.Register)

    //登录路由
    router.POST("/login", userController.Login)

    /*中间件*/
    middleware := middlewares.AuthMiddleware()
    router.Use(middleware)
    router.Use(middlewares.PermissionMiddleware())

    router.Static("/", "./web/static/")

    router.GET("/index.html", handlers.IndexHTMLHandler)
    router.GET("/admin.html", handlers.AdminHTMLHandler)
    router.GET("/user", userController.GetUser)

    return router
}

func main() {
    db := database.InitDatabase()
    defer db.Close()

    utils.InitJwt()

    server := &http.Server{
        Addr:    ":8080",
        Handler: setupRouter(),
    }
    err := server.ListenAndServe()
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

接下来,你就可以访问'/index.html'了,任何人都可以访问。当你访问'/admin.html'时,若请求的Token不具有访问/admin.html的权限,服务器将会返回状态码403,否则,将会返回admin.html文件。

至此,我们已经通过Golang成功构建了一个轻量级的登录库/框架,该框架具有基本的用户注册、登录、权限控制和登出功能,可以很方便的集成到你自己的应用中。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:基于Golang开发一个轻量级登录库/框架 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • 在Linux下搭建Git服务器的方法详解

    下面是在Linux下搭建Git服务器的方法详解。 1. 确认系统环境 首先,确认你的Linux系统已经安装了Git。可以通过以下命令查看: git –version 如果已经安装了Git,会输出Git的版本信息,如:“git version 2.7.4”。如果没有安装,可以使用以下命令安装: sudo apt-get install git 2. 创建Gi…

    GitHub 2023年5月16日
    00
  • 微信小程序(应用号)简单实例应用及实例详解

    微信小程序(应用号)简单实例应用及实例详解 简介 微信小程序是一种全新的开发模式,可以在微信中使用的应用程序。相较于传统的Web应用,微信小程序能够更加便捷地获取用户资源,同时也具备了更好的用户体验。 准备工作 要进行小程序开发,首先需要准备好下面的工作: 微信公众平台账号 微信小程序开发工具 示例一:数字彩票 实现方案 实现一个数字彩票应用,用户可以自主选…

    GitHub 2023年5月16日
    00
  • Linux系统下Git操作命令整理

    下面我将为你讲解“Linux系统下Git操作命令整理”的完整攻略。 Git基础命令 初始化Git 首先,我们需要进入到要管理的项目目录下,然后执行git init指令来初始化Git: cd /path/to/your/project git init 添加文件 要把文件添加到Git进行版本控制,我们需要执行git add指令: git add file1 f…

    GitHub 2023年5月16日
    00
  • 官网项目Jetpack Startup库学习

    官网项目Jetpack Startup库学习 简介 Jetpack Startup库是Android Jetpack中的一个库,它可以用来简化应用程序的启动流程,这对于开发者来说,可以提高开发效率和用户体验。本攻略将彻底讲解如何在Android Studio中使用Jetpack Startup库。 步骤 在项目的build.gradle中,添加以下依赖: d…

    GitHub 2023年5月16日
    00
  • go get 和 go install 对比介绍

    下面是关于“go get 和 go install 对比介绍”的完整攻略。 简介 在使用 Go 语言进行开发时,如果需要使用第三方库,通常需要用到 go get 或 go install 命令。这两个命令在 Go 的包管理中非常常见且重要。go get 是下载并安装远程代码包,而 go install 是编译并安装本地包到 $GOPATH/bin 目录中。 …

    GitHub 2023年5月16日
    00
  • Git建立本地仓库并上传到Gitee的详细步骤

    下面是Git建立本地仓库并上传到Gitee的详细步骤: 1. 创建Gitee仓库并获取SSH地址 首先登录到Gitee,进入个人中心,在左侧菜单栏中选择“我的仓库”,并点击“创建仓库”按钮,输入仓库名称、描述、选择仓库类型、是否私有等信息,然后点击“创建仓库”按钮,就可以创建一个Gitee仓库了。 创建成功后,在该仓库的页面中找到SSH地址,并记下来,后面需…

    GitHub 2023年5月16日
    00
  • GitHub Eclipse配置使用教程详解

    下面是这篇教程的完整攻略。 一、GitHub Eclipse配置使用教程详解 1. 环境准备 首先,我们需要准备一个做好的Eclipse和安装好Git的电脑。如果还没有安装Git,可以去Git官网下载安装。安装完成之后,打开Git Bash,运行以下命令: git config –global user.name "Your Name"…

    GitHub 2023年5月16日
    00
  • 实用的Go语言开发工具及使用示例

    实用的Go语言开发工具及使用示例 Go语言被广泛应用于Web应用、分布式系统和云计算等领域。在进行Go语言开发时,使用合适的开发工具可以提高开发效率,本文将介绍几款实用的Go语言开发工具及使用示例,供开发者参考。 1. GoLand GoLand是一款由JetBrains开发的集成开发环境(IDE),专门用于Go语言开发。该IDE集成了丰富的代码编辑、调试、…

    GitHub 2023年5月16日
    00
合作推广
合作推广
分享本页
返回顶部