文章目录

  • Go Iris 实现认证与授权
    • 1. 常见的认证类型
      • HTTP Basic Auth
      • OAUth2.0
      • JWT 认证
    • 2. Iris 实现HTTP BASIC认证
      • HTTP BASIC认证过程
    • 3. Iris 实现OAUth2.0
      • OAUth2.0授权过程

Go Iris 实现认证与授权

1. 常见的认证类型

HTTP Basic Auth

在HTTP中,基本认证(Basic access authentication)是一种用来允许网页浏览器或其他客户端程序在请求时提供用户名和口令形式的身份凭证的一种登录验证方式。

虽然基本认证非常容易实现,但该方案创建在以下的假设的基础上,即:客户端和服务器主机之间的连接是安全可信的。特别是,如果没有使用SSL/TLS这样的传输层安全的协议,那么以明文传输的密钥和口令很容易被拦截。该方案也同样没有对服务器返回的信息提供保护。

OAUth2.0

OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(authorization layer)。“客户端"不能直接登录"服务提供商”,只能登录授权层,以此将用户与客户端区分开来。"客户端"登录授权层所用的令牌(token),与用户的密码不同。用户可以在登录的时候,指定授权层令牌的权限范围和有效期。

"客户端"登录授权层以后,"服务提供商"根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

OAuth2的基本流程为:

  1. 第三方应用请求用户授权。
  2. 用户同意授权,并返回一个凭证(code)
  3. 第三方应用通过第二步的凭证(code)向授权服务器请求授权
  4. 授权服务器验证凭证(code)通过后,同意授权,并返回一个资源访问的凭证(Access Token)。
  5. 第三方应用通过第四步的凭证(Access Token)向资源服务器请求相关资源。
  6. 资源服务器验证凭证(Access Token)通过后,将第三方应用请求的资源返回。

JWT 认证

JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。 此信息可以通过数字签名进行验证和信任。JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。

JWT 的原理是,服务器认证以后,生成一个 JSON 对象,发回给用户,就像下面这样:

{"name":    name, // 用户名"exp":      time.Now().Add(time.Hour * 2).Unix(), // 添加过期时间
}

以后,用户与服务端通信的时候,都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名;

2. Iris 实现HTTP BASIC认证

HTTP BASIC认证过程

  1. 客户端向服务器请求数据,请求的内容可能是一个网页或者是一个其它的MIME类型,此时,假设客户端尚未被验证,则客户端提供如下请求至服务器:
  Get /index.html HTTP/1.0Host: www.yourhost.com
  1. 服务器向客户端发送验证请求代码401,服务器返回的数据:
  HTTP/1.0 401 UnauthorisedServer: nginx/1.0WWW-Authenticate: Basic realm="yourhost.com"Content-Type: text/htmlContent-Length: xxx
  1. 当符合http1.01.1规范的客户端浏览器收到401返回值时,将自动弹出一个登录窗口,要求用户输入用户名和密码
  2. 用户输入用户名和密码后,将用户名及密码以BASE64加密方式加密,并将密文放入前一条请求信息中,则客户端发送的第一条请求信息则变成如下内容:
  Get /index.html HTTP/1.0Host: www.yourhost.comAuthorization: Basic xxxxxxxxxxxxxxxxxxxxxxxxxxxx //加密串
  1. 服务器收到上述请求信息后,将Authorization字段后的用户信息取出、解密,将解密后的用户名及密码与用户数据库进行比较验证, 如用户名及密码正确,服务器则根据请求,将所请求资源发送给客户端

示例程序:

该示例程序首先将全局路由重定向到/admin,在/admin,使用authHandler中间件进行登录处理,主要在于使用ctx.Request().BasicAuth()函数:

// basic.go
package mainimport ("time""github.com/kataras/iris""github.com/kataras/iris/middleware/basicauth"
)func main() {app := iris.New()authConfig := basicauth.Config{Users:   map[string]string{"myusername": "mypassword", "mySecondusername": "mySecondpassword"},Realm:   "Authorization Required", // 默认表示域 "Authorization Required"Expires: time.Duration(30) * time.Minute,}authentication := basicauth.New(authConfig)//作用范围 全局 app.Use(authentication) 或者 (app.UseGlobal 在Run之前)//作用范围 单个路由 app.Get("/mysecret", authentication, h)app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") })//作用范围  PartyneedAuth := app.Party("/admin", authentication){//http://localhost:8080/adminneedAuth.Get("/", authHandler)// http://localhost:8080/admin/profileneedAuth.Get("/profile", authHandler)// http://localhost:8080/admin/settingsneedAuth.Get("/settings", authHandler)}// open http://localhost:8080/adminapp.Run(iris.Addr(":8080"))
}func authHandler(ctx iris.Context) {username, password, _ := ctx.Request().BasicAuth()//第三个参数因为中间件所以不需要判断其值,否则不会执行此处理程序ctx.Writef("%s %s:%s", ctx.Path(), username, password)
}

在运行上面的代码前,需要安装相关的库:

go get -u "github.com/kataras/iris"

运行程序:

go run main.go

运行结果如下图所示,访问http://localhost:8080,将会自动弹出登录窗口要求登录

3. Iris 实现OAUth2.0

OAUth2.0授权过程

  1. 服务提供方(provider),用户使用服务提供方来存储受保护的资源,如照片,视频,联系人列表
  2. 用户,存放在服务提供方的受保护的资源的拥有者
  3. 客户端,要访问服务提供方资源的第三方应用,通常是网站,如提供照片打印服务的网站。在认证过程之前,客户端要向服务提供者申请客户端标识

下面是一个简单的示例程序,该程序将进行github的OAUth2.0授权:

任何OAuth2(甚至是纯golang/x/net/oauth2)包可以与iris一起使用,但在这个例子中我们使用markbates’ goth:

在终端输入下面的命令安装包 :

go get github.com/markbates/goth/...

这个OAuth2示例适用于会话,因此我们需要附加会话管理器

开发人员可以使用任何第三方包添加自定义cookie编码器/解码器。

在这个例子中,我们将使用gorilla的securecookie:

go get github.com/markbates/goth/…

go get github.com/gorilla/securecookie

securecookie的示例可以在“sessions / securecookie”示例文件夹中找到。

package mainimport ("errors""os""sort""github.com/gorilla/securecookie" //可选,用于seesion的编码器/解码器"github.com/kataras/iris""github.com/kataras/iris/sessions""github.com/markbates/goth""github.com/markbates/goth/providers/auth0""github.com/markbates/goth/providers/github"
)var sessionsManager *sessions.Sessionsfunc init() {//附加session管理器cookieName := "mycustomsessionid"// AES only supports key sizes of 16, 24 or 32 bytes.// You either need to provide exactly that amount or you derive the key from what you type in.// AES仅支持16,24或32字节的密钥大小。// 您需要准确提供该字节数,或者从您键入的内容中获取密钥。hashKey := []byte("the-big-and-secret-fash-key-here")blockKey := []byte("lot-secret-of-characters-big-too")secureCookie := securecookie.New(hashKey, blockKey)sessionsManager = sessions.New(sessions.Config{Cookie: cookieName,Encode: secureCookie.Encode,Decode: secureCookie.Decode,})
}//下面是一些辅助函数// GetProviderName函数是用于获取提供者名称(授权应用名称)通过请求。
// 默认情况下,将从URL查询字符串中提取此授权应用名称。
// 如果您以不同的方式提供, 将自己的函数分配给返回提供者的变量用您的请求的名称。
var GetProviderName = func(ctx iris.Context) (string, error) {//尝试从的url参数中获取providerif p := ctx.URLParam("provider"); p != "" {return p, nil}//尝试从url PATH参数“{provider}或:provider或{provider:string}或{provider:alphabetical}”获取它if p := ctx.Params().Get("provider"); p != "" {return p, nil}//尝试从上下文的每个请求存储中获取它if p := ctx.Values().GetString("provider"); p != "" {return p, nil}//如果没有找到,则返回一个带有相应错误的空字符串return "", errors.New("you must select a provider")
}/*
BeginAuthHandler是用于启动身份验证过程的便捷处理程序。
它希望能够从查询参数中获取提供程序的名称授权应用名称)
作为“provider”或“:provider”。BeginAuthHandler会将用户重定向到相应的身份验证端点对于请求的provider。
请参阅https://github.com/markbates/goth/examples/main.go以查看此操作。
*/
func BeginAuthHandler(ctx iris.Context) {url, err := GetAuthURL(ctx)if err != nil {ctx.StatusCode(iris.StatusBadRequest)ctx.Writef("%v", err)return}ctx.Redirect(url, iris.StatusTemporaryRedirect)
}/*
GetAuthURL使用provided的请求启动身份验证过程。
它将返回一个应该用于向用户发送的URL。它希望能够从查询参数中获取provider的名称
作为“provider”或“:provider”或来自“provider”键的上下文值。我建议使用BeginAuthHandler而不是执行所有这些步骤,但那完全取决于你。
*/
func GetAuthURL(ctx iris.Context) (string, error) {providerName, err := GetProviderName(ctx)if err != nil {return "", err}provider, err := goth.GetProvider(providerName)if err != nil {return "", err}sess, err := provider.BeginAuth(SetState(ctx))if err != nil {return "", err}url, err := sess.GetAuthURL()if err != nil {return "", err}session := sessionsManager.Start(ctx)session.Set(providerName, sess.Marshal())return url, nil
}// SetState设置与给定请求关联的状态字符串。
// 如果没有状态字符串与请求相关联,则会生成一个。
// 此状态发送给provider,可以在提取期间检索回调
var SetState = func(ctx iris.Context) string {state := ctx.URLParam("state")if len(state) > 0 {return state}return "state"
}// GetState获取回调期间provider的返回的状态。
// 这用于防止CSRF攻击,请参阅 http://tools.ietf.org/html/rfc6749#section-10.12
var GetState = func(ctx iris.Context) string {return ctx.URLParam("state")
}/*
CompleteUserAuth在锡上做了它所说的。 它完成了身份验证处理并从provider处获取有关用户的所有基本信息。它希望能够从查询参数中获取provider的名称作为“provider”或“:provider”。请参阅https://github.com/markbates/goth/examples/main.go以查看此操作。
*/
var CompleteUserAuth = func(ctx iris.Context) (goth.User, error) {providerName, err := GetProviderName(ctx)if err != nil {return goth.User{}, err}provider, err := goth.GetProvider(providerName)if err != nil {return goth.User{}, err}session := sessionsManager.Start(ctx)value := session.GetString(providerName)if value == "" {return goth.User{}, errors.New("session value for " + providerName + " not found")}sess, err := provider.UnmarshalSession(value)if err != nil {return goth.User{}, err}user, err := provider.FetchUser(sess)if err == nil {//可以找到现有session数据的用户return user, err}//获取新令牌并重试获取_, err = sess.Authorize(provider, ctx.Request().URL.Query())if err != nil {return goth.User{}, err}session.Set(providerName, sess.Marshal())return provider.FetchUser(sess)
}// 注销使用户session
func Logout(ctx iris.Context) error {providerName, err := GetProviderName(ctx)if err != nil {return err}session := sessionsManager.Start(ctx)session.Delete(providerName)return nil
}//一些函数助手的结尾 设置key secret 与回调方法
func main() {goth.UseProviders(github.New(os.Getenv("GITHUB_KEY"), os.Getenv("GITHUB_SECRET"), "http://localhost:3000/auth/github/callback"),// Auth0为每个客户分配域,必须提供域以使auth0正常工作auth0.New(os.Getenv("AUTH0_KEY"), os.Getenv("AUTH0_SECRET"), "http://localhost:3000/auth/auth0/callback", os.Getenv("AUTH0_DOMAIN")),)m := make(map[string]string)m["github"] = "Github"var keys []stringfor k := range m {keys = append(keys, k)}sort.Strings(keys)providerIndex := &ProviderIndex{Providers: keys, ProvidersMap: m}//创建我们的应用,//设置一个视图//设置sessions//并为展示设置路由器app := iris.New()//启动路由器app.Get("/auth/{provider}/callback", func(ctx iris.Context) {user, err := CompleteUserAuth(ctx)if err != nil {ctx.StatusCode(iris.StatusInternalServerError)ctx.Writef("%v", err)return}ctx.ViewData("", user)if err := ctx.View("user.html"); err != nil {ctx.Writef("%v", err)}})app.Get("/logout/{provider}", func(ctx iris.Context) {Logout(ctx)ctx.Redirect("/", iris.StatusTemporaryRedirect)})app.Get("/auth/{provider}", func(ctx iris.Context) {//尝试让用户无需重新进行身份验证if gothUser, err := CompleteUserAuth(ctx); err == nil {ctx.ViewData("", gothUser)if err := ctx.View("user.html"); err != nil {ctx.Writef("%v", err)}} else {BeginAuthHandler(ctx)}})app.Get("/", func(ctx iris.Context) {ctx.ViewData("", providerIndex)if err := ctx.View("index.html"); err != nil {ctx.Writef("%v", err)}})// http://localhost:3000app.Run(iris.Addr("localhost:3000"))
}type ProviderIndex struct {Providers    []stringProvidersMap map[string]string
}

Go Iris 实现认证与授权相关推荐

  1. linux认证授权系统,linux高级操作系统用户认证与授权-20210323002921.doc-原创力文档...

    HYPERLINK "/" 长沙理工大学 <Linux高级操作系统>课程设计报告 基于Linux的用户认证与授权研究 廖正磊 学 院 计算机与通信工程 专业 计算机科学 ...

  2. 5.1基于JWT的认证和授权「深入浅出ASP.NET Core系列」

    原文:5.1基于JWT的认证和授权「深入浅出ASP.NET Core系列」 希望给你3-5分钟的碎片化学习,可能是坐地铁.等公交,积少成多,水滴石穿,码字辛苦,如果你吃了蛋觉得味道不错,希望点个赞,谢 ...

  3. solr kerberos java_solr添加kerberos认证及授权

    solr添加kerberos认证及授权 @(OTHERS)[solr] 一.kerberos (一)添加用户 在kdc中添加solr用户: root@kdc:/# kadmin.local kadmi ...

  4. Core篇——初探Core的认证,授权机制

    目录 1.Cookie-based认证的实现 2.Jwt Token 的认证与授权 3.Identity Authentication + EF 的认证 Cookie-based认证的实现 cooki ...

  5. OAuth2.0认证和授权原理

     什么是OAuth授权? 一.什么是OAuth协议 OAuth(开放授权)是一个开放标准. 允许第三方网站在用户授权的前提下访问在用户在服务商那里存储的各种信息. 而这种授权无需将用户提供用户名和 ...

  6. Apache认证、授权和访问控制

    Apache认证.授权和访问控制 http://tech.it168.com/o/2007-08-21/200708211031890.shtml 转载于:https://www.cnblogs.co ...

  7. ASP.NET Core 认证与授权[2]:Cookie认证

    ASP.NET Core 认证与授权[2]:Cookie认证 原文:ASP.NET Core 认证与授权[2]:Cookie认证 由于HTTP协议是无状态的,但对于认证来说,必然要通过一种机制来保存用 ...

  8. Kubernetes1.5新特性(一):Kubelet API增加认证和授权能力

    2019独角兽企业重金招聘Python工程师标准>>> 背景介绍 在Kubernetes1.5中,对于kubelet新增加了几个同认证/授权相关的几个启动参数,分别是: 认证相关参数 ...

  9. Springboot整合shiro基于url身份认证和授权认证

    你还不会shiro吗? 前奏 shiro核心配置文件(rolesFilter可选). 身份认证 多表登录源如何操作? 授权管理 如何解决界面多角色/资源问题 访问效果 权限管理在日常开发中很重要,所以 ...

最新文章

  1. cProfile——Python性能分析工具
  2. 维护服务器技术员流程,技术员岗位工作的流程表.doc
  3. UDP和TCP中的伪首部
  4. JavaScript学习笔记(十)——学习心得与经验小结
  5. gre考试能用计算机么,新GRE考试必须知道的九大考场问题
  6. P5127-子异和【线段树,树链剖分,位运算】
  7. ASP.NET MVC 5调用其他Action
  8. mysql集成函数_mysql的内置函数
  9. [转载] 七龙珠第一部——第009话 兔子头儿的绝招
  10. EasyUI-在iframe里获取现阶段选中的tab的标题
  11. Problem 1036 四塔问题
  12. Linux下Oracle中sqlplus上下键乱码问题
  13. 14_星仔带你学Java之Java编码规范、常用类
  14. 小米正式递交上市招股书:雷军股权绝对掌控
  15. 移远 NB-IOT_BC95_AT命令集
  16. [答疑]请问商品领用审批的序列图画的对么
  17. tesseract-ocr安装简体中文语言包
  18. [Mysql] 3.Mysql 数据类型
  19. alert意为:警告、警报。
  20. 两数之和(Two Sum)

热门文章

  1. Java 工具(jmap,jstack)在linux上的源码分析(四)safe point
  2. 驱动笔记(自己总结的)
  3. ubuntu 22.04 lts 安装步骤(vmware)
  4. rt-thread的at组件在freeRTOS上的移植与应用
  5. CF1422D Returning Home
  6. JS三元运算符怎样判断多个条件的方法
  7. 名编辑电子杂志大师教程 | 没PDF,如何一页页的直接排版编辑名编辑电子杂志?
  8. 高效管理:10年资深项目经理,最喜欢用这两招
  9. 模糊测试-radamsa学习笔记
  10. C# 生成chart图表的三种方式