Github OAuth

说起来真是糟心,国内的三方登录大部分都是比较规范的oAuth。但是恶心就恶心在如果正式使用,网站必须有备案。唉,算了,看来也只有国外的没这个变态的要求了。

Github 上注册一个APP

之前名字是Applications后来改成OAuth applications了。 点进去新建一个app然后填写对应的信息,这里不再赘述。

在网站上配置授权登录

开始

1、进入授权链接构建

# 请求URL
https://github.com/login/oauth/authorize
参数名 类型
client_id String 注册App时官方分配的
redirect_uri String 用户授权后带着code跳转的链接地址(如:http://www.woolson.cn/github/callback)
scope String 控制需要获取权限的范围,具体看API,第三方登录的这里就不用传这个参数就行了
state String 这参数会在Github重定向的时候带着,用来判断获取信息请求是否被其他人拦截返回,可随机生成一段
# 构建下面这个样链接
https://github.com/login/oauth/authorize?client_id=${client_id}&redirect_uri=${redirect_uri}&state=${state}

可在前端放置一枚按钮,直接 location.href 到此链接,然后会跳转至Github的授权页授权

后端处理获取用户信息

用户授权后跳转至 redirect_uri 后端路由处理拿到的 code 换取 access_token(获取用户信息关键)

code会带在redirect_uri后面,使用路由中 request.query.code 获取

http://www.woolson.cn/github/callback?code=*****&state=*****

下面用 code 获取 access_token

我直接使用 NodeJS 的 Request 模块直接后端操作,so redirect_uri就不用了

# 请求URL
https://github.com/login/oauth/access_token
参数名 类型
client_id String 注册App时官方分配的
client_secret String 注册App时官方分配的
code String 刚刚那个code
state String 在第一步中带的state,现在继续带上(其实不带入也可以的)

Request 发送请求拿 token

const param = {
  url: "https://github.com/login/oauth/access_token",
  client_id: "{client_id}",
  client_secret: "{client_secret}",
  code: req.query.code,
}

request(fetchUrlwithParams(param), (err, response, body) => {
  body = JSON.parse(body)
  body.access_token // 这个就是需要拿到的token
})

access_token 获取 user 的信息 注意:需要在请求中加入请求头 User-Agent 并且值为你APP的名称

# 请求URL
https://api.github.com/user
参数名 类型
access_token String 只需要带上上一步返回的access_token即可
if(body.access_token) {
  const param = {
    url: "https://api.github.com/user?access_token=" + body.access_token,
    headers: {
      "User-Agent": "app name",
    }
  }
  request(param, (err, response, body) => {
    body = JSON.parse(body)
    if(!body.message) insertGithub(req, res, body)
    else res.redirect("/study")
  })
}else res.redirect("/")

如上,如果获取用户信息失败,会在返回信息中带有 message 字段。获取正常,存储用户信息;获取失败,重定向到网站首页。

存储用户信息和种cookie

1、这一步是为啥呢,因为不可能每次打开网站都进行一次授权。小网站做登录有点矫情。 2、保存用户信息。怕保存数据量太大,对需要的信息保存一下。(本网站没保存任何敏感信息,只有名称和Github主页) 3、种植cookie,在浏览器中种上类似于ID的东西,用户访问就带上,类似于记住我的功能一样。等过期了,再让用户授权一次。

可以使用Mongodb,进行数据保存,这里不做赘述。 种植 cookie 就是在重定向到网站的时候在 Response 中带上 cookie

const param = {
  domain: ".woolson.cn",
  maxAge: 5184000000,
  httpOnly: false,
  secure: false,
  path: "/",
}

user.save((err, docs) => {
  res.cookie("user", hashs.nameHash, param)
  res.redirect("/study")
})

种上cookie以后就是取 cookie, Nodejs 需要在App上使用 cookie-parser Like this:

import cookieParser from "cookie-parser"
app.use(cookieParser())

然后在以后的请求中获取 cookie

在保存的时候种的cookie,里面带有你用户的ID用来取用户信息的。

app.get("/oauth/login", (req, res) => {
  const userID = req.cookies.user
  if(userID) getLoginUser(req, res)
  else jsonWrite(res)
})

这样就能拿到信息啦……其实后面说的都比较简单,具体实现可以根据实际情况。