как применять роли в промежуточных маршрутах - PullRequest
0 голосов
/ 18 октября 2019

я хочу установить авторизацию промежуточного программного обеспечения с ролями в golang, ограничить некоторые API ролями, например, для доступа администратора ко всем API, для работников1 некоторые из API

Я сделал авторизацию с помощью jwt и middleware, сейчася пытаюсь внедрить роли в существующий код

Пакет авторизации

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
}

Функция проверки JWT

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)
    })
}

КакМогу ли я реализовать роли в этом коде?

1 Ответ

1 голос
/ 18 октября 2019

Я предполагаю, mux это gorilla/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 и, используя справочную таблицу, определяет, включает ли роль пользователя имя маршрута.

...