Skip to content

一步步实现微服务权限管理系统(2)

前言

  • 前端参考了很多框架,可谓百花齐放,但很多封装过剩,不利于学习和应用,最终我选择了 [vue-pure-admin](https://github.com/pure-admin/vue-pure-admin)
  • 后端我将使用 go-zero 来带领大家一步步实现一个权限管理系统
  • 本系列项目存放在 purezeroadmin 中,每一部分我都将打tag,并保证每个tag能正常运行。请多点赞和评论。
  • 后面示例均为 purezeroadmin 项目为例,你们可以根据需要自建工程来进行试验。均采用vscode进行试验。
  • go-zero 常用命令我将放入其对应的 makefile 文件中。

前端相关接口参考

前端模拟的接口在 mock 文件夹中,后端可参照修改

后端修改

登陆接口

  1. 公共api创建 前端返回接口均为 {success: true, data: xxx}, 所以创建公共api `
cat base-api/base.api

api:

type Base {
    Success bool `json:"success"`
}
  1. 依照前章示例,创建 user.api 文件
cat `user-api/api/user.api`

api:

syntax = "v1"

info (
    title: "q9090960bnb3"
    desc:  "haha"
    date:  "2024-10-31"
)

import "../../base-api/base.api"

type UserLoginData {
    Avatar       string   `json:"avatar"`
    Username     string   `json:"username"`
    Nickname     string   `json:"nickname"`
    Roles        []string `json:"roles"`
    Permissions  []string `json:"permissions"`
    AccessToken  string   `json:"accessToken"`
    RefreshToken string   `json:"refreshToken"`
    Expires      string   `json:"expires"`
}

type (
    UserLoginReq {
        UserName string `json:"username"`
        Password string `json:"password"`
    }
    UserLoginResp {
        Base
        Data UserLoginData `json:"data"`
    }
)

service user-api {
    @doc "用户登录"
    @handler userLogin
    post /login (UserLoginReq) returns (UserLoginResp)
}
  1. 生成代码
goctl api go --api user-api/api/user.api --dir user-api
  1. 参考前端mock数据,修改 user-api/internal/logic/userloginlogic.go 中的函数
func (l *UserLoginLogic) UserLogin(req *types.UserLoginReq) (resp *types.UserLoginResp, err error) {
    if req.UserName == "admin" {
        return &types.UserLoginResp{
            Base: types.Base{
                Success: true,
            },
            Data: types.UserLoginData{
                Avatar:       "https://avatars.githubusercontent.com/u/44761321",
                Username:     "admin",
                Nickname:     "小铭",
                Roles:        []string{"admin"},
                Permissions:  []string{"*:*:*"},
                AccessToken:  "eyJhbGciOiJIUzUxMiJ9.admin",
                RefreshToken: "eyJhbGciOiJIUzUxMiJ9.adminRefresh",
                Expires:      "2030/10/30 00:00:00",
            },
        }, nil
    }

    return &types.UserLoginResp{
        Base: types.Base{
            Success: true,
        },
        Data: types.UserLoginData{
            Avatar:       "https://avatars.githubusercontent.com/u/52823142",
            Username:     "common",
            Nickname:     "小林",
            Roles:        []string{"common"},
            Permissions:  []string{"permission:btn:add", "permission:btn:edit"},
            AccessToken:  "eyJhbGciOiJIUzUxMiJ9.common",
            RefreshToken: "eyJhbGciOiJIUzUxMiJ9.commonRefresh",
            Expires:      "2030/10/30 00:00:00",
        },
    }, nil
}

修改刷新token接口

  1. user.api 中添加
type UserRefreshTokenData {
    AccessToken  string `json:"accessToken"`
    RefreshToken string `json:"refreshToken"`
    Expires      string `json:"expires"`
}

type (
    UserRefreshTokenReq {
        RefreshToken string `json:"refreshToken"`
    }
    UserRefreshTokenResp {
        Base
        Data UserRefreshTokenData `json:"data"`
    }
)

service user-api {
    @doc "用户登录"
    @handler UserRefreshToken
    post /refresh-token (UserRefreshTokenReq) returns (UserRefreshTokenResp)
}
  1. 参考前端mock数据,修改 user-api/internal/logic/userrefreshtokenlogic.go 中的函数
func (l *UserRefreshTokenLogic) UserRefreshToken(req *types.UserRefreshTokenReq) (resp *types.UserRefreshTokenResp, err error) {
    if req.RefreshToken != "" {
        return &types.UserRefreshTokenResp{
            Base: types.Base{
                Success: true,
            },
            Data: types.UserRefreshTokenData{
                AccessToken:  "",
                RefreshToken: "",
                Expires:      "",
            },
        }, nil
    }
    return &types.UserRefreshTokenResp{}, nil
}

修改异步获取路由接口

  1. user.api 中添加
type RouterData {
    Path      string       `json:"path"`
    Name      string       `json:"name,omitempty"`
    Component string       `json:"component,omitemty"`
    Meta      Meta         `json:"meta"`
    Children  []RouterData `json:"children,omitempty"`
}

type Meta {
    Title string   `json:"title"`
    Icon  string   `json:"icon,omitempty"`
    Rank  int64    `json:"rank,omitempty"`
    Roles []string `json:"roles,omitempty"`
    Auths []string `json:"auths,omitempty"`
}

type (
    UserRouterReq  {}
    UserRouterResp {
        Base
        Data []RouterData `json:"data"`
    }
)

service user-api {
    @doc "用户登出"
    @handler userRouter
    get /get-async-routes (UserRouterReq) returns (UserRouterResp)
}
  1. 参考前端mock数据,修改 user-api/internal/logic/userrouterlogic.go 中的函数
func (l *UserRouterLogic) UserRouter(req *types.UserRouterReq) (resp *types.UserRouterResp, err error) {
    return &types.UserRouterResp{
        Base: types.Base{
            Success: true,
        },
        Data: []types.RouterData{
            {
                Path: "/permission",
                Meta: types.Meta{
                    Title: "权限管理",
                    Icon:  "ep:lollipop",
                    Rank:  10,
                },
                Children: []types.RouterData{
                    {
                        Path: "/permission/page/index",
                        Name: "PermissionPage",
                        Meta: types.Meta{
                            Title: "页面权限",
                            Roles: []string{"admin", "common"},
                        },
                    },
                    {
                        Path: "/permission/button",
                        Meta: types.Meta{
                            Title: "按钮权限",
                            Roles: []string{"admin", "common"},
                        },
                        Children: []types.RouterData{
                            {
                                Path:      "/permission/button/router",
                                Component: "permission/button/index",
                                Name:      "PermissionButtonRouter",
                                Meta: types.Meta{
                                    Title: "路由返回按钮权限",
                                    Auths: []string{
                                        "permission:btn:add",
                                        "permission:btn:edit",
                                        "permission:btn:delete",
                                    },
                                },
                            },
                            {
                                Path:      "/permission/button/login",
                                Component: "permission/button/perms",
                                Name:      "PermissionButtonLogin",
                                Meta: types.Meta{
                                    Title: "登录返回按钮权限",
                                },
                            },
                        },
                    },
                },
            },
        },
    }, nil
}

前端取消mock

参考 如何关闭mock

前端配置端口转发

vite.config.ts 中配置转发

// 本地跨域代理 https://cn.vitejs.dev/config/server-options.html#server-proxy
proxy: {
"^/(login|refresh-token|get-async-routes)": {
    target: "http://localhost:8888",
    changeOrigin: true,
},
},

启动测试

  1. 启动后端服务
# vue-pure-admin工程下执行 cd back-end/user-api
❯ go run user.go
Starting server at 0.0.0.0:8888...
  1. 启动前端服务
# vue-pure-admin工程下执行 cd front-end
❯ pnpm dev

tag版本

purezeroadmin 项目下

git checkout v1.1.0

接下来

目前,前端请求路由太自由了,最好采用统一前缀去访问后端系统

Comments