如何在中间件路由中应用角色



我想在 golang 中使用角色设置中间件授权,将某些 API 限制为角色,例如用于管理员访问所有 API,对于 workers1 一些 API

我已经完成了 jwt 和中间件的授权,现在我试图将角色注入到现有代码中

授权包

func Login(w http.ResponseWriter, r *http.Request) {
user := &models.User{}
err := json.NewDecoder(r.Body).Decode(user)
if err != nil {
var resp = map[string]interface{}{"status": false, "message": "Ivalid request"}
json.NewEncoder(w).Encode(resp)
return
}
resp := FindOne(user.Email, user.Password)
json.NewEncoder(w).Encode(resp)
}
func FindOne(email, password string) map[string]interface{} {
user := &models.User{}
if err := database.DBGORM.Where("Email = ?", email).First(user).Error; err != nil {
var resp = map[string]interface{}{"status": false, "message": "Email address not found"}
return resp
}
expiresAt := time.Now().Add(time.Minute * 5).Unix()
errf := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
if errf != nil && errf == bcrypt.ErrMismatchedHashAndPassword { //Password does not match!
var resp = map[string]interface{}{"status": false, "message": "Invalid login credentials. Please try again"}
return resp
}
tk  := &models.Token{
UserID: user.ID,
Name:   user.Name,
Email:  user.Email,
Role: user.Role,
StandardClaims: &jwt.StandardClaims{
ExpiresAt: expiresAt,
},
}
token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), tk)
tokenString, error := token.SignedString([]byte("secret"))
if error != nil {
fmt.Println(error)
}
var resp = map[string]interface{}{"status": false, "message": "logged in"}
resp["token"] = tokenString //Store the token in the response
return resp
}

智威汤逊验证功能

func JwtVerify(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var header = r.Header.Get("x-access-token") //Grab the token from the header
header = strings.TrimSpace(header)
if header == "" {
//Token is missing, returns with error code 403 Unauthorized
w.WriteHeader(http.StatusForbidden)
json.NewEncoder(w).Encode(Exception{Message: "Missing auth token"})
return
}
tk := &models.Token{}
_, err := jwt.ParseWithClaims(header, tk, func(token *jwt.Token) (interface{}, error) {
return []byte("secret"), nil
})
if err != nil {
w.WriteHeader(http.StatusForbidden)
json.NewEncoder(w).Encode(Exception{Message: err.Error()})
return
}
ctx := context.WithValue(r.Context(), "user", tk)
next.ServeHTTP(w, r.WithContext(ctx)) 
})
}

这是路线

func Handlers()  *mux.Router {
router := mux.NewRouter().StrictSlash(true)
router.Use(CommonMiddleWare)
router.HandleFunc("/api/login", controller.Login)
router.HandleFunc("/api/register", controller.CreateUser)
router.HandleFunc("/api/getclientbylogin/login={login}", controller.GetNowClientHardwareByLogin).Methods("GET")
router.HandleFunc("/api/getclientbyname/fullname={lname}&{fname}&{sname}", controller.GetProfilesByFullNames).Methods("GET")
router.HandleFunc("/api/getaddress/{type}={value}", controller.GetLocation).Methods("GET")
router.HandleFunc("/api/getfullnames/{type}", controller.GetNames).Methods("GET")
router.HandleFunc("/api/operstatus={login}", controller.CheckEquipment).Methods("GET")
router.HandleFunc("/api/cablediagnostic={login}", controller.CheckInventory).Methods("GET")
s := router.PathPrefix("/auth").Subrouter()
s.Use(utils.JwtVerify)
s.HandleFunc("/api/getname/{type}={value}", controller.GetName).Methods("GET")

return router
}
func CommonMiddleWare(next http.Handler) http.Handler  {
return http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
res.Header().Add("Content-type", "application/json")
res.Header().Set("Access-Control-Allow-Origin", "*")
res.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
res.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")
next.ServeHTTP(res, req)
})
}

如何实现此代码的角色?

我假设muxgorilla/mux.这与我在项目中所做的很接近:

首次注册具有以下名称的路由:

router.HandleFunc("/api/register", controller.CreateUser).Name("createUser")

然后使用中间件中的该名称执行角色/方法查找:

currentRoute:=mux.CurrentRoute(request)
if currentRoute!=nil {
if !checkRole(ctx,currentRoute.GetName()) {
// return 403
}
}

其中checkRole是从 ctx 获取用户角色的函数,使用查找表确定用户的角色是否包含路由名称。

最新更新