Чтобы обеспечить безопасность и стабильность системы и защитить безопасность пользовательских данных, в службу обычно вводятся методы аутентификации личности для безопасного перехвата, проверки и фильтрации запросов пользователей. Обычно используемые методы аутентификации:
- JWT: JWT предоставляет метод выдачи токена доступа (токена доступа) и проверки выданного подписанного токена доступа. Сам токен содержит ряд утверждений, согласно которым приложение может ограничить доступ пользователя к ресурсу.
- OAuth2: OAuth2 — это структура авторизации, которая предоставляет подробный набор механизмов авторизации (руководство). Пользователи или приложения могут разрешать сторонним приложениям доступ к определенным ресурсам с помощью общедоступных или частных настроек.
- Базовая: аутентификация по имени пользователя и паролю, которая выполняется с каждым запросом, что не является безопасным.
Практическая тренировка
В этой статье будет представлен механизм проверки jwt в микросервисе go-kit для реализации выпуска и проверки токена. Принцип jwt больше не разрабатывается, и вы можете обратиться к последней ссылке. Кратко опишу идею реализации:
- Создайте новый интерфейс входа и проверьте имя пользователя и пароль. Проверка возвращается клиенту путем создания токена.
- Добавьте механизм проверки токена в интерфейс расчета, который инкапсулируется промежуточным программным обеспечением, предоставляемым go-kit.
- В этом примере используется реализация go стороннего jwt.
dgrijalva/jwt-go
Шаг 1: Подготовка кода
Скопируйте каталог arithmetic_circuitbreaker_demo, переименуйте его в arithmetic_jwt_demo и переименуйте каталог регистров в service.
Установите зависимую стороннюю библиотеку jwt:
go get github.com/dgrijalva/jwt-go
Шаг 2: Создайте jwt.go
существуетservice
Создайте файл в каталогеjwt.go
.
- Сначала определите ключ, необходимый для генерации токена (это самое важное в jwt, и его нельзя упускать).
- 自定义声明。 существует
StandardClaims
ДобавленUserId
,Name
Два поля, другие поля, такие как роли, могут быть расширены в соответствии с фактическими потребностями. - определение
keyfunc
, этот метод используется как callback-функция при проверке токена, что будет описано позже. - Определить метод для создания токена
Sign
. Здесь для генерации напрямую вызывается сторонняя библиотека jwt, а время истечения токена установлено на 2 минуты для удобства демонстрации.
следующееjwt.go
Весь код:
//secret key
var secretKey = []byte("abcd1234!@#$")
// ArithmeticCustomClaims 自定义声明
type ArithmeticCustomClaims struct {
UserId string `json:"userId"`
Name string `json:"name"`
jwt.StandardClaims
}
// jwtKeyFunc 返回密钥
func jwtKeyFunc(token *jwt.Token) (interface{}, error) {
return secretKey, nil
}
// Sign 生成token
func Sign(name, uid string) (string, error) {
//为了演示方便,设置两分钟后过期
expAt := time.Now().Add(time.Duration(2) * time.Minute).Unix()
// 创建声明
claims := ArithmeticCustomClaims{
UserId: uid,
Name: name,
StandardClaims: jwt.StandardClaims{
ExpiresAt: expAt,
Issuer: "system",
},
}
//创建token,指定加密算法为HS256
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
//生成token
return token.SignedString(secretKey)
}
Шаг 3. Добавьте интерфейс входа в систему.
Сервисный уровень: добавьте новый интерфейс входа в систему в соответствии с архитектурой go-kit, чтобы:
- Добавлен метод входа в интерфейс службы.
- Реализуйте метод Login в ArithmeticService: проверьте имя пользователя и пароль и вызовите метод Sign jwt для создания маркера;
- Реализовать метод Login в loggingMiddleware;
- Реализовать метод Login в metricMiddleware;
// Service Define a service interface
type Service interface {
//……
// HealthCheck
Login(name, pwd string) (string, error)
}
func (s ArithmeticService) Login(name, pwd string) (string, error) {
if name == "name" && pwd == "pwd" {
token, err := Sign(name, pwd)
return token, err
}
return "", errors.New("Your name or password dismatch")
}
Уровень конечной точки: новый запрашивает интерфейс входа в систему и требуемую структуру объекта ответа, метод подготовки, созданный конечной точкой.
// AuthRequest
type AuthRequest struct {
Name string `json:"name"`
Pwd string `json:"pwd"`
}
// AuthResponse
type AuthResponse struct {
Success bool `json:"success"`
Token string `json:"token"`
Error string `json:"error"`
}
func MakeAuthEndpoint(svc Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
req := request.(AuthRequest)
token, err := svc.Login(req.Name, req.Pwd)
var resp AuthResponse
if err != nil {
resp = AuthResponse{
Success: err == nil,
Token: token,
Error: err.Error(),
}
} else {
resp = AuthResponse{
Success: err == nil,
Token: token,
}
}
return resp, nil
}
}
Транспортный уровень: напишите методы декодирования и кодирования и добавьте маршрутизацию интерфейса входа в систему. При этом в интерфейс calculate добавлена логика обнаружения токена: перед обработкой запроса из заголовка HTTP-запроса считывается аутентификационная информация, и в случае успешного чтения добавляется контекст запроса. Здесь непосредственно используется метод HTTPToContext, предоставляемый go-kit.
func decodeLoginRequest(_ context.Context, r *http.Request) (interface{}, error) {
var loginRequest AuthRequest
if err := json.NewDecoder(r.Body).Decode(&loginRequest); err != nil {
return nil, err
}
return loginRequest, nil
}
func encodeLoginResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
w.Header().Set("Content-Type", "application/json;charset=utf-8")
return json.NewEncoder(w).Encode(response)
}
Добавьте http-маршрут:
r.Methods("POST").Path("/calculate/{type}/{a}/{b}").Handler(kithttp.NewServer(
endpoints.ArithmeticEndpoint,
decodeArithmeticRequest,
encodeArithmeticResponse,
//增加了options
append(options, kithttp.ServerBefore(kitjwt.HTTPToContext()))...,
))
// ...
r.Methods("POST").Path("/login").Handler(kithttp.NewServer(
endpoints.AuthEndpoint,
decodeLoginRequest,
encodeLoginResponse,
options...,
))
Шаг 4: Изменить main.go
Разверните исходные ArithmeticEndpoints, добавьте AuthEndpoint, добавьте код логики создания AuthEndpoint и добавьте упаковку, такую как текущее ограничение и отслеживание ссылок.
//身份认证Endpoint
authEndpoint := MakeAuthEndpoint(svc)
authEndpoint = NewTokenBucketLimitterWithBuildIn(ratebucket)(authEndpoint)
authEndpoint = kitzipkin.TraceEndpoint(zipkinTracer, "login-endpoint")(authEndpoint)
//把算术运算Endpoint\健康检查、登录Endpoint封装至ArithmeticEndpoints
endpts := ArithmeticEndpoints{
ArithmeticEndpoint: calEndpoint,
HealthCheckEndpoint: healthEndpoint,
AuthEndpoint: authEndpoint,
}
Поскольку мы требуем, чтобы доступ к интерфейсу расчета был возможен только тогда, когда токен действителен, добавьте код проверки токена в calEndpoint (последняя строка кода, напрямую используйте промежуточное программное обеспечение, предоставленное go-kit):
calEndpoint := MakeArithmeticEndpoint(svc)
calEndpoint = NewTokenBucketLimitterWithBuildIn(ratebucket)(calEndpoint)
calEndpoint = kitzipkin.TraceEndpoint(zipkinTracer, "calculate-endpoint")(calEndpoint)
calEndpoint = kitjwt.NewParser(jwtKeyFunc, jwt.SigningMethodHS256, kitjwt.StandardClaimsFactory)(calEndpoint)
Шаг 5: Запустите и протестируйте
пройти черезdocker-compose
Запустите консул, зипкин, hystrix-dashboard, затем запустите Gateyway, наконец, запустите сервис (указав консул и адреса сервисов).
Установите запрос POST http://localhost:9090/arithmetic/login в Postman, а тело будет следующим:
{
"name": "name",
"pwd": "pwd"
}
Можно увидеть следующие результаты:
Затем запросите интерфейс расчета и установите авторизацию в заголовке, результат будет следующим:
Через две минуты проверьте еще раз, вы обнаружите, что срок действия возвращенного токена истек.
Суммировать
В этой статье собраны примеры внедрения jwt в микросервисы go-kit. Добавлен интерфейс входа в систему, так что интерфейс расчета может работать только тогда, когда токен действителен. Благодаря характеристикам аутентификации jwt действительность токена, запрошенного пользователем после успешного входа в систему, больше не зависит от центра аутентификации.По сравнению с OAuth2 это может значительно снизить нагрузку на центр аутентификации, упрощая горизонтальное расширение микросервисов. .
использованная литература
- Пример кода для этой статьи @github
- Руководство по началу работы с JSON Web Token (Yifeng Ruan)
- официальный сайт ДВТ
- dgrijalva/jwt-go (реализация JWT на ходу)
Эта статья была впервые опубликована в моей публичной учетной записи WeChat [Xi Yiang Bar], пожалуйста, отсканируйте код, чтобы следовать!