QQ互联(QQ登录),前后端分离对接思路 - boyyang的个人博客网站

如何接入QQ登录功能,我在网上查询了很多实现方案,但是前后端分离的情况。没有看到有实现的方案,有肯定是有的,可能没有找到。

接下来大概讲一下前后端分离的情况下,接入QQ登录功能的大概思路。在整个接入的流程中最重要的两个东西是,appid和appkey( 申请地址 ),

1. 申请基本信息填写

下拉选择根据网站来或者选里面的其它选项,网站名称和简介貌似没有啥影响,点击创建应用进入下一步。

这一步的的填写就比较关键了,网站地址也就是你部署项目的域名,回调地址(我使用的是前端页面的地址),网站地址以及回调地址必须为同一个域名下的,比如说你的网站地址为:https://www.boyyang.cn 那么你的回调地址必须也是该域名下的地址,比如:https://www.boyyang.cn/loginBack

提供方如果你是个人开发就直接写你名字就行,如果是为公司就填写公司名称,图标按照要求上传就行,网站备案号,也就是你填写的网站地址备案号就行。如果你的域名没有备案,那肯定是不行的。

什么是回调地址呢?回调地址就是当用户授权登录成功后,QQ互联的那个页面会跳转到你所填写的回调地址页面。

当你在这个页面授权登录成功后,他会打开你所填写的回调地址页面,同时他会拼接上code参数。前端获取到code后,就可以将这个code通过接口传递给后端,后端通过这个code进行一系列操作便可以获取到用户端一些基本信息,比如说用户名称,用户头像,性别等等。

在填写完基本信息后,你的应用会处于审核状态,这个时候你就可以通过点击查看获取到appid和appkey这2个重要的参数了。

2.前端页面准备 前端得准备2个页面,第一个页面就是你登录按钮放哪儿,这个按钮最好放你网站首页比较显眼的位置,因为上一步填写成功后,QQ互联的审核员会访问你提供的网站地址进行访问,如过你的页面打不开或者没有QQ登录按钮审核不会给通过的。第二个页面便是你的回调地址页面。

点击QQ登录按钮的代码如下:

const qqLogin = () => {

const state = JSON.stringify({path: route.path, query: route.query})

window.sessionStorage.setItem('state', state)

const url = `https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=${APP_ID}&state=${state}&redirect_uri=${encodeURIComponent(REDIRECTURI)}`

window.open(url, '_blank')

} 其中state可以根据自己的需求传递,最好是唯一的,这个值是必须传递的,你传递的是啥,在授权成功后,他会将该值传回给你,这样你就可以知道这个链接是否被篡改过的。

回调页面的大致代码如下:

在这个页面你可以拿到code以及state的值,将code传递给后端,接下来就是后端的工作了。后端通过前端获取到的code等参数获取用户信息等相关操作。在signInByQQ这个接口其实就可以直接返回用户信息,token等相关信息了。

3.后端 后端做得操作相对来说比较多,由于我使用的go-zero作为后端框架,所以就讲一些大概的过程。

在前端拿到code后通过signInByQQ这个接口将code传递给了后端,后端拿到这个后可以通过code去获取AccessToken 代码片段如下:

type AccessTokenInfo struct {

AccessToken string `json:"access_token"`

ExpiresIn string `json:"expires_in"`

RefreshToken string `json:"refresh_token"`

}

func AccessToken(code string, redirectURI string) (accessToken *AccessTokenInfo, err error) {

params := url.Values{}

params.Add("grant_type", "authorization_code")

params.Add("client_id", AppId)

params.Add("client_secret", AppKey)

params.Add("code", code)

params.Add("fmt", "json")

str := fmt.Sprintf("%s&redirect_uri=%s", params.Encode(), redirectURI)

loginURL := fmt.Sprintf("%s?%s", "https://graph.qq.com/oauth2.0/token", str)

response, err := http.Get(loginURL)

if err != nil {

return nil, err

}

body, err := io.ReadAll(response.Body)

if err != nil {

return nil, err

}

defer func(Body io.ReadCloser) {

_ = Body.Close()

}(response.Body)

var accessTokenInfo AccessTokenInfo

err = json.Unmarshal(body, &accessTokenInfo)

if err != nil {

return nil, err

}

return &accessTokenInfo, nil

} 通过code换取到token后下一步便是通过token换取openid了,代码片段如下:

type OpenIdInfo struct {

OpenId string `json:"openid"`

ClientId string `json:"client_Id"`

}

func OpenId(accessToken string) (openIdInfo *OpenIdInfo, err error) {

resp, err := http.Get(fmt.Sprintf("%s?access_token=%s&fmt=json", "https://graph.qq.com/oauth2.0/me", accessToken))

if err != nil {

return nil, err

}

defer func(Body io.ReadCloser) {

_ = Body.Close()

}(resp.Body)

body, err := io.ReadAll(resp.Body)

if err != nil {

return nil, err

}

err = json.Unmarshal(body, &openIdInfo)

if err != nil {

return nil, err

}

return openIdInfo, nil

}

在获取到token以及openid后,便可以通过这2个参数去获取用户的基本信息了,代码片段如下:

type QQUserInfo struct {

Nickname string `json:"nickname"`

Avatar string `json:"figureurl_qq_1"`

}

func UserInfo(accessToken string, openid string) (userInfo *QQUserInfo, err error) {

params := url.Values{}

params.Add("access_token", accessToken)

params.Add("openid", openid)

params.Add("oauth_consumer_key", AppId)

uri := fmt.Sprintf("https://graph.qq.com/user/get_user_info?%s", params.Encode())

resp, err := http.Get(uri)

if err != nil {

return nil, err

}

defer func(Body io.ReadCloser) {

_ = Body.Close()

}(resp.Body)

body, err := io.ReadAll(resp.Body)

if err != nil {

return nil, err

}

err = json.Unmarshal(body, &userInfo)

if err != nil {

return nil, err

}

return userInfo, nil

}

这里我只获取了用户昵称以及头像,除此之外以为还能获取到一些其它的信息:

参数说明描述ret返回码msg如果ret<0,会有相应的错误信息提示,返回数据全部用UTF-8编码is_lost判断是否有数据丢失。如果应用不使用cache,不需要关心此参数。0或者不返回:没有数据丢失,可以缓存。1:有部分数据丢失或错误,不要缓存nickname用户在QQ空间的昵称。figureurl大小为30×30像素的QQ空间头像URL。figureurl_1大小为50×50像素的QQ空间头像URL。figureurl_2大小为100×100像素的QQ空间头像URL。figureurl_qq_1大小为40×40像素的QQ头像URL。figureurl_qq_2大小为100×100像素的QQ头像URL。需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有。gender性别。 如果获取不到则默认返回"男"gender_type性别类型。默认返回2province省city市year年constellation星座is_yellow_vip标识用户是否为黄钻用户yellow_vip_level黄钻等级is_yellow_year_vip是否为年费黄钻用户 拿到这些信息后,后端便可以通过这些信息写入数据库了,然后下发token等信息返回给前端。整个流程也就结束了。

3.一些注意项 QQ登录接入过程中是不好调试的,在审核前需要将前端的按钮放出来,并且点击按钮成功跳转到QQ登录的页面,只有这样审核才会通过。也就是说你的网站必须将前置工作做完了,然后线上能访问了,审核才会给你通过。

总结: 在刚刚接触看到那么多东西,脑子一团浆糊,按照文档一步一步下来,其实就是调取QQ互联的接口,按照接口顺序获取参数,比如说code,token这类的东西,然后拿这些东西取换取用户信息,拿到了这些信息,怎么处理就是自己的事情了。

Copyright © 2088 影月电竞大师赛 - 赛事与排位攻略 All Rights Reserved.
友情链接