golang开发支持onlyoffice的token功能

发布于:2025-03-17 ⋅ 阅读:(20) ⋅ 点赞:(0)

一直都没去弄token这块,想着反正docker run的时候将jwt置为false即可。

看了好多文章,感觉可以试试,但是所有文件几乎都没说思路。

根据我的理解和成功的调试,思路是:

我们先定义2个概念,一个是文档下载管理服务,一个是onlyoffice协作服务。

用户点击链接进入协作页面,那么文档下载服务那边会根据这个链接里带的文档id,以及用户的id,把一些变量传给协作页面里,例如用户是否有权限编辑,还是只能看……还有文档的下载地址,文档类型等,这些参数,onlyoffice协作服务会在页面取过去。

打开页面后,页面里的上述变量也填充了,页面里再弄个JavaScript执行一段代码,将上述填充了参数的json结构体,JSON.stringfy后,推荐用body方式传到文档下载服务那边,文档下载服务再解析,然后作为荷载生成token,返回给协作页面里,协作页面里取到token后,赋值给页面某个元素即可。

当最后一个用户关闭协作页面9s后,onlyoffice协作服务器会发一段信息给文档下载服务器那边,文档下载服务器收到信息,是不是token格式,是不是要解码?敬请期待。

当然,token的secret一方面在文档下载服务端用到,同时要加到docker启动的onlyoffice容器中叫local.json里去。这个网上很多。

以上就是思路,很少有人讲,或许大家都认为容易懂吧。

前端代码参考:

const config = {
    "document": {
      "fileType": "{{.fileType}}",
      "key": "{{.Key}}", //"Khirz6zTPdfd7"
      "title": "{{.Doc.FileName}}",
      "url":"http:\/\/192.168.100.37/attachment/onlyoffice/测试v3.docx"
      // "url": "{{.Engineercmsapi_url}}/attachment/onlyoffice/{{.Doc.FileName}}?hotqinsessionid={{.Sessionid}}",
    },
    "documentType": "{{.documentType}}",
    "editorConfig": {
      "callbackUrl": "{{.Engineercmsapi_url}}/url-to-callback?id={{.Doc.Id}}",
      "customization": {
        "uiTheme": "theme-dark",
        "unit": "cm",
        "wordHeadingsColor": "#00ff00",
        "zoom": 100,
      },
      "user": {
        "id": {{.Uid }},
        "name": "{{.Username}}"
      },
      "lang": "zh-CN", //"en-US",
      "mode": {{.Mode }}, //"view",//edit
      "region": "zh-CN",
    },
    "height": "100%",
    "type": {{.Type }}, //"desktop",embedded,mobile访问文档的平台类型 网页嵌入
    "width": "100%"
  }
  // window.docEditor = new DocsAPI.DocEditor("placeholder", config);

  $(function () {
    const configJsonStr = JSON.stringify(config);
    $.ajax({
      type: "POST",
      url: "/v1/onlyoffice/jwtencode",
      contentType: "application/json",
      data: configJsonStr,
      dataType: "json",
      success: function (data) {
        console.log("成功")
        console.log(data)
        if(data.jwt){
          config.token = data.jwt;
        }  
        var docEditor = new DocsAPI.DocEditor("placeholder", config);
      },
      error: function (err) {
        console.error(err);
      }
    })
  })

golang服务端代码参考

// *************官方给的生成tokend的代码****开始*****冰山一角*****
// ***它只是告诉了我们,它用的是jwt.SigningMethodHS256
type onlyofficeJwtManager struct {
	key []byte
}

func (j onlyofficeJwtManager) Sign(payload interface {
	Valid() error
}) (string, error) {
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, payload)
	ss, err := token.SignedString(j.key)

	if err != nil {
		return "", errors.New("could not generate a new jwt")
	}

	return ss, nil
}
// *************官方给的生成tokend的代码***结束******离补齐似乎相差十万八千里********

// ******我补的代码***********

type OnlyofficeClaims struct {
	Document             OnlyDocument     `json:"document"`
	DocumentType         string           `json:"documentType"`
	EditorConfig         OnlyEditorConfig `json:"editorConfig"`
	Height               string           `json:"height"`
	Type                 string           `json:"type"`
	Width                string           `json:"width"`
	jwt.RegisteredClaims                  // 只要结构体里放上这个就算是inteface{},并且符合作为claims的要求了。
}

type OnlyDocument struct {
	FileType string `json:"fileType"`
	Key      string `json:"key"`
	Title    string `json:"title"`
	Url      string `json:"url"`
}

type OnlyEditorConfig struct {
	CallbackUrl   string     `json:"callbackUrl"`
	Customization OnlyCustom `json:"customization"`
	User          OnlyUser   `json:"user"`
	Lang          string     `json:"lang"`
	Mode          string     `json:"mode"`
	Region        string     `json:"region"`
}

type OnlyCustom struct {
	UiTheme           string `json:"uiTheme"`
	Unit              string `json:"unit"`
	WordHeadingsColor string `json:"wordHeadingsColor"`
	Zoom              int    `json:"zoom"`
}

type OnlyUser struct {
	Id   string `json:"id"`
	Name string `json:"name"`
}

// @Title post onlyoffce jwtencode token
// @Description post onlyoffice jwtencode token
// @Success 200 {object} models.Ollyoffice
// @Failure 400 Invalid page supplied
// @Failure 404 office not found
// @router /jwtencode [post]
// 生成token
func (c *OnlyController) JwtEncode() {
	content := c.Ctx.Input.RequestBody
	var onlyofficeconfig OnlyofficeClaims
	err := json.Unmarshal(content, &onlyofficeconfig)
	if err != nil {
		logs.Error(err)
	}
	logs.Info(onlyofficeconfig) // {"document":{"fileType":"doc","key":"1558683150313208200","title":"xml.doc","url":"http://192.168.100.37/attachment/onlyoffice/测试v3.docx"},"documentType":"word","editorConfig":{"callbackUrl":"http://192.168.137.1:8081/url-to-callback?id=10","customization":{"uiTheme":"theme-dark","unit":"cm","wordHeadingsColor":"#00ff00","zoom":100},"user":{"id":"0","name":"127.0.0.1"},"lang":"zh-CN","mode":"edit","region":"zh-CN"},"height":"100%","type":"desktop","width":"100%"}

	jwt_enabled, err := web.AppConfig.String("JWT_ENABLED")
	if err != nil {
		logs.Error(err)
	}
	if jwt_enabled == "true" {
		jwt_secret, err := web.AppConfig.String("onlyoffice_token_secret")
		if err != nil {
			logs.Error(err)
		}
		key := onlyofficeJwtManager{[]byte(jwt_secret)}
		logs.Info(key)

		token, err := key.Sign(onlyofficeconfig) // 这里用了官方的代码
		if err != nil {
			logs.Error(err)
		}
		c.Data["json"] = map[string]interface{}{"state": "SUCCESS", "info": "SUCCESS", "jwt": token}
		c.ServeJSON()
		return
	}
	c.Data["json"] = map[string]interface{}{"state": "SUCCESS", "info": "SUCCESS", "jwt": onlyofficeconfig}
	c.ServeJSON()
}

 开源项目代码库:3xxx (hotqin888) (github.com)