Skip to content

Instantly share code, notes, and snippets.

@riskers
Last active April 16, 2021 11:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save riskers/1deb046e0c2d0f130980bab4bbd17abb to your computer and use it in GitHub Desktop.
Save riskers/1deb046e0c2d0f130980bab4bbd17abb to your computer and use it in GitHub Desktop.
cookie-session vs JWT vs oauth vs CAS

都可以做 SSO

  • CAS: 多个系统只需登录一次,无需重复登录
  • oAuth: 第三方系统访问主系统资源,用户无需将在主系统的账号告知第三方,只需通过主系统的授权,第三方就可使用主系统的资源(如:APP1需使用微信支付,微信支付会提示用户是否授权,用户授权后,APP1就可使用微信支付功能了)

概述

oAuth 是一个关于授权的开放网络标准,目前 2.0 版。

oAuth 的作用就是让客户端安全可控地获取用户授权,与服务提供商互动

  • Third-party application: 第三方应用(『客户端』,就是开发者)
  • HTTP service: HTTP服务提供商(如 github )
  • Resource Owner: 资源所有者(用户)
  • User Agent: 用户代理(浏览器)
  • Authorization: 认证服务器,即服务提供商专门用来处理认证的服务器
  • Resource server: 资源服务器,即 github 存在用户生成的资源的服务器,和认证服务器可以是同一台服务器也可以是不同服务器

思路

oAuth 在『客户端』与『服务提供商』之间,设置了一个授权层(authorization layer)。客户端不能直接登录『服务提供商』,只能登录授权层,这样将用户和『客户端』区分开。

  • 『客户端』登录授权层使用 token(令牌)
  • 用户登录服务提供商使用的是密码,用户在登录时可以指定授权层的权限范围和有效期

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

流程

人人网开放平台创建应用

得到 API KEYSecret Key:

一定要填写回调:

用户使用 oAuth 是这个流程:

  • A. 用户打开客户端,客户端要求用户给授权

  • B. 用户同意授权给客户端

    http://graph.renren.com/oauth/grant
    
    * client_id=e9677ff99be74072ba2c59cd2dad944b
    * redirect_uri=http%3A%2F%2Flocalhost%3A3333%2Fmain
    * response_type=code
    * display=page
    * secure=true
    * origin=00000
    

    用户同意授权之后,页面会跳转到指定的回调地址。 这里我使用了 http://localhost:3333 本地地址,并且带上了『应用授权码』(code参数)

  • C. 客户端使用上一步得到的授权,向认证服务器申请 token

    https://graph.renren.com/oauth/token
    
    /*params*/
    * grant_type=authorization_code
    * client_id=e9677ff99be74072ba2c59cd2dad944b
    * redirect_uri=http://localhost:3333/main
    * client_secret=a3ab032aa239488abf081019b5fa2385
    * code=vgHiJEY3Bc4GctffDNXQ1bu1TsUTZn98
    

    把 code 和 secret key 一起发送申请token

    这一步在客户端的后台服务器上完成,对用户不可见,这很重要!因为你的 secret key 是不能暴漏出来的!

  • D. 认证服务器对客户端进行认证后,确认无误,同意发放 token

  • E. 客户端使用 token,向资源服务器申请获取资源

    使用 token 调用 API

  • F. 资源服务器确认 token 无误,同意向客户端开放资源

授权模式

  • 授权码模式
  • 简化模式
  • 密码模式
  • 客户端模式

刚才说的人人网使用的就是授权码模式,这也是功能最完整、流程最严密的授权模式。特点是通过客户端的后台服务器,与"服务提供商"的认证服务器进行互动。


@riskers
Copy link
Author

riskers commented Apr 3, 2019

@riskers
Copy link
Author

riskers commented Jun 4, 2020

微信登录 Token 案例

FE

前端重定向到一个微信提供的地址:

login = () => {
    location.href = `https://open.weixin.qq.com/connect/qrconnect?appid=${APP_ID}&redirect_uri=${encodeURIComponent('http://localhost:3000/api/wechat/callback')}&response_type=code&scope=snsapi_login&state=${Math.random()}#wechat_redirect`
  }

然后到了这个页面,微信扫码登录:

Server

扫码登录后跳转到 callback 页面:

router.get('/wechat/callback', async(ctx) => {
  // code 是微信平台带过来的,需要用 code 申请 token
  const { code } = ctx.request.query

  // 申请 token
  const res = await axios.get(`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${APPID}&secret=${APPSECRET}&code=${code}&grant_type=authorization_code`)

  const {
    access_token,
    refresh_token,
    openid,
    unionid,
  } = res.data

  // 有了 access_token 可以再去调用微信 API 获得头像等用户信息
  // 略
  
  // 这里把 openid 作为 cookie 带到前端,其实用 token 好一点
  ctx.cookies.set('uid', openid)
  ctx.response.redirect('/')
})

然后把 token 存在 redis 里,每次请求 cookie 里的 token 都会带上,验证是否合法,不合法则重新登录,略。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment