《Web Development with Go》JWT认证满意版
2024-09-01 21:50:07
这个比昨晚的要满意,
认证放到中间件那里了。
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") }
最新文章
- Oracle 数据导入导出
- Java中前台JSP请求Servlet实例(http+Servlet)
- 一个noconsole程序
- JQuery中Ajax的Post提交中文乱码的解决方案
- Arrays.equals()
- 路径MTU
- Selenium索引
- Linux内核源代码解析——TCP状态转移图以及其实现
- 选址问题lingo求解
- HDU 4291 A Short problem(2012 ACM/ICPC Asia Regional Chengdu Online)
- spring +springmvc+mybatis组合总结
- I2C 读取总是 0xFF,但是 ACK 是正常的解决方法
- listview的工作原理
- 51nod1172 Partial Sums V2
- 【资料】Mac OS X 10.9虚拟机镜像及tools
- JavaScript 基础(一) - JavaScript的引入方式,JavaScript 变量命名规则,JS 的五种基本数据类型,ECMAScript 算数运算符,逻辑运算符
- Codeforces 1111D Destroy the Colony 退背包 (看题解)
- 读取 exe dll 自定义config 文件
- Windows 多用户接续设置
- SSH-运行main函数,一直报空指针,调依赖注入配置的dao
热门文章
- python 金融应用(三)数据可视化
- 毕业半年,买了一台MacBook Pro
- VS编译命令
- 不启动AndroidStudio直接启动其模拟器
- ES6中export default与export的区别
- 【朝花夕拾】Android多线程之(三)runOnUiThread篇——程序猿们的贴心小棉袄
- django基础之day08,利用bulk_create 批量插入成千上万条数据
- 区块链学习——HyperLedger-Fabric v1.0环境搭建详细教程
- Caffe源码-Blob类
- 原生js复制粘贴上传图片前后台代码,兼容firebox,chrome, ie11,亲测有效