记一次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}`,
  } 

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

动图演示具体流程👇

最后

今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。

网络安全学习资源分享:

最后给大家分享我自己学习的一份全套的网络安全学习资料,希望对想学习 网络安全的小伙伴们有帮助!

零基础入门

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

【点击领取】网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

1.学习路线图

攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去接私活完全没有问题。

2.视频教程

网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。【点击领取视频教程】

在这里插入图片描述

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取技术文档】

在这里插入图片描述

(都打包成一块的了,不能一一展开,总共300多集)

3.技术文档和电子书

技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本【点击领取书籍】

在这里插入图片描述

4.工具包、面试题和源码

“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。

在这里插入图片描述

最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。

这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。

参考解析:深信服官网、奇安信官网、Freebuf、csdn等

内容特点:条理清晰,含图像化表示更加易懂。

内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…

!(https://img-blog.csdnimg.cn/8de5365b55fd4a929e0cef43c14ce512.png)
在这里插入图片描述

因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享

  • 18
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值