141 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2014 beego Author. All Rights Reserved.
 | 
						|
//
 | 
						|
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
// you may not use this file except in compliance with the License.
 | 
						|
// You may obtain a copy of the License at
 | 
						|
//
 | 
						|
//      http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
//
 | 
						|
// Unless required by applicable law or agreed to in writing, software
 | 
						|
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
// See the License for the specific language governing permissions and
 | 
						|
// limitations under the License.
 | 
						|
 | 
						|
// Package jwt provides JWT (Json Web Token) authentication
 | 
						|
//
 | 
						|
// Usage
 | 
						|
// In file main.go
 | 
						|
//
 | 
						|
//	import (
 | 
						|
// 		"github.com/astaxie/beego"
 | 
						|
//		"github.com/astaxie/beego/plugins/jwt"
 | 
						|
// )
 | 
						|
//
 | 
						|
//	func main() {
 | 
						|
//		// JWT for Url matching /v1/*
 | 
						|
//		// PrivateKeyPath: The path for the private RSA key used by JWT
 | 
						|
//		// PublicKeyPath: The path for the public RSA key used by JWT
 | 
						|
//		// The list of Urls should be excluded from the JWT Auth
 | 
						|
//		beego.InsertFilter("/v1/*", beego.BeforeRouter, jwt.AuthRequest(&jwt.Options{
 | 
						|
//			PrivateKeyPath: "conf/beeblog.rsa",
 | 
						|
//			PublicKeyPath:  "conf/beeblog.rsa.pub",
 | 
						|
//			WhiteList:      []string{"/v1/jwt/issue-token", "/docs"},
 | 
						|
//		}))
 | 
						|
//		beego.Run()
 | 
						|
//	}
 | 
						|
//
 | 
						|
// In file routers/router.go
 | 
						|
//
 | 
						|
//	import (
 | 
						|
// 		"github.com/astaxie/beego"
 | 
						|
//		"github.com/astaxie/beego/plugins/jwt"
 | 
						|
// )
 | 
						|
//	func init() {
 | 
						|
//		ns := beego.NSNamespace("/jwt",
 | 
						|
//			beego.NSInclude(
 | 
						|
//				&jwt.JwtController{},
 | 
						|
//			),
 | 
						|
//		)
 | 
						|
//		beego.AddNamespace(ns)
 | 
						|
//	}
 | 
						|
//
 | 
						|
package jwt
 | 
						|
 | 
						|
import (
 | 
						|
	"io/ioutil"
 | 
						|
	"net/http"
 | 
						|
	"time"
 | 
						|
 | 
						|
	"github.com/astaxie/beego"
 | 
						|
	"github.com/astaxie/beego/context"
 | 
						|
	"github.com/astaxie/beego/logs"
 | 
						|
	goJwt "github.com/dgrijalva/jwt-go"
 | 
						|
)
 | 
						|
 | 
						|
// Options for the JWT Auth
 | 
						|
type Options struct {
 | 
						|
	PrivateKeyPath string
 | 
						|
	PublicKeyPath  string
 | 
						|
	WhiteList      []string
 | 
						|
}
 | 
						|
 | 
						|
// RSAKeys store PrivateKey and PublicKey
 | 
						|
var RSAKeys struct {
 | 
						|
	PrivateKey []byte
 | 
						|
	PublicKey  []byte
 | 
						|
}
 | 
						|
 | 
						|
// AuthRequest retunn FilterFunc
 | 
						|
func AuthRequest(o *Options) beego.FilterFunc {
 | 
						|
	RSAKeys.PrivateKey, _ = ioutil.ReadFile(o.PrivateKeyPath)
 | 
						|
	RSAKeys.PublicKey, _ = ioutil.ReadFile(o.PublicKeyPath)
 | 
						|
 | 
						|
	return func(ctx *context.Context) {
 | 
						|
		// :TODO the url patterns should be considered here.
 | 
						|
		// Shouldn't only use the string equal
 | 
						|
		for _, method := range o.WhiteList {
 | 
						|
			if method == ctx.Request.URL.Path {
 | 
						|
				return
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		parsedToken, err := goJwt.ParseFromRequest(ctx.Request, func(t *goJwt.Token) (interface{}, error) {
 | 
						|
			return RSAKeys.PublicKey, nil
 | 
						|
		})
 | 
						|
 | 
						|
		if err == nil && parsedToken.Valid {
 | 
						|
			ctx.Output.SetStatus(http.StatusOK)
 | 
						|
		} else {
 | 
						|
			ctx.Output.SetStatus(http.StatusUnauthorized)
 | 
						|
		}
 | 
						|
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
// Controller oprations for Jwt
 | 
						|
type Controller struct {
 | 
						|
	beego.Controller
 | 
						|
}
 | 
						|
 | 
						|
// URLMapping is used to mapping the string to method
 | 
						|
func (c *Controller) URLMapping() {
 | 
						|
	c.Mapping("IssueToken", c.IssueToken)
 | 
						|
}
 | 
						|
 | 
						|
// IssueToken function
 | 
						|
// @Title IssueToken
 | 
						|
// @Description Issue a Json Web Token
 | 
						|
// @Success 200 string
 | 
						|
// @Failure 403 no privilege to access
 | 
						|
// @Failure 500 server inner error
 | 
						|
// @router /issue-token [get]
 | 
						|
func (c *Controller) IssueToken() {
 | 
						|
	c.Data["json"] = CreateToken()
 | 
						|
	c.ServeJSON()
 | 
						|
}
 | 
						|
 | 
						|
// CreateToken return the token
 | 
						|
func CreateToken() map[string]string {
 | 
						|
	log := logs.NewLogger(10000)
 | 
						|
	log.SetLogger("console", "")
 | 
						|
 | 
						|
	token := goJwt.New(goJwt.GetSigningMethod("RS256")) // Create a Token that will be signed with RSA 256.
 | 
						|
	token.Claims["ID"] = "This is my super fake ID"
 | 
						|
	token.Claims["exp"] = time.Now().Unix() + 36000
 | 
						|
	// The claims object allows you to store information in the actual token.
 | 
						|
	tokenString, _ := token.SignedString(RSAKeys.PrivateKey)
 | 
						|
	// tokenString Contains the actual token you should share with your client.
 | 
						|
	return map[string]string{"token": tokenString}
 | 
						|
}
 |