网站接入QQ登录注意事项-编程思维

本文主要跟大家分享下我的个人博客 陈新的个人博客 站点在接入QQ登录的过程中所遇到的一些问题,在这里分享给大家,方便准备想接入QQ登录功能的或者接入过程中正遇到一些问题的小伙伴快速解决问题,避免踩我已经踩过的坑。

一、跳转到QQ登录授权页面的地址

跳转到QQ登录授权页面的地址应该用:https://graph.qq.com/oauth2.0/authorize ,而不是用https://graph.qq.com/oauth2.0/show 这个前缀,后者这个是PC端的QQ授权页面,如果你的网站跳转到的是后面这个地址,将会导致手机端使用的QQ登录授权页面也是PC端的,这样手机端就无法使用QQ一键登录功能了,正确的应该使用前者这个地址,腾讯会自动判断跳转到PC端还是手机端的QQ登录授权页面。

手机端的QQ登录界面应该类似于如下:

 

二、QQ授权页面传参

不要往QQ授权页面的地址中传入参数display=pc,这个参数告诉QQ说我当前正在PC端进行QQ一件登录,因此也会造成和上述一样的问题。

以上就是本人在对接QQ登录过程中遇到的一些问题,下面附上本人的个人站中用到的QQ登录的代码,方便大家快速集成QQ登录功能,本人的个人站使用asp.net core 3.1.

接口对接代码

using BlogSys.Models;
using BlogSys.Models.QQLogin;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace BlogSys.Services
{
    /// <summary>
    /// QQ登录功能。
    /// </summary>
    public class QQLoginService
    {
        const string callbackUrl = "这里填写你提供给腾讯的你的网站的回调地址";
        const string clientId = "这里填写网站应用ID";
        const string clientSecret = "这里填写网站应用秘钥";
        HttpClient client;
        ILogger<QQLoginService> logger;
        public QQLoginService(HttpClient client, ILogger<QQLoginService> logger)
        {
            this.client = client;
            this.logger = logger;
        }
        /// <summary>
        /// QQ 登录
        /// </summary>
        /// <param name="code"></param>
        /// <param name="redirect_url"></param>
        /// <returns></returns>
        public async Task<QQUserInfo> Login(string code)
        {
            QQUserInfo userInfo = null;
            QQApiAccessToken accessToken = await this.GetAccessToken(code, callbackUrl);
            QQOpenIDInfo openIDInfo = await this.GetOpenID(accessToken.access_token);
            userInfo = await this.GetUserInfo(accessToken.access_token, clientId, openIDInfo.openid);
            userInfo.OpenID = openIDInfo.openid;
            return userInfo;
        }
        //根据不同页面点击QQ登录时,生成QQ授权登录页面地址,方面登录前在哪个页面,登录后就跳回哪个页面。
        public string GetQQLoginUrl(string redirectUrl)
        {
            return $"https://graph.qq.com/oauth2.0/authorize?which=Login&response_type=code&redirect_uri={callbackUrl}&client_id={clientId}&state={redirectUrl}";
        }
        /// <summary>
        /// 获取API访问Token.
        /// </summary>
        /// <param name="code"></param>
        /// <param name="redirect_uri"></param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public async Task<QQApiAccessToken> GetAccessToken(string code, string redirect_uri, string fmt = "json")
        {
            string grant_type = "authorization_code";
            string apiUrl = $"/oauth2.0/token?grant_type={grant_type}&client_id={clientId}&client_secret={clientSecret}&code={code}&redirect_uri={redirect_uri}&fmt={fmt}";
            HttpResponseMessage responseMessage = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string resultStr = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(resultStr))
            {
                return null;
            }
            return JsonSerializer.Deserialize<QQApiAccessToken>(resultStr);
        }
        /// <summary>
        /// 根据刷新Token获取访问Token.
        /// </summary>
        /// <param name="refresh_token"></param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public async Task<QQApiAccessToken> GetAccessTokenByRefreshToken(string refresh_token, string fmt = "json")
        {
            string grant_type = "refresh_token";
            string apiUrl = $"/oauth2.0/token?grant_type={grant_type}&client_id={clientId}&client_secret={clientSecret}&refresh_token={refresh_token}&fmt={fmt}";
            HttpResponseMessage responseMessage = await client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string resultStr = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(resultStr))
            {
                return null;
            }
            return JsonSerializer.Deserialize<QQApiAccessToken>(resultStr);
        }
        /// <summary>
        /// 获取QQ OpenId信息
        /// </summary>
        /// <param name="access_token">API访问Token</param>
        /// <param name="fmt"></param>
        /// <returns></returns>
        public async Task<QQOpenIDInfo> GetOpenID(string access_token, string fmt = "json")
        {
            string apiUrl = $"oauth2.0/me?access_token={access_token}&fmt={fmt}";
            HttpResponseMessage responseMessage = await this.client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string apiResult = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(apiResult))
                return null;
            return JsonSerializer.Deserialize<QQOpenIDInfo>(apiResult);
        }
        /// <summary>
        /// 获取用户信息
        /// </summary>
        /// <param name="access_token"></param>
        /// <param name="oauth_consumer_key"></param>
        /// <param name="openid"></param>
        /// <returns></returns>
        public async Task<QQUserInfo> GetUserInfo(string access_token, string oauth_consumer_key, string openid)
        {
            string apiUrl = $"user/get_user_info?access_token={access_token}&oauth_consumer_key={oauth_consumer_key}&openid={openid}";
            HttpResponseMessage responseMessage = await this.client.SendAsync(new HttpRequestMessage(HttpMethod.Get, apiUrl));
            if (!responseMessage.IsSuccessStatusCode)
                return null;
            string apiResult = await responseMessage.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(apiResult))
                return null;
            return JsonSerializer.Deserialize<QQUserInfo>(apiResult);
        }
    }
}

 

QQ登录相关实体模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSys.Models.QQLogin
{
    public class QQUserInfo
    {
        /// <summary>
        /// 返回码 0:成功 其他:失败
        /// </summary>
        public int ret { get; set; }
        /// <summary>
        /// 如果ret<0,会有相应的错误信息提示,返回数据全部用UTF-8编码。
        /// </summary>
        public string msg { get; set; }
        /// <summary>
        /// 用户在QQ空间的昵称。
        /// </summary>
        public string nickname { get; set; }
        /// <summary>
        /// 大小为30×30像素的QQ空间头像URL。
        /// </summary>
        public string figureurl { get; set; }
        /// <summary>
        /// 大小为50×50像素的QQ空间头像URL。
        /// </summary>
        public string figureurl_1 { get; set; }
        /// <summary>
        /// 大小为100×100像素的QQ空间头像URL。
        /// </summary>
        public string figureurl_2 { get; set; }
        /// <summary>
        /// 大小为40×40像素的QQ头像URL。
        /// </summary>
        public string figureurl_qq_1 { get; set; }
        /// <summary>
        /// 大小为100×100像素的QQ头像URL。
        /// 需要注意,不是所有的用户都拥有QQ的100x100的头像,但40x40像素则是一定会有。
        /// </summary>
        public string figureurl_qq_2 { get; set; }
        /// <summary>
        /// 性别。 如果获取不到则默认返回"男"
        /// </summary>
        public string gender { get; set; }
        public string is_yellow_vip { get; set; }
        public string vip { get; set; }
        public string yellow_vip_level { get; set; }
        public string level { get; set; }
        public string is_yellow_year_vip { get; set; }
        /// <summary>
        /// QQ用户唯一标识。
        /// </summary>
        public string OpenID { get; set; }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSys.Models.QQLogin
{
    public class QQApiAccessToken
    {
        /// <summary>
        /// 授权令牌,Access_Token。
        /// </summary>
        public string access_token { get; set; }
        /// <summary>
        /// 该access token的有效期,单位为秒。
        /// </summary>
        public string expires_in { get; set; }
        /// <summary>
        /// 在授权自动续期步骤中,获取新的Access_Token时需要提供的参数。
        /// 注:refresh_token仅一次有效
        /// </summary>
        public string refresh_token { get; set; }
    }
}

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace BlogSys.Models.QQLogin
{
    public class QQOpenIDInfo
    {
        public string client_id { get; set; }
        public string openid { get; set; }
    }
}

 以下代码为asp.net core 中注入HttpClient 的部分。

public void ConfigureServices(IServiceCollection services)
{
	services.AddHttpClient<QQLoginService>(httpClient =>
	{
		httpClient.BaseAddress = new Uri("https://graph.qq.com");
	});
   
}

 

好了,以上就是我今天要和小伙伴们分享的内容,如果你在对接QQ登录过程中遇到了一些困惑,那么请登录我的  个人博客 并在我的这篇文章中留言,因为我的个人博客收到用户留言,会立刻通知我这边,以便我快速帮你们解答。

版权声明:本文版权归作者所有,遵循 CC 4.0 BY-SA 许可协议, 转载请注明原文链接
https://www.cnblogs.com/chenxinblogs/p/15249278.html

Spring Security OAuth2.0认证授权一:框架搭建和认证测试-编程思维

一、OAuth2.0介绍 OAuth(开放授权)是一个开放标准,允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息,而不 需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。 1.stackoverflow和github 听起来挺拗口,不如举个例子说明下,就以stackoverflow登录为例:我们登

oauth 的权限问题与信息隐忧_duanxz-编程思维

核心提示:以 QQ 登陆和微博登陆为代表的“一键登陆”背后不仅仅是登陆这么简单,它还默认获取了你的其他隐私资料和账号的部分使用权限,我们在享受便利的同时一定不要忘记保护好我们的个人信息安全。 去年3Q大战之后,开放几乎成为了最热的词汇,随后的国内互联网看似进入了开放平台的“蜜年”,各种基于开放平台的应用和社会化登录也随

oauth的机制原理讲解及开发流程_duanxz-编程思维

一. OAuth 2.0 协议 OAuth(Open Authorization,开放授权)是为用户资源的授权定义了一个安全、开放及简单的标准,第三方无需知道用户的账号及密码,就可获取到用户的授权信息,并且这是安全的。OAuth 2.0 是目前比较流行的做法,它率先被Google, Yahoo, Microsoft,

深入理解oauth2.0_duanxz-编程思维

1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间。是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题。豪车一般配备两种钥匙:主钥匙和泊车钥匙。当你到酒店后,只需要将泊车钥匙交给服务生,停车的事情就由服务生去处理。与主钥匙相比,这种泊车钥匙的使用功能是受限制的:它只能启动发