{"id":207533,"date":"2025-07-08T09:56:04","date_gmt":"2025-07-08T01:56:04","guid":{"rendered":"https:\/\/server.hk\/cnblog\/207533\/"},"modified":"2025-07-08T09:56:04","modified_gmt":"2025-07-08T01:56:04","slug":"golang-%e5%a6%82%e4%bd%95%e8%8e%b7%e5%be%97-mux-%e7%9a%84%e6%8e%88%e6%9d%83%ef%bc%9f","status":"publish","type":"post","link":"https:\/\/server.hk\/cnblog\/207533\/","title":{"rendered":"Golang &#8211; \u5982\u4f55\u83b7\u5f97 mux \u7684\u6388\u6743\uff1f"},"content":{"rendered":"<p><b><\/b> <\/p>\n<p>\u5f53\u524d\u4f4d\u7f6e\uff1a <span>&gt;<\/span> <span>&gt;<\/span> <span>&gt;<\/span> <span>&gt;<\/span> <span>Golang &#8211; \u5982\u4f55\u83b7\u5f97 mux \u7684\u6388\u6743\uff1f<\/span><\/p>\n<p><span>\u6765\u6e90\uff1astackoverflow<\/span><br \/>\n<span>2024-04-23 13:27:34<\/span><br \/>\n<span><i><\/i>0\u6d4f\u89c8<\/span><br \/>\n<span style=\"cursor: pointer\"><i><\/i>\u6536\u85cf<\/span> <\/p>\n<p>\u5b66\u4e60<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">Golang<\/span>\u8981\u52aa\u529b\uff0c\u4f46\u662f\u4e0d\u8981\u6025\uff01\u4eca\u5929\u7684\u8fd9\u7bc7\u6587\u7ae0<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">\u300aGolang &#8211; \u5982\u4f55\u83b7\u5f97 mux \u7684\u6388\u6743\uff1f\u300b<\/span>\u5c06\u4f1a\u4ecb\u7ecd\u5230<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\"><\/span>\u7b49\u7b49\u77e5\u8bc6\u70b9\uff0c\u5982\u679c\u4f60\u60f3\u6df1\u5165\u5b66\u4e60<span style=\"color: #FF6600;, Helvetica, Arial, sans-serif;font-size: 14px;background-color: #FFFFFF\">Golang<\/span>\uff0c\u53ef\u4ee5\u5173\u6ce8\u6211\uff01\u6211\u4f1a\u6301\u7eed\u66f4\u65b0\u76f8\u5173\u6587\u7ae0\u7684\uff0c\u5e0c\u671b\u5bf9\u5927\u5bb6\u90fd\u80fd\u6709\u6240\u5e2e\u52a9\uff01<\/p>\n<p> \u95ee\u9898\u5185\u5bb9<br \/>\n <\/p>\n<p>\u6211\u662f golang \u7684\u65b0\u624b\uff0c\u6211\u5f00\u59cb\u4f7f\u7528 jwt \u5b66\u4e60 gorilla\/mux\u3002<\/p>\n<p>\u6211\u521a\u521a\u6210\u529f\u6ce8\u518c\u7528\u6237\u5230 mongodb\uff0c\u7136\u540e\u767b\u5f55\u3002 \u6211\u7528postman\u6765\u6d4b\u8bd5\u3002\u4f46\u662f\u5f53\u6211\u5c1d\u8bd5\u6d4f\u89c8\u53d7\u4fdd\u62a4\u7684\u8def\u7ebf\u65f6\u3002 \u6211\u5728\u9a8c\u8bc1\u4e2d\u6536\u5230\u9519\u8bef\u201c\u7f3a\u5c11\u8eab\u4efd\u9a8c\u8bc1\u4ee4\u724c\u201d\u3002<\/p>\n<p>\u90ae\u9012\u5458\u5982\u4f55\u83b7\u5f97\u6d4f\u89c8\u53d7\u4fdd\u62a4\u8def\u7531\u7684\u6388\u6743\uff1f<\/p>\n<p>\u4e0b\u9762\u662f\u6ce8\u518c\u548c\u767b\u5f55\u7684\u4ee3\u7801\uff1a<\/p>\n<p> \u8def\u7531\u5668\u529f\u80fd <\/p>\n<pre>func router() *mux.router {\n\n    router := mux.newrouter().strictslash(true)\n  router.use(commonmiddleware)\n\n  \/\/router.handlefunc(\"\/\", middleware.testapi).methods(\"get\", \"options\")\n  router.handlefunc(\"\/register\", middleware.registerhandler).methods(\"post\", \"options\")\n  router.handlefunc(\"\/login\", middleware.loginhandler).methods(\"post\", \"options\")\n\n  secure := router.pathprefix(\"\/auth\").subrouter()\n  secure.use(auth.jwtverify)\n\n    secure.handlefunc(\"\/api\/task\", middleware.getalltask).methods(\"get\", \"options\")\n    secure.handlefunc(\"\/api\/task\", middleware.createtask).methods(\"post\", \"options\")\n    secure.handlefunc(\"\/api\/task\/{id}\", middleware.taskcomplete).methods(\"put\", \"options\")\n    secure.handlefunc(\"\/api\/undotask\/{id}\", middleware.undotask).methods(\"put\", \"options\")\n    secure.handlefunc(\"\/api\/deletetask\/{id}\", middleware.deletetask).methods(\"delete\", \"options\")\n    secure.handlefunc(\"\/api\/deletealltask\", middleware.deletealltask).methods(\"delete\", \"options\")\n    return router\n}\n\nfunc commonmiddleware(next http.handler) http.handler {\n  return http.handlerfunc(func(w http.responsewriter, r *http.request) {\n    w.header().add(\"content-type\", \"application\/json\")\n    w.header().set(\"access-control-allow-origin\", \"*\")\n    w.header().set(\"access-control-allow-methods\", \"post, get, options, put, delete\")\n    w.header().set(\"access-control-allow-headers\", \"accept, content-type, content-length, accept-encoding, x-csrf-token, authorization, access-control-request-headers, access-control-request-method, connection, host, origin, user-agent, referer, cache-control, x-header\")\n    next.servehttp(w, r)\n  })\n}<\/pre>\n<p> \u6ce8\u518c\u529f\u80fd <\/p>\n<pre>func registerhandler(w http.responsewriter, r *http.request) {\n  w.header().set(\"content-type\", \"application\/json\")\n  var user models.user\n  body, _ := ioutil.readall(r.body)\n  err := json.unmarshal(body, &amp;user)\n  var res models.responseresult\n  if err != nil {\n    res.error = err.error()\n    json.newencoder(w).encode(res)\n    return\n  }\n\n  var result models.user\n  err = usercollection.findone(context.todo(), bson.d{{\"username\", user.username}}).decode(&amp;result)\n\n  if err != nil {\n    if err.error() == \"mongo: no documents in result\" {\n      hash, err := bcrypt.generatefrompassword([]byte(user.password), 5)\n\n      if err != nil {\n        res.error = \"error while hashing password, try again\"\n        json.newencoder(w).encode(res)\n        return\n      }\n      user.password = string(hash)\n\n      _, err = usercollection.insertone(context.todo(), user)\n      if err != nil {\n        res.error = \"error while creating user, try again\"\n        json.newencoder(w).encode(res)\n        return\n      }\n      res.result = \"register successful\"\n      json.newencoder(w).encode(res)\n      return\n    }\n    res.error = err.error()\n    json.newencoder(w).encode(res)\n    return\n  }\n  res.result = \"username already exists!!\"\n  json.newencoder(w).encode(res)\n  return\n}<\/pre>\n<p> \u767b\u5f55\u529f\u80fd <\/p>\n<pre>func loginhandler(w http.responsewriter, r *http.request) {\n  w.header().set(\"content-type\", \"application\/json\")\n  var user models.user\n  body, _ := ioutil.readall(r.body)\n  err := json.unmarshal(body, &amp;user)\n\n  if err != nil {\n    log.fatal(err)\n  }\n  \/\/var resulttoken models.token\n  var resultuser models.user\n  var res models.responseresult\n\n  err = usercollection.findone(context.todo(), bson.d{{\"username\", user.username}}).decode(&amp;resultuser)\n\n  if err != nil {\n    res.error = \"invalid username\"\n    json.newencoder(w).encode(res)\n    return\n  }\n\n  expiresat := time.now().add(time.minute * 100000).unix()\n\n  errf := bcrypt.comparehashandpassword([]byte(resultuser.password), []byte(user.password))\n\n  if errf != nil &amp;&amp; errf == bcrypt.errmismatchedhashandpassword {\n    var  res = map[string]interface{}{\"status\": false, \"message\": \"invalid login credential. please try again\"}\n    json.newencoder(w).encode(res)\n    return\n  }\n  tk := &amp;models.token{\n    username: user.username,\n    standardclaims: &amp;jwt.standardclaims{\n      expiresat: expiresat,\n    },\n  }\n\n  token := jwt.newwithclaims(jwt.getsigningmethod(\"hs256\"), tk)\n\n  tokenstring, err := token.signedstring([]byte(\"secret\"))\n\n  if err != nil {\n    res.error = \"error while generating token, try again\"\n    json.newencoder(w).encode(res)\n    return\n  }\n  var resp = map[string]interface{}{\"status\": false, \"message\": \"logged in\"}\n  resp[\"token\"] = tokenstring\n  resp[\"tk\"] = tk\n\n  json.newencoder(w).encode(resp)\n}<\/pre>\n<p> \u9a8c\u8bc1\u529f\u80fd <\/p>\n<pre>func JwtVerify(next http.Handler) http.Handler {\n  return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {\n    var header = r.Header.Get(\"x-access-token\")\n\n    json.NewEncoder(w).Encode(r)\n    header = strings.TrimSpace(header)\n\n    if header == \"\" {\n      w.WriteHeader(http.StatusForbidden)\n      json.NewEncoder(w).Encode(Exception{Message: \"Missing auth token\"})\n      return\n    }\n\n    tk := &amp;models.Token{}\n\n    _, err := jwt.ParseWithClaims(header, tk, func(token *jwt.Token) (interface{}, error) {\n      return []byte(\"secret\"), nil\n    })\n\n    if err != nil {\n      w.WriteHeader(http.StatusForbidden)\n      json.NewEncoder(w).Encode(Exception{Message: err.Error()})\n      return\n    }\n\n    ctx := context.WithValue(r.Context(), \"user\", tk)\n    next.ServeHTTP(w, r.WithContext(ctx))\n  })\n}<\/pre>\n<p> <\/p>\n<h2>\u89e3\u51b3\u65b9\u6848<\/h2>\n<p> <\/p>\n<p>\u7531\u4e8e\u60a8\u6b63\u5728\u68c0\u67e5\u8bf7\u6c42\u6807\u5934\u4e2d\u7684\u4ee4\u724c <code>x-access-token<\/code>\uff0c\u56e0\u6b64\u9700\u8981\u5728\u53d1\u9001\u8bf7\u6c42\u65f6\u6dfb\u52a0\u76f8\u540c\u7684\u4ee4\u724c\u3002\u8fd9\u53ef\u4ee5\u5728 postman \u4e2d\u8f7b\u677e\u5b8c\u6210\uff0c\u5982\u4e0b\u6240\u793a &#8211;<\/p>\n<\/p>\n<p>\u6211\u4f7f\u7528\u7684\u8def\u7531\u5668\u662f &#8211;<\/p>\n<p>\u4e3b\u5305<\/p>\n<pre>func router() *mux.router {\n    router := mux.newrouter().strictslash(true)\n    secure := router.pathprefix(\"\/auth\").subrouter()\n    secure.use(auth.jwtverify)\n    secure.handlefunc(\"\/api\", middleware.apihandler).methods(\"get\")\n    return router\n}\n\nfunc main() {\n    r := router()\n    http.listenandserve(\":8080\", r)\n}\n<\/pre>\n<p>\u6211\u4f7f\u7528\u7684\u4e2d\u95f4\u4ef6\u662f &#8211;<\/p>\n<p>\u5305\u6388\u6743<\/p>\n<pre>func jwtverify(next http.handler) http.handler {\n    return http.handlerfunc(func(w http.responsewriter, r *http.request) {\n        var header = r.header.get(\"x-access-token\")\n\n        json.newencoder(w).encode(r)\n        header = strings.trimspace(header)\n\n        if header == \"\" {\n            w.writeheader(http.statusforbidden)\n            json.newencoder(w).encode(\"missing auth token\")\n            return\n        } else {\n            json.newencoder(w).encode(fmt.sprintf(\"token found. value %s\", header))\n        }\n        next.servehttp(w, r)\n    })\n}\n<\/pre>\n<p>\u5904\u7406\u7a0b\u5e8f\u662f &#8211;<\/p>\n<p>\u5c01\u88c5\u4e2d\u95f4\u4ef6<\/p>\n<pre>func ApiHandler(w http.ResponseWriter, r *http.Request) {\n    w.WriteHeader(http.StatusOK)\n    w.Header().Set(\"Content-Type\", \"application\/json\")\n    json.NewEncoder(w).Encode(\"SUCCESS!\")\n    return\n}\n<\/pre>\n<p>\u60a8\u53ef\u4ee5\u5728\u6388\u6743\u90e8\u5206\u4f20\u9012\u4ee4\u724c\uff1a<\/p>\n<p>\u4ee5\u4e0a\u5c31\u662f\u300aGolang &#8211; \u5982\u4f55\u83b7\u5f97 mux \u7684\u6388\u6743\uff1f\u300b\u7684\u8be6\u7ec6\u5185\u5bb9\uff0c\u66f4\u591a\u5173\u4e8e\u7684\u8d44\u6599\u8bf7\u5173\u6ce8\u516c\u4f17\u53f7\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u5f53\u524d\u4f4d\u7f6e\uff1a &gt; &gt; &#46;&#46;&#46;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4925],"tags":[],"class_list":["post-207533","post","type-post","status-publish","format-standard","hentry","category-4925"],"_links":{"self":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/207533","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/comments?post=207533"}],"version-history":[{"count":0,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/posts\/207533\/revisions"}],"wp:attachment":[{"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/media?parent=207533"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/categories?post=207533"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/server.hk\/cnblog\/wp-json\/wp\/v2\/tags?post=207533"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}