阅读 5179

给你的网站添加第三方登录以及短信验证功能

OAuth 2.0 是目前最流行的授权机制,用来授权第三方应用,获取用户数据。比如掘金这种第三方账号 微信、微博、github 登录方式一样。思考一下这种登录方式是如何设计和实现的呢?日常生活中很多APP或者网站在用户输入完手机号之后都需要发送验证码校验,那么这整套流程又是如何实现的呢?

掘金登录

一、OAuth的思路

OAuth在“客户端”和“服务供应商”之间,设置了一个授权层。“客户端”不能直接登录“服务供应商”,只能登录授权,以此将用户与客户端区分开来。“客户端”登录授权之后,“服务提供商”根据令牌的权限范围和有效期,向"客户端"开放用户储存的资料。

简单说,OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

二、OAuth的登录实践

以GitHub为例子,实现OAuth的授权登录。接下来我会一步步实践如何在你的网站中接入github授权登录

1、GitHub 应用登记

点击按钮去github主页新建一个OAuth App,点击创建 按如下提示填写信息

创建完之后记住页面上方的 Client ID 和 Client Secret,后面开发时需要用到这两个参数。

2、代码实现

2.1 前端实现

前端采用了掘金的授权登录方式,当用户点击第三方GitHub登录,弹出一个新窗口

window.open("/oauth", "", "height=600, width=700")

在这个新窗口里只需要跳转链接,client_id,redirect_uri 就是之前创建的参数配置自己的就行。

window.location.href = 'github.com/login/oauth…' 用户授权登录之后会跳到redirect页面,在redirect请求后端带上刚产生的code,后端拿到code请求github得到的用户信息资料,最后关闭弹窗。

2.2 后端实现

后端作者采用的是Koa2,代码如下

router.get('/oauth', async function(ctx, next) {
  const requestToken = ctx.request.query.code
  const tokenResponse = await axios({
    method: 'post',
    url: 'https://github.com/login/oauth/access_token?' +
      `client_id=${OAUTH_GITHUB.clientID}&` +
      `client_secret=${OAUTH_GITHUB.clientSecret}&` +
      `code=${requestToken}`,
    headers: {
      accept: 'application/json'
    }
  })
  const accessToken = tokenResponse.data.access_token
  const result = await axios({
    method: 'get',
    url: `https://api.github.com/user`,
    headers: {
      accept: 'application/json',
      Authorization: `token ${accessToken}`
    }
  })
复制代码

后面根据自己的业务需求,将获取到的信息存入到用户表中。这里的方式很多,我是直接将github授权登录的信息插入到我的用户表里,或者你新建一个第三方oauth表去存放也是可以的。

const oauthLogin = async (userData = {}) => {
  const username = userData.username
  const nickname = userData.username
  const avatar = userData.avatar
  const date = Date.now()
  const userSql = `select * from users where username = '${username}' `
  const rows = await exec(userSql)
  if (rows.length > 0) {
    return rows[0] || {}
  } else {
    const sql = `insert into users (username,password, nickname, avatar, date) values ('${username}', '${password}', '${nickname}', '${avatar}', '${date}');`
    const insertData = await exec(sql)
  }
}
复制代码

最后的效果

三、短信验证登录

3.1 开通短信服务

短信验证自然需要用到服务商,阿里云有免费短信开通功能,免费开通短信服务,开通之后按每条0.04元计算。为了练习充了一元测试短信验证功能,免费开通这个还是非常的好的,不用发很多钱就可以上手测试

3.2 前端实现

还是拿掘金的案例来讲,用户点击注册输入手机号之后,点击获取验证码。

3.3后端实现

router.post('/sendSmsCodeToUser', async function (ctx, next) {
  const { username } = ctx.request.body
  CODE = Math.random().toString().slice(-6)
  var client = new RPCClient({
    accessKeyId: 'LTAI4FcGip5kqy1', // 自己申请短信的
    accessKeySecret: 'BvmhpNobez41as1vA5z1QSbhTGIm', 
    endpoint: 'https://dysmsapi.aliyuncs.com',
    apiVersion: '2019-12-14'
  })
  var params = {
    "RegionId": "cn-hangzhou",
    "PhoneNumbers": `${username}`,
    "SignName": "起航网",
    "TemplateCode": "SMS_180059442",
    "TemplateParam": `{code: ${CODE}}`
  }
  var requestOption = {
    method: 'POST'
  }
  var result = await client.request('SendSms', params, requestOption).then((res) => {
      return res
    }, (ex) => {
      return ex
    })
  if ('Code' in result) {
    ctx.body = new SuccessModel({message: '验证码发送成功'})
  } else {
    const limit = result.data.Message.split(':')[1]
    ctx.body = limit >= 10 ? new ErrorModel({message: '同一手机号每天只能发送 10 条验证码'}) : new ErrorModel({message: '同一手机号每小时只能发送 5 条验证码'})
  }
})
复制代码

前后端请求对比CODE,实现短信验证登录功能

关注下面的标签,发现更多相似文章
评论