这个比昨晚的要满意,
认证放到中间件那里了。
Mux使用的是gorilla,
中间件使用的是negroni,
启动是用的negroni.classic方法。
package main import ( "encoding/json" "fmt" "io/ioutil" "log" "net/http" "time" "github.com/codegangsta/negroni" jwt "github.com/dgrijalva/jwt-go" "github.com/dgrijalva/jwt-go/request" "github.com/gorilla/mux" ) // using asymmetric crypto/RSA keys // location of the files used for signing and verification const ( privKeyPath = "keys/app.rsa" // openssl genrsa -out app.rsa 1024 pubKeyPath = "keys/app.rsa.pub" // openssl rsa -in app.rsa -pubout > app.rsa.pub ) const ( SecretKey = "welcome to wangshubo‘s blog" ) // verify key and sign key var ( verifyKey, signKey []byte ) //struct User for parsing login credentials type User struct { UserName string `json:"username"` Password string `json:"password"` } // read the key files before starting http handlers func init() { var err error signKey, err = ioutil.ReadFile(privKeyPath) if err != nil { log.Fatal("Error reading private key") return } verifyKey, err = ioutil.ReadFile(pubKeyPath) if err != nil { log.Fatal("Error reading private key") return } } func authMiddleware(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) { // validate the token pubKey, err := jwt.ParseRSAPublicKeyFromPEM(verifyKey) if err != nil { fmt.Println("ParseRSAPublicKeyFromPEM:", err.Error()) return } token, err := request.ParseFromRequest(r, request.AuthorizationHeaderExtractor, func(token *jwt.Token) (interface{}, error) { // since we only use one private key to sign the tokens, // we also only use its public counter part to verify return pubKey, nil }) if err == nil && token.Valid { next(w, r) } else { w.WriteHeader(http.StatusUnauthorized) fmt.Fprint(w, "Authentication failed") } } // reads the login credentials, checks them and creates JWT the token func loginHandler(w http.ResponseWriter, r *http.Request) { var user User //decode into User struct err := json.NewDecoder(r.Body).Decode(&user) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintln(w, "Error in request body") return } log.Println(user.UserName, user.Password) // validate user credentials if user.UserName != "shijuvar" || user.Password != "pass" { w.WriteHeader(http.StatusForbidden) fmt.Fprintln(w, "Wrong info") return } // create a signer for rsa 256 t := jwt.New(jwt.SigningMethodRS256) // set our claims claims := make(jwt.MapClaims) claims["iss"] = "admin" claims["CustomUserInfo"] = struct { Name string Role string }{user.UserName, "Member"} claims["exp"] = time.Now().Add(time.Minute * 20).Unix() t.Claims = claims priKey, err := jwt.ParseRSAPrivateKeyFromPEM(signKey) if err != nil { fmt.Println("ParseRSAPrivateKeyFromPEM:", err.Error()) return } tokenString, err := t.SignedString(priKey) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintln(w, "Sorry, error while Signing Token!") log.Printf("Token Signing error: %v\n", err) return } response := Token{tokenString} jsonResponse(response, w) } // only accessible with a valid token func authHandler(w http.ResponseWriter, r *http.Request) { response := Response{"Authorized to the system"} jsonResponse(response, w) } type Response struct { Text string `json:"text"` } type Token struct { Token string `json:"token"` } func jsonResponse(response interface{}, w http.ResponseWriter) { json, err := json.Marshal(response) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") w.Write(json) } //Entry point of the program func main() { r := mux.NewRouter() r.HandleFunc("/login", loginHandler).Methods("POST") r.Handle("/auth", negroni.New( negroni.HandlerFunc(authMiddleware), negroni.Wrap(http.HandlerFunc(authHandler)), )).Methods("POST") n := negroni.Classic() n.UseHandler(r) n.Run(":8080") }
原文地址:https://www.cnblogs.com/aguncn/p/12004610.html
时间: 2024-10-26 17:38:39