使用JWT

时间:2017-11-05 00:06:41

标签: go authorization jwt

我对go-kit和微服务架构也很陌生。

我有一个JWT,其中包含经过身份验证的用户ID作为声明,以及每个服务的方法,我想检查用户是否有权更新自己的客户端记录,但似乎无处不在我说,感觉不对。做这样的事情的最佳做法是什么?

// client.go
type Client struct {
    ID     string `json:"id"`
    UserID string `json:"user_id"`
    // ...
}

type ClientDataLayer interface {
    Load(db *sql.DB, id string) *Client
    Update(db *sql.DB, cl *Client) *Client
    // ... more CRUD methods
}

在服务中间件中执行此操作我将不得不调用另一个服务的方法,这似乎打破了体系结构的目的:

// service.go
type Service interface {
    UpdateClient(ctx context.Context, cl *Client) (*Client, error)
    // ... more methods
}

func NewClientService(db *sql.DB, cdl ClientDataLayer) {
    // ....
}

type service struct {
    db  *sql.DB
    cdl ClientDataLayer
}

func (svc *service) UpdateClient(ctx context.Context, id string) (*Client, error) {
    return nil, nil
}

// service middleware
type accessControl struct {
    svc Service
}

func (ac *accessControl) UpdateClient(ctx context.Context, cl *Client) (*Client, error) {
    // ... get token and claims from context
    // scopes := jwt.Claims().Get("scopes")

    // Here I don't have the client's user_id, 
    // and it does not feel right to call another service's method
    if !strings.Contains(scopes, "client:write") || cl.UserID != userID {
        return nil, errors.New("forbidden")
    }

    // ...
    return nil, nil
}

在端点上执行它几乎相同的

// transport.go
func makeUpdateClientEndpoint(svc Service) endpoint.Endpoint {
    return func(ctx context.Context, request interface{}) (interface{}, error) {
        // type cast request
        // ... get token and claims from context
        // scopes := jwt.Claims().Get("scopes")

        // Same problem as before, I don't have the client's user_id

        if !strings.Contains(scopes, "client:write") || cl.UserID != userID {
            return nil, errors.New("forbidden")
        }

        cl, _ := svc.UpdateClient(ctx, request.ClientID)

        // ...

        return nil, nil
    }
}

我可能会通过使用ClientDataLayer来检索客户端并检查用户的ID。作为一种避免混淆另一种服务方法来加载客户端的方法,因为它可能还有用于日志记录或度量的中间件。

我怎么能在没有那么多麻烦的情况下实现这一目标?我想打破模式?

0 个答案:

没有答案