记一次OAuth2.0用户鉴权

前言

我们平时登录不同的平台,总会有使用到Token的场景,比如用github账户登录掘金,这个时候我们肯定不会把自己的github账号密码给掘金, OAuth 就是这样一套机制,用于各种免密授权登录场景,在便利的同时保证安全性,其实就是向平台申请token授权。笔者最近在用spotify API二次开发自己的应用,所以也碰到用户鉴权登录的场景,踩坑蛮多,也学到很多,所以整理下来,希望能帮助到大家🤗。

简要的授权流程

  • 用户打开客户端以后,客户端要求用户给予授权(掘金登录选项:github登录)。
  • 用户同意给予客户端授权(我点击github登录,登录通过)。
  • 客户端使用上一步获得的授权,向认证服务器申请令牌(掘金申请 access_token)。
  • 认证服务器对客户端进行认证以后,确认无误,同意发放令牌(github给他 access_token)。
  • 客户端使用令牌,向资源服务器申请获取资源(掘金拿着access_token 去换资源)。
  • 资源服务器确认令牌无误,同意向客户端开放资源(github校验通行)。

掘金和github简要举例,帮助大家理解,接下来我用Spotify的鉴权详细举例吧

授权码模式(authorization code)

你的网站需要获得服务器的授权,要现在对应的开发者申请账号、秘钥、重定向地址

  • client_id:我们去spotify那里注册的
  • client Secret: soptify给我们的秘钥
  • redirect_uri:认证服务器把客户端重定向去的一个 url(本地开发一般是loacalhost)
  • response_type:需要你给我一个 code
  • state:任意值,规范规请求和返回时都是一样的值

首先示范一下如何在spotify develope申请开发者身份

这里针对申请spotify开发者身份的流程介绍,图文较多,不敢兴趣的可以划过,下面有我对OAth鉴权的流程介绍。

  • 登录后点击create a client id,生成一个专用的client_idclient_secret

  • 同时设置Redirect URIs,这是通过鉴权后重定向的地址,端口上运行你的应用,一定要填写准确。

  • Scopes 权限选择,权限选择在进行授权申请之前,要先确定这个应用需要哪些权限,确定好了再到授权过程中通过后端参数进行声明。

    Spotify对权限进行了详细的分类,全部的权限如下:

soptify官网的授权流程

Authentication 授权

授权的最终目的是获取一个名为access_token的值,然后用这个access_token去获取各种个样的API信息。

Spotify为了严格区分不同的用途和权限,把这个access_token的获取方法分为了三种流程,各自的权限、存活期都不同。

三种流程特点如下:

  • Authorization Code Flow: 标准方法,可刷新token
  • Client Credentials Flow: app级token,不可获取用户行为。
  • Implicit Grant Flow: 临时授权。可获取用户行为,不可刷新。存活期短。

如果没有用户的点击授权,那么只能使用后两者的授权模式。在用户点击授权后,才能拿到用户的行为种子做个性化开发,这也是推荐的开发者授权模式,接下来就是Authorization Code授权流程:

  • /authorize发送GET请求,请求头包括client_idredirect_uri
  • /authorize,accounts判断是有效client_idredirect_uri,client_secret(这里注意必须和你申请应用填的完全一致)后,Spotify弹出页面,用户手动登录并点击允许授权
  • Spotify把页面跳转至自己设定的callback网址,并明文传输一个Code
  • Code码向/token发送POST请求,并在header中包括一个动态生成并base64编码的Authorization字符串,格式为Authorization: Basic *<base64 encoded client_id:client_secret>*
  • 从Spotify获得访问令牌access_token和更新令牌refresh_token(双令牌)
  • 拿到授权码acess_token后,每次向浏览器请求资源,请求头都会加上Authorization字段
  • access_token过期后就不能再用了,这时请求服务器会返回401状态码,这个时候就要用refresh token来更新token:用refresh_token/token发送POST请求,获得新的access_token

听起来有些弯弯绕绕😵,其实本质上就是根据OAuth 2.0 标准协议,把服务商的资源,来授权给第三方应用访问,常见于单点登录场景(SSO)

理论差不多是上面这些,还有看不懂的小伙伴可以搜有一下OAuth2.0协议,接下来我们开始写代码了~🤗

编码

首先我们的应用进程要获得client_idclient_secret,肯定不能明文写在代码里,我们可以在本地终端写入临时的环境变量,通过node进程模块process读取到id和秘钥。

process 对象是一个 global (全局变量),提供有关信息,控制当前 Node.js 进程。作为一个对象,它对于 Node.js 应用程序始终是可用的,故无需使用 require()

Node进程怎么写入环境变量呢?这里介绍两种临时环境变量的配置方法

配置Node环境变量
  • Windows配置 临时cmd 查看环境变量,添加环境变量,删除环境变量
#查看环境变量
set SPOTIFY_CLIENT_ID
#如果不存在则添加环境变量 
set SPOTIFY_CLIENT_ID=XXXX
set SPOTIFY_CLIENT_SECRET=YYYY
#环境变量追加值 set 变量名=%变量名%;变量内容 (你的应用路径名)
set path=%path%;C:\web;C:\Tools 
#需要删除环境变量,直接=后面不写入值 
set SPOTIFY_CLIENT_ID=
set SPOTIFY_CLIENT_SECRET= 

Window cmd环境图在这

临时 (powershell) 查看环境变量,添加环境变量,删除环境变量

#查看是否存在 
$env:SPOTIFY_CLIENT_ID  
#如果不存在则添加环境变量  
$env:SPOTIFY_CLIENT_ID="XXX" 
$env:SPOTIFY_CLIENT_SECRET="YYY" 
#环境变量追加值 
$env:path=$env:path + ";C:\web;C:\Tools"  
#删除环境变量 del env:SPOTIFY_CLIENT_ID  
#显示所有的环境变量 ls env: 

powershell图在这

这里需要特别注意的是虽然通过 CMD 和 Powershell 都能修改环境变量,在不同终端的环境变量是不能共享的,(笔者在这里踩了很久坑TT)即你在 CMD 可以设置 SPOTIFY_CLIENT_ID="XXX",同时也可以在 Powershell 中设置 SPOTIFY_CLIENT_ID="YYY"如果你只在cmd里设置,Node环境里是读不到的!😰 。并且,上面的环境设置只是临时的,只针对当前运行窗口的环境有效。当终端运行窗口关闭以后,相关设置都会丢失。

设置好后就可以在node中通过process.env.REDIRECT_URI读取到账户、秘钥信息,接下来就是在后端写鉴权需要的各种接口了

先上一张官网的授权流程图,感受一下授权流程🧐

登录
  • /login登录
let redirect_uri = 
  process.env.REDIRECT_URI || 
  'http://localhost:8888/callback'

app.get('/login', function(req, res) {
  res.redirect('https://accounts.spotify.com/authorize?' +
    querystring.stringify({
      response_type: 'code',
      client_id: process.env.SPOTIFY_CLIENT_ID,
      scope: 'user-read-private user-read-email user-read-recently-played user-top-read user-follow-read user-follow-modify playlist-read-private playlist-read-collaborative playlist-modify-public',
      expires_in: 3600,
      redirect_uri
    }))
}) 

这里的scope看着写,需要什么权限就配置什么,权限越多,能访问的用户资源就越多,用户可以点击授权登录后可以在官网链接删除授权。

access_token
  • callback
app.get('/callback', function(req, res) {
  let code = req.query.code || null
  let authOptions = {
    url: 'https://accounts.spotify.com/api/token',
    form: {
      code: code,
      redirect_uri,
      grant_type: 'authorization_code',
      expires_in: 3600
    },
    headers: {
      'Authorization': 'Basic ' + (new Buffer(
        process.env.SPOTIFY_CLIENT_ID + ':' + process.env.SPOTIFY_CLIENT_SECRET
      ).toString('base64'))
    },
    json: true
  }
  request.post(authOptions, function(error, response, body) {
    if(!error && response.statusCode === 200){
      var access_token = body.access_token
      var expires_in = body.expires_in
      let uri = process.env.FRONTEND_URI || 'http://localhost:3000'
      res.redirect(uri + '?access_token=' + access_token +'?expires_in=' + expires_in)
    } else {
      res.redirect(`/#${querystring.stringify({ error: 'invalid_token' })}`);
    }
  })
}) 

若参数无误,响应数据包格式:

若参数无误,服务器将返回一段JSON文本,包含以下参数:

  • access_token:要获取的Access Token。
  • expires_in:Access Token的有效期,以秒为单位。
  • refresh_token:用于刷新Access Token 的 Refresh Token。
  • scope:Access Token最终的访问范围,即用户实际授予的权限列表(用户在授权页面时,有可能会取消掉某些请求的权限)。
  • cookies: 让浏览器记住客户端,包含session_id

这个时候就会自动跳转到最开始设定好的redirect_url,这个时候这个url上运行着我的React应用,有了鉴权之后就可以愉快的使用用户信息,访问调用spotify的API啦~

超时刷新 refresh_token

refresh_token顾名思义,refresh_token就是起到刷新token的作用,避免用户再次点击授权进行验证,那么refresh_token是怎么和access_token联合起来使用的呢?

如果我们遇到了access_token过期了,那么我们需要使用refresh_token去获取一个新的access_token,听起来很简单,那如果refresh_token也过期了呢?这时用户需要重新登录吗?官网给出的解决方案很简单,使用**refresh_token来扩展access_token的有效性。就是协调双令牌

正确的做法即是两个令牌都有自己的过期时间,因为access_token是需要使用refresh_token刷新获取,所以refresh_token设置的过期时间要比access_token时间长,那么如何避免refresh_token过期呢?办法就是我们使用refresh_token刷新了access_token后,将POST请求发送到Accounts服务/api/token端点,grant_type注明是 refresh_token那么Spotify将返回新的access_token。也返回新的refresh_token,这样两个令牌的时间又得到了延长。这就保证了用户在一个规定时间段只要访问了应用,就可以享受无感知的刷新体验。

app.get('/refresh_token', function(req, res) {
  // requesting access token from refresh token
  const refresh_token = req.query.refresh_token;
  let authOptions = {
    url: 'https://accounts.spotify.com/api/token',
    headers: {
      'Authorization': `Basic` + (new Buffer(
          process.env.SPOTIFY_CLIENT_ID + ':' + process.env.SPOTIFY_CLIENT_SECRET
        ).toString('base64')),
    },
    form: {
      grant_type: 'refresh_token',
      refresh_token,
    },
    json: true,
  };

  request.post(authOptions, function(error, response, body) {
    if (!error && response.statusCode === 200) {
      var access_token = body.access_token;
      res.send({ access_token });
    }
  });
}); 
axios发具体请求

因为每一次向服务端发请求,请求头都需要带上authorization
所以在我们的前端应用通过
window.location.href.match(/access_token=([^&]*)/)拿到token
window.location.href.match(/expires_in=([\w]*)/)[1]拿到过期时间

… 剩下需要的参数自己匹配 然后axios配置

 headers: {
    'Authorization': `Bearer ${access_token}`,
  } 

就可以发请求拿到数据啦~ 🤭

动图演示具体流程👇

最后

这就是我的一次OAuth2鉴权登录的完整记录啦,(找了蛮多资料发现叙述完整流程的很少,踩了蛮多坑,所以自己动手写了个完整的 ~)

于是乎我们就可以愉快的借助spotify的数据二次开发啦╰(* °▽°* )╯,很感谢看到这里的掘友,希望本文能让你收获些东西,本文以spotify的开放API举例,不玩spotify也没关系,相信大家也能从本文了解一下OAth2的鉴权流程,码字不易,希望你喜欢🥰

接下来我将给各位同学划分一张学习计划表!

学习计划

那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:

阶段一:初级网络安全工程师

接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。

综合薪资区间6k~15k

1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?

阶段二:中级or高级网络安全工程师(看自己能力)

综合薪资区间15k~30k

7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。

零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;

Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完

用Python编写漏洞的exp,然后写一个简单的网络爬虫

PHP基本语法学习并书写一个简单的博客系统

熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)

了解Bootstrap的布局或者CSS。

阶段三:顶级网络安全工程师

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资料分享

当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。

习资源包免费分享!](https://mp.weixin.qq.com/s/BWb9OzaB-gVGVpkm161PMw)

学习资料分享

当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。

  • 8
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
基于Spring Boot、OAuth2.0和JWT Token认证开发的后台接口是一种使用现代化技术实现的身份验证和授机制。下面是关于这种后台接口的一些说明: 首先,Spring Boot是一个基于Spring框架的快速开发框架,提供了简化的配置和自动化的特性,使开发者能够更快速高效地开发后台接口。 OAuth2.0是一种开放标准的授协议,它允许用户第三方应用访问他们在资源拥有者上存储的信息,而不需要将用户名和密码提供给第三方。 JWT Token(JSON Web Token)是一种用于在网络应用间安全传递声明的一种方式。它被用作身份验证和授的令牌,通过加密并以JSON格式存储信息,确保信息的完整性和安全性。 基于以上技术,我们可以开发出具有强大安全认证能力的后台接口。首先,用户在访问接口时,需要提供他们的身份证明,这可以是用户名和密码。接口服务器会使用OAuth2.0协议进行身份验证,并颁发JWT Token给用户用户在未来的请求中,可以使用该Token进行身份验证,而无需每次都提供用户名和密码。 接口服务器会对JWT Token进行验证,以确保Token的完整性和有效性。如果Token失效或被伪造,访问将被拒绝。如果验证通过,接口服务器会正常处理用户的请求。 使用Spring Boot和OAuth2.0进行开发,可以方便地设置限和角色。可以根据用户的角色和限,限制他们对某些资源的访问。 总之,基于Spring Boot、OAuth2.0和JWT Token认证开发的后台接口提供了一种安全可靠的身份验证和授机制,能够有效保护后台接口的安全性,防止非法访问和数据泄露。这种技术组合在开发现代化的网络应用时非常有用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值