基于servicecomb-mesher的网关认证鉴权方案

点击上方蓝色字体,关注我们

基于servicecomb-mesher的网关认证鉴权方案_第1张图片

【Apache ServiceComb 黑客松编程竞赛】微服务化的AI web相册正在火热报名中,超多好礼等你来拿!详情戳上图

背景

Servicecomb-mesher 是 Apache servicecomb 的微服务网格项目。Mesher 实际上在应用层作为一个代理,拦截并代替业务服务发起和接收请求,为服务添加治理功能。Mesher同时可以也可以用作微服务的网关,在网关模式下,Mesher需要提供为用户实现的认证功能提供框架能力。现在比较流行的一种认证模式是:用户不用再注册账号,直接利用已有的Google,Github, QQ等账号登录,mesher作为网关应当实现第三方登录功能。提高开发者的开发效率,和用户的使用体验。

目前oauth2授权框架使用最广泛,上述过程的实质是:mesher使用oauth2协议获得第三方应用访问其用户信息(我们关注的是唯一信息,可能是用户名,也可能是OpenID、UserID)的授权,获取该用户信息后,用该用户信息实现认证。

开发者如何使用Mesher OAuth2 认证能力

以通过Github账号认证为例:

1. 注册你的应用,访问这个链接(https://github.com/settings/applications/new),填写相应的信息,其中callback_url填写为http(s)://yourdomain.com/oauth2_callback。获取ClientID,和ClientSecret。

2. 配置Mesher,在proxy/handler/oauth2 目录oauth2_handler文件中,添加如下代码,完成对mesher的配置:

Use(&OAuth2{
        GrantType: "authorization_code",
        UseConfig: &oauth2.Config{
        ClientID:     "",           // (required, string) your client_ID
        ClientSecret: "",           // (required, string) your client_Secret
        Scopes:       []string{""}, // (optional, string) scope specifies requested permissions
        RedirectURL:  "",           // (required, string) URL to redirect users going through the OAuth2 flow
        Endpoint: oauth2.Endpoint{ // (required, string) your auth server endpoint
            AuthURL:  "https://github.com/login/oauth/authorize",
            TokenURL: "https://github.com/login/oauth/access_token",
            },
        },
        Authenticate: func(userinfo string, req *http.Request) error {
            return nil
       },
    })

3. 添加认证鉴权功能的实现。当用户登录github.com成功并授权后,用户会rediect到mesher, mesher将获取用户在github.com的用户信息,并调用Authenticate: func(userInfo string, req *http.Request) error 回调函数。需要开发者实现该回调,利用github.com的用户信息完成自定义的认证的流程。

以上就是开发者使用mesher oauth2 认证能力的全过程。

用户认证流程如下

1. 用户在浏览器中访问如下URL:

https://github.com/login/oauth/authorize?response_type=code&client_id=your_client_id&redirect_uri=http(s)://your_domain.com/oauth2_callback

  • response_type=code : 代表期望的请求响应类型为authorization code。

  • client_id=clientID 为应用的客户端id,开发者步骤1获取得到的。

  • redirect_uri=http(s): //yourdomain.com/oauth2_callback:redirect_uri是成功获取token之后,重定向的地址。

2. 该URL是OAuth2配置的登录页面。如下:

基于servicecomb-mesher的网关认证鉴权方案_第2张图片

3. 输入github账户的用户名密码,然后页面跳转到授权页面:

基于servicecomb-mesher的网关认证鉴权方案_第3张图片

4. 然后点击页面上的授权按钮,浏览器会返回redirect到redirect_uri配置的地址

http(s)://yourdomain.com/oauth2_callback/?code=xxxxx

这样mesher就能拿到code,并最终获取到用户在github.com用户信息,调用开发者提供的回调函数,完成最终的认证流程。

设计思路

1. mesher作为可定制化的服务网关,帮助开发者轻松的获取到第三方应用的用户信息,并利用开发者实现的认证回调函数实现认证功能。

2. 以handler链的形式注入mesher中,handler链注入的形式的优势是,扩展性强,可以操作response对象,修改cookies。

3. 目前oauth2授权框架使用最广泛的认证方式之一,也是用户体验较好的方式。因此mesher中将使用oauth2授权来实现认证。

关键原理

oauth2授权包含四种授权模式(http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html?tdsourcetag=s_pctim_aiomsg),其中安全性较高使用最广泛的为授权码模式,其中用grant_type=authorization_code  表示授权类型为授权码模式,用于获取access tokens和 refresh tokens。由于这是一个基于重定向的流程,客户端必须有能力和资源拥有者的user-agent(通常为WEB浏览器)进行交互,并且有能力接收来自授权服务器的重定向请求。

授权码模式流程图如下:

基于servicecomb-mesher的网关认证鉴权方案_第4张图片

(A)client通过将资源拥有者重定向到授权服务器来初始化这个流程。client需要在请求中包含client identifier, requested scope, local state, and a redirection URI,这些内容在client被赋予(或者被拒绝)权限后也会被发送回来。

(B)授权服务器通过user-agent来对资源拥有者进行身份验证,并确定资源所有者是否授予或拒绝客户端的访问请求。

(C)假设资源所有者授予访问权限,授权服务器使用先前提供的重定向URI(在请求中或在客户端注册期间)将用户代理重定向回客户端。重定向URI包含授权代码和客户端先前提供的任一本地状态。

(D)客户端通过包含在上一步骤中接收的授权代码来请求来自授权服务器的令牌端点的访问令牌。发出请求时,客户端使用授权服务器进行身份验证。客户端通过包含用于获取验证授权码的重定向URI进行 验证。

(E)授权服务器对客户端进行身份验证,验证授权代码,并确保收到的重定向URI与步骤(C)中用于重定向客户端的URI相匹配。

关键代码解读

1.  handler 链注入

mesher提供高级别通用中间件抽象层,免于用户学习[handler chain内部的复杂性](https://docs.go-chassis.com/dev-guides/how-to-implement-handler.html),让用户只需关注与自身业务的开发。

// AuthName is a constant
const AuthName = "oauth2"
func (oa *Handler) Handle(chain *handler.Chain, inv *invocation.Invocation, cb invocation.ResponseCallBack) {
...
chain.Next(inv, func(r *invocation.Response) error {
        return cb(r)
    })
}
//Handler is is a oauth2 pre process raw data in handler
type Handler struct {
}


// Name returns router string
func (oa *Handler) Name() string {
    return AuthName
}


// NewOAuth2 returns new auth handler
func NewOAuth2() handler.Handler {
    return &Handler{}
}


func init() {
    err := handler.RegisterHandler(AuthName, NewOAuth2)
    if err != nil {
        openlogging.Error("register handler error: " + err.Error())
    return
    }
}

2. 设置授权类型和配置文件

mesher中需设置oauth2的授权类型,如authorization code,然后设置配置参数。

Use(&OAuth2{
        GrantType: "authorization_code",       // Registration grand type
                                               // The default is the authorization code model
        UseConfig: &oauth2.Config{
            ClientID:     "",                  // (required, string) your client_ID
            ClientSecret: "",                  // (required, string) your client_Secret
            Scopes:       []string{""},        // (optional, string) scope specifies requested permissions
            RedirectURL:  "",                  // (required, string) redirect url to mesher
            Endpoint: oauth2.Endpoint{         // (required, string) your auth server endpoint
                AuthURL:  "",
                TokenURL: "",
            },
        },
})

3. 从请求端获取token

oauth2授权最终的目的就是获取token,从而完成授权。首先从URL中获取code,然后用code获取token。token过期时间mesher中设置为30分钟。

code := req.FormValue("code")
    if code =="" {
       WriteBackErr(ErrInvalidCode, http.StatusUnauthorized, cb)
        return
    }
 
func getToken(code string, cb invocation.ResponseCallBack)(accessToken string, err error) {
    if auth.UseConfig!= nil {
        config :=auth.UseConfig
        token, err :=config.Exchange(context.Background(), code)
        if err != nil{
           openlogging.Error("get token failed, errors: " + err.Error())
           WriteBackErr(ErrInvalidCode, http.StatusUnauthorized, cb)
            return"", err
        }
 
        // set theexpiry token in 30 minutes
        token.Expiry =time.Now().Add(30 * 60 * time.Second)
        iftime.Now().After(token.Expiry) {
            return"", ErrExpiredToken
        }
        accessToken =token.AccessToken
        returnaccessToken, nil
    }
    return"", nil
}

Apache ServiceComb社区现诚邀开发者参加2020年华为开发者大会(HDC)!

时间

2020年2月11日-12日

地点

深圳市福田区会展中心

活动详情

为答谢大家长期对社区的支持与贡献,我们准备了一些华为开发者大会参会门票。此次Apache ServiceComb社区设有3场主题演讲、2个codelabs、黑客松活动。

Apache ServiceComb黑客松的题目是利用ServiceComb框架开发微服务化的AI Web相册。

第1,2名参赛获奖团队可获得价值3999元的Altas 200 DK开发者套件,参与就有香蕉派开发板和T恤奖品。

报名黑客松大赛 & 获取HDC门票

长按识别二维码,添加”ServiceComb小助手“

快来报名参赛 or 领取免费门票吧!

备注:本次参赛队伍名额有限,请大家火速报名。免费门票数量有限,先到先得,赠完为止。本活动有效期截止2020年2月4日,赠送活动最终解释权归ServiceComb社区。

文章好看就点这里

戳阅读原文,更有多ServiceComb小知识!

 

你可能感兴趣的:(基于servicecomb-mesher的网关认证鉴权方案)