php网站cms,移动开发专业,html5手机网站返回顶部,小米新手机发布在之前的《通过实例理解Go Web身份认证的几种方式[1]》和《通过实例理解Web应用授权的几种方式[2]》两篇文章中#xff0c;我们对Web应用身份认证(AuthN)和授权(AuthZ)的几种方式做了介绍并配以实例增强理解。 在现实世界中#xff0c;还有一大类的认证与授权是在前面的文章中… 在之前的《通过实例理解Go Web身份认证的几种方式[1]》和《通过实例理解Web应用授权的几种方式[2]》两篇文章中我们对Web应用身份认证(AuthN)和授权(AuthZ)的几种方式做了介绍并配以实例增强理解。 在现实世界中还有一大类的认证与授权是在前面的文章中没有作为重点介绍的那就是OAuth2授权[3]与基于OAuth2之上的OpenID身份认证(OIDC, OpenID Connect)[4]。 近期接触到开放平台(Open Platform)的设计和开发整个开放平台的授权流程都是基于OAuth2打造的因此在这篇文章中我就来先来通过实例详细说说OAuth2OIDC将放在后面的文章中说明。 1. OAuth是什么 OAuth中的O代表了OpenOAuth直译过来就是开放授权。OAuth是一个开放标准[5]允许用户让第三方应用访问该用户在某一网站上存储的私密的资源如照片视频联系人列表等而无需将用户名和密码提供给第三方应用。 OAuth不是什么新技术了其原型最早可追溯至2006年末至今也快小20年了。但直到2010年4月OAuth 1.0协议才以RFC 5849的形式正式发布[6]。不过OAuth 1.0版本存在两个主要问题一是当初设计时仅是为了web浏览器应用随着应用类型的增多一套授权机制难以应对现实中的所有场景比如Web应用场景、移动App应用场景、官方应用场景等因为这些场景不是完全相同的这给使用者带去很多负面体验二是一些安全性的问题(这里就不展开了)。 2012年10月解决OAuth 1.0上述问题的OAuth 2.0以RFC 6749发布[7]。OAuth 2.0是OAuth协议的下一版本但不向后兼容OAuth 1.0。OAuth 2.0关注客户端开发者的简易性同时为Web应用、桌面应用、手机和智能设备定义了专门的授权许可流程包括授权码许可机制(Authorization Code)、客户端凭据机制(Client Credentials)、资源拥有者凭据机制(Resource Owner Password Credentials)和隐式许可机制(Implicit)。如今OAuth 1.0已经被废弃谈到OAuth如无特殊说明指的都是OAuth2.0版本。 在OAuth2.0的四种授权类型中最安全的、最广泛使用的也是最常见的就是授权码许可机制(Authorization Code)了。本文后续的说明与示例也都是围绕授权码这种类型的。 2. OAuth2解决了什么问题 仅仅凭借上面关于OAuth的描述你可能依然无法对OAuth有一个直观和深刻的理解笔者第一次接触OAuth协议时也是花了不少时间才逐渐“茅塞顿开”当然本文参考资料中的那些书籍和资料“功不可没”尤其是OAuth 2.0的RFC协议规范[8]。 那么OAuth到底解决的是什么问题这里我们就用一个非常典型的示例来系统说说一下。 2.1 传统的云盘系统 现在有一个像百度网盘那样的云盘系统(my-yunpan.com)用户可以注册云盘系统的账号然后将自己的个人数据文件比如照片、音视频、文档等上传到云盘上保存。 假设这里有一个名为tonybai的用户注册了云盘并将个人的一些照片文件上传到云盘上做保存和备份 这是一个我们都可以理解的场景用户注册云盘账号然后登录云盘应用后将个人照片上传到云盘这里使用的身份认证和授权技术方案没有超出《通过实例理解Go Web身份认证的几种方式[9]》和《通过实例理解Web应用授权的几种方式[10]》两篇文章的范畴。 针对这个场景OAuth定义了三个很容易理解的概念实体 Resource Server集中存储资源(如用户照片等)的服务这个示例里就是云盘服务Resource owner资源的拥有者这里就是云盘的用户比如图中的tonybaiProtected ResourceResource owner上传并存储在Resource Server中的Resource受Resource Server保护这里对应的就是用户上传的照片。 大家先对这三个概念实体有个感性的认识即可后续备用。 2.2 第三方的照片冲印服务 智能手机时代数字照片(Digital Photo)将传统的基于胶卷的照片彻底拉下神坛。数字照片是存储在磁盘、手机中或云盘上的但依然有很多人有将数字照片像传统照片那样冲印出来放在相册里或房间照片墙上欣赏的需求于是就有了在线照片冲印服务(my-photo-print.com)。 用户注册在线照片冲印服务后将自己的数字照片上传交钱冲印即可冲印好的照片便会经由快递送至用户家中非常方便。 2.3 Resource Owner要冲印照片 有一天云盘用户tonybai要挑选一些近期存储在云盘中的照片进行冲印他搜索到了my-photo-print.com这个第三方的照片冲印服务但他需要在my-photo-print.com这个应用上重新注册一个账号再将云盘上的照片下载后重新上传到my-photo-print.com这个服务的空间中才能实现在线冲印。这对于大多数像tonybai这样的用户而言并不是一个很easy的操作体验上也是糟糕。tonybai在思考我的照片已经在云盘上了为什么不可以直接基于云盘上的照片进行冲印呢 2.4 增加开放平台(open.my-yunpan.com) 在tonybai萌生出这个困惑的同时云盘的产品经理也同步感知到了这个需求是时候给云盘系统增加开放平台了这样第三方应用便可以接入云盘系统方便快捷地为云盘用户提供各种扩展服务比如照片冲印、云上视听、数据智能管理等这也是互联网界熟知的生态建设的套路。 下面是照片冲印服务my-photo-print.com注册和接入开放平台的示意图 照片冲印服务my-photo-print.com注册和接入云盘开放平台后会得到一个client_id和client_secret这两个字段是照片冲印服务接入云盘开放平台的凭据即云盘开放平台对第三方应用进行身份认证的凭据。 不过即使照片冲印服务使用client_id和client_secret这个凭据通过了云盘系统的认证照片冲印服务依然拿不到云盘系统上用户的照片数据这里需要一个授权过程即云盘系统用户(如前文提及的tonybai)告诉云盘系统是否允许照片冲印服务访问自己的数据。 那么问题来了如何实现云盘系统用户对已接入云盘系统的第三方应用的授权呢下面我们就来探讨一下。 注这里显然是打了个伏笔一旦云盘系统建立了开放平台那么云盘系统的用户对第三方应用的授权流程也就由开放平台规定好了。 2.5 云盘系统用户对第三方应用进行授权的方案 2.5.1 凭据共享方案 一个最简单粗暴的方案就是直接用云盘系统用户的凭据代替用户去云盘系统读取该用户的数据下面是该方案的示意图 我们看到照片打印服务想要获取用户的照片它首先会提示用户输入其云盘系统上的用户名和密码然后就会拿着用户的这些凭据合法地进入到该用户在云盘系统中的个人空间并拿到想要的数据。这也意味着用户在云盘系统上可以进行的任何操作照片打印服务也都有权限进行。此外一旦用户在多个网站应用上使用的是相同的用户名和密码那么照片打印服务也可以通过拿到的凭据登录这些网站并“假扮”用户获得这些网站上的用户数据。这种通过凭据共享来实现第三方应用访问云盘上的用户数据的方案显然是毫无安全底线可言。 2.5.2 专用密码方案 现在你已经看到共享用户密码并不是一个好方法那会授予照片打印服务全局的访问权限它就能代表由它指定的任何用户并访问云盘系统上的所有照片。那是否可以授予照片打印服务一个权限有限的专用密码来实现照片获取呢此密码仅用于透露给第三方服务用户自己并不会使用这个密码来登录只是将它粘贴到所使用的第三方应用里(如下图) 这是一个可行的方案但这种方案的可用性并不好。它要求用户除了管理自己的主登录密码之外还要创建(在云盘系统中)、分发(贴到照片打印服务系统中)和管理特殊的凭据。并且用户管理这些凭据时一般不会区分专用凭据与第三方应用的对应关系往往是建立一个新专用凭据后贴到所有第三方应用中使用这使得撤销某个具体第三方应用的访问权限变得很困难。让用户科学管理这些凭据本身就给用户带来了心智负担也可理解为一种不好的体验。 不过相对于凭据共享方案的不安全专用密码方案已经是有所进步了但还远非理想。 2.6 OAuth2授权方案 前面无论是共享凭据还是专用密码方案都绕开了开放平台这显然是故意为最终理想方案的出炉做铺垫的 -- 没有差方案如何才能体现出理想方案的好呢-- 是时候叫出超级飞侠了。 这就是我们提到的OAuth2授权方案。OAuth协议的设计目的是让用户(Resource owner比如tonybai)通过OAuth协议将他们在受保护资源(Protected Resource比如照片)上的部分权限委托给第三方应用(比如照片冲印服务)使第三方应用能代表他们执行操作。这个方案既要考虑提升用户的使用体验也要考虑提升方案整体的安全性。为实现这些OAuth在流程中引入了另外一个组件授权服务器Authorization Server)。 如果我们将第三方应用(比如照片冲印服务)称为client(客户端应用)加上授权服务器Authorization Server)以及前面提到的三个概念Resource Server、Resource owner和Protected Resource我们就有了5个实体。他们究竟是什么关系呢又是如何交互的呢这就是OAuth2.0协议的核心内容。下图是来自OAuth2.0 RFC中的抽象协议流程图为了好理解我在图中加入了各个实体对应的示例中的名字 这是一个抽象图我们无法从中看出各个流程的细节但大致可以看出OAuth2授权的关键环节 client(客户端应用如照片冲印服务)需要用户(Resource owner)的授权但这个授权过程用户不会将密码等凭据暴露给clientclient凭借授权信息到授权服务器(Authorization server)换取access tokenclient凭借access token访问用户(Resource owner)在Resource Server(比如云盘系统)上的Resource数据(比如照片)。 接下来我们来看看细节我们使用OAuth2中最广泛使用的授权码方案(Authorization code)来展示这个流程下面是来自OAuth2.0 RFC中的授权码方案流程图 这个流程图依然很抽象我们用下面的“分解动作”来解释。 2.6.1 用户(Resource Owner)通过浏览器访问第三方应用(Clientmy-photo-print.com) 用户要想使用第三方应用比如my-photo-print.com服务来冲印自己位于云盘上的照片他首先要访问到这个第三方应用如下图所示 用户通过浏览器(User Agent)打开my-photo-print.com服务的登录页面这个页面除了提供使用用户名/密码登录之外还提供了“使用云盘账号”的按钮。该用户不想重新注册一遍my-photo-print.com服务的账号选择了点击“使用云盘账号”按钮。 2.6.2 用户(Resource Owner)被引导到云盘开放平台登录并对第三方应用进行授权 当用户点击“使用云盘账号”按钮后对第三方应用进行授权过程便正式开始下面是一个示意图 OAuth2.0的授权码模式的第一步便是第三方应用(Client)需要将用户(Resource Owner)引导到云盘开放平台(Authorization Server)的登录页面(/oauth/portal)为用户授权做好准备。在图中第三方应用my-photo-print.com通过网页html内重定向让用户的浏览器(User Agent)重定向到云盘开放平台的授权门户页面在重定向的请求中Client带上了自己的一些参数(比如client_id、scope等)。 云盘开放平台(Authorization Server)返回一个用户登录页面用户(tonybai)输入用户名密码以供Authorization Server做身份认证。注意这个过程完全没有client(照片冲印服务)的参与用户名和密码不会泄露给第三方。 当用户(如tonybai)点击submit提交凭据信息时可以向服务端请求也可以像图中简化版那样直接给出授权范围的提示。弹出的框提示“照片冲印服务需要用户授予两个权限”如果用户点击“授权”则会向Authorization Server发起授权请求连同用户的登录凭据一起授权请求的路径与参数如下(也可以使用表单提交的方式提交授权请求) /oauth/authorize?response_typecodeclient_idmy-photo-printstatexyz123scopeuser_info,read_photosredirect_urihttp%3A%2F%2Fmy-phone-print.com%3A8080%2Foauth%2Fcb response_typecode表示用户向授权平台请求一个授权码再强调一下这个授权码是用户(如tonybai)去申请的而不是client(第三方应用)后续也是由用户将code告知client(第三方应用)。 cilent_id表示为哪个第三方应用申请的后续授权平台在发access_token时可以基于该client_id进行校验。 scope是此次授权的权限列表。 redirect_uri是一个重定向地址这个地址可以在请求中传递如果不传递也可以在client注册开放平台账号时提供给开放平台(Authorization Server)。 state是一个随机数OAuth 2.0官方建议使用state以避免CSRF攻击。 2.6.3 用户提供codeclient用code换取access_token并读取用户数据 如果Authorization Server通过了用户的请求便会在应答中带上这次分配给用户的授权码(code)这个授权码是一次性的一旦使用便会作废当然Code也会有时效性一般就是几分钟。 我们继续看下面图示的分解动作吧 首先Authorization Server对用户的请求校验通过后便会分配授权码并通过下面这个应答返回给用户(浏览器) HTTP/1.1 302 Found
Location: http://my-phone-print.com:8080/oauth/cb?codeSplxlOBeZQQYbYS6WxSbIAstatexyz123 用户的浏览器收到这个应答后便会重定向到Location这个地址这个过程其实是在模拟用户向Client(照片冲印服务)提供code的行为。 当Client(照片冲印服务)收到收到用户的code后它会立即使用这个Code并结合自己的凭据(client_id和client_secert)向Authorization Server申请access_token POST /oauth/token HTTP/1.1
Host: open.my-yunpan.com:8081
Authorization: Basic base64(client_id:client_secret)
Content-Type: application/x-www-form-urlencodedgrant_typeauthorization_codecodeSplxlOBeZQQYbYS6WxSbIAredirect_urihttp%3A%2F%2Fmy-phone-print.com%3A8080%2Foauth%2Fcb 这是一个client发向Authorization Server的POST请求请求参数中除了固定的grant_typeauthorization_code以及code之外还带了redirect_uri这个redirect_uri是供Authorization Server校验使用的。此外这个请求是以Client身份申请的所以在http header中带上了client自己的凭据信息client_id和client_secert这里使用的是http basic auth。 Authorization Server对请求验证通过后便会给出Post应答access_token等信息都放在应答的包体中 {access_token:2YotnFZFEjr1zCsicMWpAA,token_type:example,expires_in:3600,refresh_token:tGzv3JOkF0XG5Qx2TlKWIA,example_parameter:example_value
} 这里除了包含access_token还包含了它的过期时间(expires_in)以及一个refresh_tokenclient可以使用refresh_token在access_token过期前换取一个新的access_token。但从安全角度考虑client不能无限制的换取新token所以refresh_token也会被过期时间。一旦refresh_token过期了那么client就要重新发起一次用户授权过程。 当client收到access_token后便可以拿着这个access_token到Resource Server(这里是my-yunpan.com)去获取用户(tonybai)的个人资料与照片数据了 POST /photos HTTP/1.1
Host: my-yunpan.com:8082methodlistallaccess_token2YotnFZFEjr1zCsicMWpAA my-yunpan.com验证access_token后便会将tonybai的照片列表返回给client然后client会返回重定向应答给用户的浏览器。用户浏览器收到重定向应答后便会向client(照片冲印服务)的/photos端点发起请求之后便可以在浏览器上看到自己的照片列表了。用户选择要冲印的照片后创建订单冲印即可。 从用户提交code给client到用户浏览器显示照片列表这中间用户可能会有短暂的等待毕竟client要与Authorization Server和Resource server进行多次交互用户浏览器也要进行重定向操作。 现在将“分解动作”与OAuth2.0 RFC中的授权码方案流程图结合在一起看你将会对OAuth有更深刻的理解。 注OAuth2授权流程原则上是要建立在HTTPS建立的安全通道之上的这里仅是示例我们聚焦的是OAuth2流程所以将使用HTTP进行展示。 3. 示例的具体实现 下面我们用Go语言编写一个可以简单演示OAuth2.0授权流程的示例该示例与上面描述的OAuth2的“分解动作”基本是可以对应起来的。 示例由三个服务构成my-photo-print照片冲印服务、my-yunpan云盘服务以及open-my-yunpan云盘开放平台/授权服务示例对应的目录结构如下 $tree -L 1 -F oauth2-examples
oauth2-examples
├── my-photo-print/
├── my-yunpan/
└── open-my-yunpan/ 在开始编写服务前我们需要修改一下本机(MacOS或Linux)的/etc/hosts文件 127.0.0.1 my-photo-print.com
127.0.0.1 my-yunpan.com
127.0.0.1 open.my-yunpan.com 注由于示例中较少使用到js且form action的地址也是同源的并且通过重定向来跳转所以基本不涉及到跨域问题[11]。 注在演示下面步骤前请先进入到oauth2-examples的各个目录下通过go run main.go启动各个服务程序(每个程序一个终端窗口)。 3.1 用户使用my-photo-print.com照片冲印服务 按照流程用户首先通过浏览器打开照片冲印服务的首页http://my-photo-print.com:8080如下图 这个页面是由homeHandler提供的 // oauth2-examples/my-photo-print/main.go// 照片冲印主页引导用户去授权平台
func homeHandler(w http.ResponseWriter, r *http.Request) {fmt.Println(homeHandler:, *r)// 渲染首页页面模板var state randString(6)mu.Lock()stateCache[state] struct{}{}mu.Unlock()tmpl : template.Must(template.ParseFiles(home.html))data : map[string]interface{}{State: state,}tmpl.Execute(w, data)
} 这里我们使用了服务端模板渲染并将渲染的结果作为应答发给浏览器home.html模板的内容如下 // oauth2-examples/my-photo-print/home.html!DOCTYPE html
html
headtitle照片冲印服务/title
/head
bodyh3欢迎使用照片冲印服务!/h3div用户名: input nameusername/密码: input namepassword typepassword/ button登录/button/divbutton idauth-btn使用云盘账号登录/buttonscriptvar authBtn document.getElementById(auth-btn);authBtn.addEventListener(click, function() {var clientId my-photo-print; var scope user_info,read_photos;var state {{.State}};var url http://open.my-yunpan.com:8081/oauth/portal?client_id clientId scope scopestate state redirect_urihttp%3A%2F%2Fmy-photo-print.com%3A8080%2Foauth%2Fcb window.location.href url;})/script
/body
/html 当用户选择并点击“使用云盘账号登录”时浏览器将打开云盘开放平台/授权服务的首页(http://open.my-yunpan.com:8081/oauth/portal)。 3.2 使用open.my-yunpan.com进行授权 下面是云盘开放平台/授权服务的首页 这个页面由open.my-yunpan.com的portalHandler提供 // oauth2-examples/open-my-yunpan/main.gofunc portalHandler(w http.ResponseWriter, r *http.Request) {fmt.Println(portalHandler:, *r)// 获取请求参数用于渲染应答html页面clientID : r.FormValue(client_id)scopeTxt : r.FormValue(scope)state : r.FormValue(state)redirectURI : r.FormValue(redirect_uri)// 渲染授权页面模板tmpl : template.Must(template.ParseFiles(portal.html))data : map[string]interface{}{AppName: clientID,Scopes: strings.Split(scopeTxt, ,),ScopeTxt: scopeTxt,State: state,RedirectURI: redirectURI,}tmpl.Execute(w, data)
} 和照片冲印服务首页一样这里同样使用了模板渲染的应答页面对应的portal.html模板的内容如下 !DOCTYPE html
htmlheadtitle云盘授权页面/title/headbodyh3云盘授权页面/h3p应用{{.AppName}}正在请求获取以下权限:ul{{range .Scopes}}li{{.}}/li{{end}}/ul/pform idauthorization-form methodpost action/oauth/authorizediv用户名:input nameusername idusername /密码:input namepassword idpassword typepassword /input typehidden nameresponse_type valuecode /input typehidden nameclient_id value{{.AppName}} /input typehidden namescope value{{.ScopeTxt}} /input typehidden namestate value{{.State}} /input typehidden nameredirect_uri value{{.RedirectURI}} /button typesubmit授权/button/div/form/body
/html 该页面将照片冲印服务要获得的权限以列表形式展示给用户然后提供了一个表单用户填写用户名和密码后点击“授权”浏览器便会向开放平台授权服务的/oauth/authorize发起post请求以获取codepost请求携带了一些form参数像response_type、client_id、scope、state等。 /oauth/authorize端点由authorizeHandler负责处理 // oauth2-examples/open-my-yunpan/main.gofunc authorizeHandler(w http.ResponseWriter, r *http.Request) {fmt.Println(authorizeHandler:, *r)responsTyp : r.FormValue(response_type)if responsTyp ! code {w.WriteHeader(http.StatusBadRequest)return}user : r.FormValue(username)password : r.FormValue(password)mu.Lock()v, ok : validUsers[user]if !ok {fmt.Println(not found the user:, user)mu.Unlock()w.WriteHeader(http.StatusNonAuthoritativeInfo)return}mu.Unlock()if v ! password {fmt.Println(invalid password)w.WriteHeader(http.StatusNonAuthoritativeInfo)return}clientID : r.FormValue(client_id)scopeTxt : r.FormValue(scope)state : r.FormValue(state)redirectURI : r.FormValue(redirect_uri)code : randString(8)mu.Lock()codeCache[code] authorizeContext{clientID: clientID,scopeTxt: scopeTxt,state: state,redirectURI: redirectURI,}mu.Unlock()unescapeURI, _ : url.QueryUnescape(redirectURI)redirectURI fmt.Sprintf(%s?code%sstate%s, unescapeURI, code, state)w.Header().Add(Location, redirectURI)w.WriteHeader(http.StatusFound)
} authorizeHandler会对用户进行身份认证通过后它会分配code并向浏览器返回重定向的应答重定向的地址就是照片冲印服务的回调地址http://my-photo-print.com:8080/cb?codexxxstateyyy。 3.3 换取access token并读取用户照片列表 这个重定向相当于用户浏览器向http://my-photo-print.com:8080/cb?codexxxstateyyy发起请求为照片冲印服务提供code该请求由my-photo-print的oauthCallbackHandler处理 // oauth2-examples/my-photo-print/main.go// callback handler用户拿到code后调用该handler
func oauthCallbackHandler(w http.ResponseWriter, r *http.Request) {fmt.Println(oauthCallbackHandler:, *r)code : r.FormValue(code)state : r.FormValue(state)mu.Lock()_, ok : stateCache[state]if !ok {mu.Unlock()fmt.Println(not found state:, state)w.WriteHeader(http.StatusBadRequest)return}delete(stateCache, state)mu.Unlock()// fetch access_token with codeaccessToken, err : fetchAccessToken(code)if err ! nil {fmt.Println(fetch access_token error:, err)return}fmt.Println(fetch access_token ok:, accessToken)// use access_token to get users photo listuser, pl, err : getPhotoList(accessToken)if err ! nil {fmt.Println(get photo list error:, err)return}fmt.Println(get photo list ok:, pl)mu.Lock()userPhotoList[user] plmu.Unlock()w.Header().Add(Location, /photos?useruser)w.WriteHeader(http.StatusFound)
} 这个handler中做了很多工作包括使用code换取access token使用access token读取用户的照片列表并存储在自己的存储中(这里用内存模拟生产环境应该使用数据库服务实现)最后返回一个重定向应答。 用户浏览器收到重定向应答后会重定向访问照片冲印服务的photos端点: http://my-photo-print.com:8080/photos?usertonybai以获取该用户的照片列表。photos端点的处理Handler如下 // oauth2-examples/my-photo-print/main.go// 待获取到用户照片数据后让用户浏览器重定向到该页面
func listPhonesHandler(w http.ResponseWriter, r *http.Request) {fmt.Println(listPhonesHandler:, *r)user : r.FormValue(user)mu.Lock()pl, ok : userPhotoList[user]if !ok {mu.Unlock()fmt.Println(not found user:, user)w.WriteHeader(http.StatusNotFound)return}mu.Unlock()// 渲染照片页面模板tmpl : template.Must(template.ParseFiles(photolist.html))data : map[string]interface{}{Username: user,PhotoList: pl,}tmpl.Execute(w, data)
} 这里使用了photolist.html并结合用户的照片列表数据一起来渲染照片列表页面并返回给浏览器 到这里示例演示就结束了用户通过授权让照片冲印服务读取到了照片数据。 这里还有一个服务没有提及那就是my-yunpan.com云盘服务它的实现较为简单所以这里就不赘述了。 注生产中my-yunpan.com云盘服务是要对照片冲印服务的access token进行校验的这里是演示程序没有引入数据库或redis来共享access token因此这里没有校验。 4. 小结 OAuth是一种广泛使用的开放授权机制。它通过引入授权服务器的概念实现了用户在不共享自己的用户名密码情况下也能安全地向第三方应用提供特定权限的数据访问授权。 本文通过云盘开放平台和第三方照片打印服务的应用场景详细说明了OAuth出现的背景和解决的问题并结合工作流程图和Go示例代码通俗易懂地介绍了OAuth2授权码模式的整体交互流程和实现机制。希望大家通过对这篇文章的阅读能加深对OAuth2工作原理和机制的理解。 文本涉及的源码可以在这里[12]下载。 注鉴于本人在前端的小白水平文中涉及的html代码部分在大模型的帮助下完成。渲染出来的页面比较丑陋还望大家不要责怪:)。 注Go社区提供了很多OAuth包可以帮助大家快速构建OAuth2的授权服务器比如https://github.com/go-oauth2/oauth2等。 5. 参考资料 OAuth2 Specification[13] - https://tools.ietf.org/html/rfc6749《OAuth2实战[14]》- https://book.douban.com/subject/30487753/An Illustrated Guide to OAuth and OpenID Connect[15] - https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc《OAuth2实战课[16]》OAuth和OpenID Connect的过去、现在和未来[17] - https://curity.medium.com/the-past-the-present-and-the-future-of-oauth-and-openid-connect-9b3fbf574519 “Gopher部落”知识星球[18]旨在打造一个精品Go学习和进阶社群高品质首发Go技术文章“三天”首发阅读权每年两期Go语言发展现状分析每天提前1小时阅读到新鲜的Gopher日报网课、技术专栏、图书内容前瞻六小时内必答保证等满足你关于Go语言生态的所有需求2023年Gopher部落将进一步聚焦于如何编写雅、地道、可读、可测试的Go代码关注代码质量并深入理解Go核心技术并继续加强与星友的互动。欢迎大家加入 著名云主机服务厂商DigitalOcean发布最新的主机计划入门级Droplet配置升级为1 core CPU、1G内存、25G高速SSD价格5$/月。有使用DigitalOcean需求的朋友可以打开这个链接地址[19]https://m.do.co/c/bff6eed92687 开启你的DO主机之路。 Gopher Daily(Gopher每日新闻) - https://gopherdaily.tonybai.com 我的联系方式 微博(暂不可用)https://weibo.com/bigwhite20xx微博2https://weibo.com/u/6484441286博客tonybai.comgithub: https://github.com/bigwhiteGopher Daily归档 - https://github.com/bigwhite/gopherdaily 商务合作方式撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。 参考资料 [1] 通过实例理解Go Web身份认证的几种方式: https://tonybai.com/2023/10/23/understand-go-web-authn-by-example/ [2] 通过实例理解Web应用授权的几种方式: https://tonybai.com/2023/11/04/understand-go-web-authz-by-example/ [3] OAuth2授权: https://tools.ietf.org/html/rfc6749 [4] OpenID身份认证(OIDC, OpenID Connect): https://openid.net/specs/openid-connect-core-1_0.html [5] OAuth是一个开放标准: https://en.wikipedia.org/wiki/OAuth [6] OAuth 1.0协议才以RFC 5849的形式正式发布: https://www.rfc-editor.org/rfc/rfc5849 [7] OAuth 2.0以RFC 6749发布: https://datatracker.ietf.org/doc/html/rfc6749 [8] OAuth 2.0的RFC协议规范: https://datatracker.ietf.org/doc/html/rfc6749 [9] 通过实例理解Go Web身份认证的几种方式: https://tonybai.com/2023/10/23/understand-go-web-authn-by-example/ [10] 通过实例理解Web应用授权的几种方式: https://tonybai.com/2023/11/04/understand-go-web-authz-by-example/ [11] 跨域问题: https://tonybai.com/2023/11/19/understand-go-web-cross-origin-problem-by-example/ [12] 这里: https://github.com/bigwhite/experiments/tree/master/oauth2-examples [13] OAuth2 Specification: https://tools.ietf.org/html/rfc6749 [14] OAuth2实战: https://book.douban.com/subject/30487753/ [15] An Illustrated Guide to OAuth and OpenID Connect: https://developer.okta.com/blog/2019/10/21/illustrated-guide-to-oauth-and-oidc [16] OAuth2实战课: https://time.geekbang.org/column/intro/100053901?codexEq9GQzVQBD0fk2eJ2wRE811l71Ld3NxuFeQg7hN8B0%3D [17] OAuth和OpenID Connect的过去、现在和未来: https://curity.medium.com/the-past-the-present-and-the-future-of-oauth-and-openid-connect-9b3fbf574519 [18] “Gopher部落”知识星球: https://public.zsxq.com/groups/51284458844544 [19] 链接地址: https://m.do.co/c/bff6eed92687