一般公司项目比较多,比较分散,但是对于都是公司的用户来说,用户数据一般是共享的,所以集成统一认证与授权的功能一般就必不可少,这样可以实现一个用户,分配一点权限,能访问公司很多项目.
一般的认证与授权方案有 OAuth、分布式 Session、OpenID 和 JWT 等.目前常用的是OAuth2,其重点在于为Web应用程序、桌面应用程序、移动设备以及室内设备的授权流程提供简单的客户端开发方式。它为第三方应用提供对HTTP服务的有限访问,既可以是资源拥有者通过授权允许第三方应用获取HTTP服务,也可以是第三方以自己的名义获取访问权限。
OAuth2 中主要分为了4种角色(重点核心)
1.resource owner 资源所有者,是能够对受保护的资源授予访问权限的实体,可以是一个用户,这时会被称为end-user。
2.resource server 资源服务器,持有受保护的资源,允许持有访问令牌(access token)的请求访问受保护资源。
3.client 客户端,持有资源所有者的授权,代表资源所有者对受保护资源进行访问。
4.authorization server 授权服务器,对资源所有者的授权进行认证,成功后向客户端发送访问令牌。
(所有的操作都是围绕这四种角色来开展的.)
官方有一个流程图:
主要是六步操作:
1.client请求Resource owner 来 获取授权;
2.Resource owner 同意授权,返回授权许可(Authorization Grant);
3.client携带Authorization Grant要求授权Resource Server 进行认证,并发送一个token令牌;
4.Resource Server 对client进行身份验证,并认证Authorization Grant,如果有效,返回token令牌;
5.client携带Authorization Grant向Resource Server请求受保护资源的访问;
6.Resource Server验证token令牌,如果有效,接受访问请求,返回受保护资源。
授权类型
OAuth2默认定了四种授权类型
1.authorization code 授权码类型
2.implicit 简化类型(也称为隐式类型)
3.resource owner password credentials 密码类型
4. client credential 客户端类型
下面主要说一下客户端类型
具体代码如下:(着重看每个方法上面的注释,可以便于理解)
package main import ( "encoding/json" "fmt" "github.com/google/uuid" "gopkg.in/oauth2.v3/errors" "gopkg.in/oauth2.v3/manage" "gopkg.in/oauth2.v3/models" "gopkg.in/oauth2.v3/server" "gopkg.in/oauth2.v3/store" "log" "net/http" ) func main(){ clientStore, srv := InitOauthManager() /** 注册获取 clientId和clientSecret( 1.client请求Resource owner 来 获取授权; ) */ http.HandleFunc("/route", func(w http.ResponseWriter, r *http.Request) { clientId := uuid.New().String()[:8] clientSecret := uuid.New().String()[:8] err := clientStore.Set(clientId, &models.Client{ ID: clientId, Secret: clientSecret, }) if err != nil { fmt.Println(err.Error()) } w.Header().Set("Content-Type", "application/json") /** //(2.Resource owner 同意授权,返回授权许可(Authorization Grant)) */ json.NewEncoder(w).Encode(map[string]string{"CLIENT_ID": clientId, "CLIENT_SECRET": clientSecret}) //实际项目中一般存到数据库或者redis }) /** 获取access_token( 3.client携带Authorization Grant要求授权Resource Server 进行认证,并发送一个token令牌; 4.Resource Server 对client进行身份验证,并认证Authorization Grant,如果有效,返回token令牌) */ http.HandleFunc("/token", func(w http.ResponseWriter, r *http.Request) { srv.HandleTokenRequest(w, r) }) /** 带着access_token 访问路径(5.client携带Authorization Grant向Resource Server请求受保护资源的访问;) */ http.HandleFunc("/test01", validateToken(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("HelloWord")) }, srv)) log.Fatal(http.ListenAndServe(":8888", nil)) } /** token校验(6.Resource Server验证token令牌,如果有效,接受访问请求,返回受保护资源。) */ func validateToken(f http.HandlerFunc, srv *server.Server) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { _, err := srv.ValidationBearerToken(r) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } f.ServeHTTP(w, r) }) } //初始化OauthManager func InitOauthManager() (*store.ClientStore, *server.Server) { manager := manage.NewDefaultManager() manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg) manager.MustTokenStorage(store.NewMemoryTokenStore()) clientStore := store.NewClientStore() manager.MapClientStorage(clientStore) srv := server.NewDefaultServer(manager) srv.SetAllowGetAccessRequest(true) srv.SetClientInfoHandler(server.ClientFormHandler) manager.SetRefreshTokenCfg(manage.DefaultRefreshTokenCfg) srv.SetInternalErrorHandler(func(err error) (re *errors.Response) { log.Println("Internal Error:", err.Error()) return }) srv.SetResponseErrorHandler(func(re *errors.Response) { log.Println("Response Error:", re.Error.Error()) }) return clientStore, srv }
1.首先我们启动项目.访问: http://localhost:8888/route 获取 clientId 和 clientSecret
2.然后访问: http://localhost:8888/token?grant_type=client_credentials&client_id=012eaf30&client_secret=298262d9 获取 到 access_token
3.在访问 :http://localhost:8888/test01?access_token=P8AR0LRKOLOYEMV9ACUXWG 可以看到返回的值
4.我们不加access_token或者修改下这个access_token 看是否还能获取到响应内容呢?
1.修改access_token 发现:
2.不加access_token
可以看到 没有正确的token令牌 是不让我们访问的,至此,我们整个模拟流程走通了.
Oauth支持的5类 grant_type 及说明
authorization_code — 授权码模式(即先登录获取code,再获取token)
password — 密码模式(将用户名,密码传过去,直接获取token)
client_credentials — 客户端模式(无用户,用户向客户端注册,然后客户端以自己的名义向’服务端’获取资源)
implicit — 简化模式(在redirect_uri 的Hash传递token; Auth客户端运行在浏览器中,如JS,Flash)
refresh_token — 刷新access_token
未完待续....
【参考链接】
标签:http,Resource,认证,golang,token,client,srv,GO,授权 From: https://www.cnblogs.com/opensmarty/p/17956105