首页

Go web使用串联处理器函数登陆与写日志

假如我们需要在每次请求时,记录下每个处理器函数的日志;或者在请求需要登陆后才可见的页面时做一个统一认证,那么串联多个处理器函数就可以轻松实现这些功能。Go语言虽不是一门函数式编程语言,但它拥有一些函数式编程语言特性,如函数类型,匿名函数和闭包。我么可以将一个函数传递给另一个函数。

下面这个代码例子就演示了两个功能,一个登陆,一个写日志,没有引入第三方包,全部是标准库:
    package main

    import (
        "fmt"
        "net/http"
        "reflect"
        "runtime"
        "time"
    )

    // 处理器函数
    func hello(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello!")
    }

    // 记录请求日志,在运行时,将处理器函数的名字通过反射拿到,一并写入日志
    func log(h http.HandlerFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            name := runtime.FuncForPC(reflect.ValueOf(h).Pointer()).Name()
            fmt.Println("Handler function called - " + name)
            h(w, r)
        }
    }

    // 认证保护
    func protect(h http.HandlerFunc) http.HandlerFunc {
        return func(w http.ResponseWriter, r *http.Request) {
            if ok := Check(r); ok {
                h(w, r)
            } else {
                http.Error(w, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
            }
        }
    }

    // 登陆,保存cookie
    func login(w http.ResponseWriter, r *http.Request) {
        expiration := time.Now()
        expiration = expiration.AddDate(0, 0, 1)
        uidCookie := http.Cookie{Name: "userid", Value: "token", Expires: expiration}
        http.SetCookie(w, &uidCookie)
        fmt.Fprintf(w, "login is ok!")
    }

    // 简单的cookie认证
    func Check(r *http.Request) bool {
        uidCookie, _ := r.Cookie("userid")
        if uidCookie == nil {
            return false
        }

        if uidCookie.Value == "token" {
            return true
        }

        return false
    }

    func main() {
        server := http.Server{
            Addr: "127.0.0.1:8080",
        }

        http.HandleFunc("/login", login)
        http.HandleFunc("/hello", protect(log(hello)))
        server.ListenAndServe()
    }
代码非常简单,一个写日志的函数(写日志时,记录是哪个函数调用,方便日后查错),一个认证保护的函数(这里简单实用cookie认证,如在生产环境可以做加密,会话等),一个cookie认证,还有两个处理器函数,分别是hello,login。我们也可以只写日志,或者只需要认证保护:log(hello)、protect(hello),下面一步步来演示它:

第一步:执行代码
> go run server.go

第二步:在浏览器输入 http://localhost:8080/hello

在没有登陆,没有把cookie写入客户端情况下,访问被保护的页面是显示无权访问,这样就可以保护我们需要登陆认证的页面。

第三步:在浏览器输入 http://localhost:8080/login

请求这个页面就是写入cookie到客户端,也就是我们常常的登陆请求,这里是简单的写cookie,生产环境的要复杂一些。

第四步:在浏览器再次输入 http://localhost:8080/hello

这次再访问这个页面就可以看见我们想要看的内容了,认证通过。
from 爱施园
Posted by 森林 on 2019/01/17
Copyright ©2018 爱施园 粤ICP备14091834号