Skip to content

如何在 Vitepress 中实现权限管理?

在WEB应用中,权限一般是指控制路由或者文档部分内容有权限才可见,确保只有授权的用户能访问特定的功能与数据。

整体思路就两步:

  1. 先把文档保护起来,不让公开访问。
  2. 对私有文档做授权,有权限才可见。

文档权限控制,在一些内部私有文档的场景,很有用。

前言

对于使用 Vitepress 构建的项目文档站来说,实现权限管理也是可以实现的。

要在 Vitepress 中实现权限管理,首先得对它的架构和工作原理有个清晰的认识。Vitepress 是一个基于 Vite + Vue 的静态网站生成器,完全可以当成一个前端项目来按需改造。

做权限管理,这里假设你服务端已经有一套用户体系,也已经实现了用户登录功能。也可以参考 Vitepress 微信授权登录

一、保护私有内容

在做权限控制前,先要确定是怎样的机制保护内容前端不可见的。

然后通过授权的方式,在你的保护机制上开个口子给授权的用户访问。

提供两个我都尝试过的方案,可以按这个思路自行选择改造。

方案1:编译时加密

前端的方案,在编译时,使用Vite插件,实现内容的加密,前端判断权限后根据会话取秘钥做解密。

这个功能的Vite插件我没找到开源的,有尝试过自己写,确定是可以实现的。

开发Vite插件:docs/.vitepress/crypto-plugin.js

function cryptoPlugin() {  
    return {  
        name: 'crypto-plugin',  
        enforce: 'pre', // 插件顺序,在Vite核心插件前执行  
        transform(src, id) {
	        //id:文件名,判断要处理的文件
	        if (id.indexOf('.md') !== -1){
			    //Markdown中的文字加密后,放到解密函数的参数中
			    //TODO 这部分我已验证了替换的可行性,还差写个加密解密
		        return src.replace('原文', '处理过的密文')  
	        }  
        },  
    };  
}  
  
export default cryptoPlugin

使用插件:docs/.vitepress/config.js

import {defineConfig} from 'vitepress'  
import cryptoPlugin from './crypto-plugin.js'  

export default defineConfig({  
    vite: {  
        plugins: [  
            cryptoPlugin()
        ]  
    },  
})

方案2:服务端判断

服务端方案,自己开发静态文件服务端,根据请求路径判断当前用户是否有权限,有权限才返回文件内容。

由服务端判断,前端就不用做处理,下面是我用Golang写的例子:

go
  
// HandlerStaticServer 静态文件服务  
func (ctl *Controller) HandlerStaticServer(ctx *gin.Context) {  
    path := ctx.Request.URL.Path  
    if strings.HasSuffix(path, "/") {  
       path += "/index.html"  
    }  
    dir := "/usr/www" // 静态文件根目录,VitePress编译后的文件放这,代替Nginx
    fBytes, err := os.ReadFile(dir + path)  
    if err != nil {  
       http.NotFound(ctx.Writer, ctx.Request)  
       return  
    }  
    // 请求文件后缀  
    suffix := (strings.Split(path, "?")[0])[strings.LastIndex(path, "."):]  
    if suffix == ".html" || suffix == ".js" {  
       //登录会话  
       token, _ := hgin.GetCookieToken(ctx)  
       //已登录,则判断path权限  
       if token!="" {  
          //TODO 判断当前用户path权限...  
       }  
    }  
    // 根据文件取Content-Type  
    contentType := declareContentType[suffix]  
    if contentType == "" {  
       contentType = http.DetectContentType(fBytes) //根据内容取Content-Type,优先使用自己声明的  
    }  
    ctx.Data(http.StatusOK, contentType, fBytes)  
}

用其他语言思路也一样,整体思路就是不使用公开的静态文件服务,而是自己写一个静态文件服务,去判断访问权限。

二、路由页面权限

路由页面权限控制,在路由更新事件监听中实现权限判断

主题入口文件docs/.vitepress/theme/index.js

import DefaultTheme from 'vitepress/theme';

export default {
    extends: DefaultTheme,
    enhanceApp({app, router}) {
        // 单页面应用路由更新时触发事件
        router.onBeforeRouteChange = (to) => {
            // 根据路由结合后台接口做判断
            ...
        }
    }
}

三、文档部分内容权限

通过自定义标签,把需要权限的内容,放到标签中。 可以参考 VitePress会员主题 方案。

总结

这篇文章介绍了在 Vitepress 中实现权限管理的方案,从文档保护与权限判断两个层面做了介绍。