Skip to content

Commit

Permalink
feat: 重构 QQ 登陆组件,新增 OSChina 登录组件
Browse files Browse the repository at this point in the history
  • Loading branch information
mrhuo committed Jan 10, 2021
1 parent 197890d commit babf662
Show file tree
Hide file tree
Showing 14 changed files with 184 additions and 68 deletions.
40 changes: 39 additions & 1 deletion MrHuo.OAuth.NetCoreApp/Controllers/OAuthController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
using System.Text.Encodings.Web;
using System.Text.Unicode;
using MrHuo.OAuth.Alipay;
using MrHuo.OAuth.QQ;
using MrHuo.OAuth.OSChina;

namespace MrHuo.OAuth.NetCoreApp.Controllers
{
Expand All @@ -31,7 +33,9 @@ public IActionResult Index(
[FromServices] HuaweiOAuth huaweiOAuth,
[FromServices] CodingOAuth codingOAuth,
[FromServices] SinaWeiboOAuth sinaWeiboOAuth,
[FromServices] AlipayOAuth alipayOAuth
[FromServices] AlipayOAuth alipayOAuth,
[FromServices] QQOAuth qqOAuth,
[FromServices] OSChinaOAuth oschinaOAuth
)
{
var redirectUrl = "";
Expand Down Expand Up @@ -82,6 +86,16 @@ [FromServices] AlipayOAuth alipayOAuth
redirectUrl = alipayOAuth.GetAuthorizeUrl();
break;
}
case "qq":
{
redirectUrl = qqOAuth.GetAuthorizeUrl();
break;
}
case "oschina":
{
redirectUrl = oschinaOAuth.GetAuthorizeUrl();
break;
}
default:
return ReturnToError($"没有实现【{type}】登录方式!");
}
Expand All @@ -100,6 +114,8 @@ public async Task<IActionResult> LoginCallback(
[FromServices] CodingOAuth codingOAuth,
[FromServices] SinaWeiboOAuth sinaWeiboOAuth,
[FromServices] AlipayOAuth alipayOAuth,
[FromServices] QQOAuth qqOAuth,
[FromServices] OSChinaOAuth oschinaOAuth,
[FromQuery] string code,
[FromQuery] string state,
[FromQuery] string error_description = "")
Expand Down Expand Up @@ -214,6 +230,28 @@ public async Task<IActionResult> LoginCallback(
HttpContext.Session.Set("OAuthUserDetail", authorizeResult.UserInfo, true);
break;
}
case "qq":
{
var authorizeResult = await qqOAuth.AuthorizeCallback(code, state);
if (!authorizeResult.IsSccess)
{
throw new Exception(authorizeResult.ErrorMessage);
}
HttpContext.Session.Set("OAuthUser", authorizeResult.UserInfo.ToUserInfoBase());
HttpContext.Session.Set("OAuthUserDetail", authorizeResult.UserInfo, true);
break;
}
case "oschina":
{
var authorizeResult = await oschinaOAuth.AuthorizeCallback(code, state);
if (!authorizeResult.IsSccess)
{
throw new Exception(authorizeResult.ErrorMessage);
}
HttpContext.Session.Set("OAuthUser", authorizeResult.UserInfo.ToUserInfoBase());
HttpContext.Session.Set("OAuthUserDetail", authorizeResult.UserInfo, true);
break;
}
default:
throw new Exception($"没有实现【{type}】登录回调!");
}
Expand Down
2 changes: 2 additions & 0 deletions MrHuo.OAuth.NetCoreApp/MrHuo.OAuth.NetCoreApp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<ProjectReference Include="..\MrHuo.OAuth.Github\MrHuo.OAuth.Github.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.Gitlab\MrHuo.OAuth.Gitlab.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.Huawei\MrHuo.OAuth.Huawei.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.OSChina\MrHuo.OAuth.OSChina.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.QQ\MrHuo.OAuth.QQ.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.SinaWeibo\MrHuo.OAuth.SinaWeibo.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.Wechat\MrHuo.OAuth.Wechat.csproj" />
</ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions MrHuo.OAuth.NetCoreApp/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public void ConfigureServices(IServiceCollection services)
Configuration["oauth:alipay:public_key"],
Configuration["oauth:alipay:encrypt_key"]
));
services.AddSingleton(new QQ.QQOAuth(OAuthConfig.LoadFrom(Configuration, "oauth:qq")));
services.AddSingleton(new OSChina.OSChinaOAuth(OAuthConfig.LoadFrom(Configuration, "oauth:oschina")));
}

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
Expand Down
4 changes: 3 additions & 1 deletion MrHuo.OAuth.NetCoreApp/Views/Home/Index.cshtml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
("Huawei", true, null),
("Coding", true, null),
("SinaWeibo", true, null),
("Alipay", false, null),
("Alipay", true, null),
("QQ", false, null),
("OSChina", true, null),
};
}

Expand Down
11 changes: 11 additions & 0 deletions MrHuo.OAuth.OSChina/MrHuo.OAuth.OSChina.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\MrHuo.OAuth.Core\MrHuo.OAuth.Core.csproj" />
</ItemGroup>

</Project>
20 changes: 20 additions & 0 deletions MrHuo.OAuth.OSChina/OSChinaOAuth.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace MrHuo.OAuth.OSChina
{
/// <summary>
/// https://www.oschina.net/openapi
/// </summary>
public class OSChinaOAuth : OAuthLoginBase<OSChinaUserInfoModel>
{
public OSChinaOAuth(OAuthConfig oauthConfig) : base(oauthConfig)
{
}

protected override string AuthorizeUrl => "https://www.oschina.net/action/oauth2/authorize";
protected override string AccessTokenUrl => "https://www.oschina.net/action/openapi/token";
protected override string UserInfoUrl => "https://www.oschina.net/action/openapi/user";
}
}
29 changes: 29 additions & 0 deletions MrHuo.OAuth.OSChina/OSChinaUserInfoModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Text.Json.Serialization;

namespace MrHuo.OAuth.OSChina
{
public class OSChinaUserInfoModel : IUserInfoModel
{
[JsonPropertyName("id")]
public int Id { get; set; }

[JsonPropertyName("email")]
public string Email { get; set; }

[JsonPropertyName("name")]
public string Name { get; set; }

[JsonPropertyName("gender")]
public string Gender { get; set; }

[JsonPropertyName("avatar")]
public string Avatar { get; set; }

[JsonPropertyName("location")]
public string Location { get; set; }

[JsonPropertyName("error_description")]
public string ErrorMessage { get; set; }
}
}
8 changes: 1 addition & 7 deletions MrHuo.OAuth.QQ/MrHuo.OAuth.QQ.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="5.0.0" />
<PackageReference Include="System.Text.Json" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\MrHuo.OAuth\MrHuo.OAuth.csproj" />
<ProjectReference Include="..\MrHuo.OAuth.Core\MrHuo.OAuth.Core.csproj" />
</ItemGroup>

</Project>
13 changes: 0 additions & 13 deletions MrHuo.OAuth.QQ/QQAccessTokenModel.cs

This file was deleted.

75 changes: 35 additions & 40 deletions MrHuo.OAuth.QQ/QQOAuth.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Text.Json;
using System.Web;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;

namespace MrHuo.OAuth.QQ
{
Expand All @@ -10,65 +10,60 @@ namespace MrHuo.OAuth.QQ
/// <para>https://wiki.open.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91%E4%BD%BF%E7%94%A8Authorization_Code%E8%8E%B7%E5%8F%96Access_Token_1</para>
/// <para>https://wiki.open.qq.com/wiki/%E3%80%90QQ%E7%99%BB%E5%BD%95%E3%80%91API%E6%96%87%E6%A1%A3</para>
/// </summary>
public class QQOAuth : OAuthApiBase<QQAccessTokenModel, QQUserInfoModel>
public class QQOAuth : OAuthLoginBase<QQUserInfoModel>
{
private const string AUTHORIZE_URI = "https://graph.qq.com/oauth2.0/authorize";
private const string ACCESS_TOKEN_URI = "https://graph.qq.com/oauth2.0/token";
private const string OPENID_URI = "https://graph.qq.com/oauth2.0/me";
private const string USERINFO_URI = "https://graph.qq.com/user/get_user_info";
private readonly string AppId;
private readonly string AppKey;
private readonly string RedirectUri;
private readonly string Scope;
protected override string AuthorizeUrl => "https://graph.qq.com/oauth2.0/authorize";
protected override string AccessTokenUrl => "https://graph.qq.com/oauth2.0/token";
protected override string UserInfoUrl => "https://graph.qq.com/user/get_user_info";

public QQOAuth(IConfiguration configuration, IHttpContextAccessor httpContextAccessor)
: base(configuration, httpContextAccessor)
public QQOAuth(OAuthConfig oauthConfig) : base(oauthConfig)
{
AppId = _configuration["oauth:qq:app_id"];
AppKey = _configuration["oauth:qq:app_key"];
RedirectUri = HttpUtility.UrlEncode(_configuration["oauth:qq:redirect_uri"]);
Scope = _configuration["oauth:qq:scope"];
}

public override string GetAuthorizeUrl(string state)
{
return $"{AUTHORIZE_URI}?response_type=code&client_id={AppId}&redirect_uri={RedirectUri}&scope={Scope}&state={state}";
}

public override string GetAccessTokenUrl(string code, string state)
{
return $"{ACCESS_TOKEN_URI}?grant_type=authorization_code&client_id={AppId}&client_secret={AppKey}&code={code}&redirect_uri={RedirectUri}&state={state}";
}

public override string GetUserInfoUrl(QQAccessTokenModel accessToken)
{
return $"{USERINFO_URI}?access_token={accessToken.AccessToken}&oauth_consumer_key={AppId}&openid={GetOpenId(accessToken.AccessToken)}";
}

/// <summary>
/// 如果成功返回,即可在返回包中获取到Access Token。
/// 如果成功返回,即可在返回包中获取到 Access Token。
/// 返回如下字符串:access_token=FE04************************CCE2&expires_in=7776000 。
/// </summary>
/// <param name="accessTokenResponse"></param>
/// <param name="authorizeCallbackParams"></param>
/// <returns></returns>
protected override QQAccessTokenModel ResolveAccessTokenFromString(string accessTokenResponse)
public override async Task<DefaultAccessTokenModel> GetAccessTokenAsync(Dictionary<string, string> authorizeCallbackParams)
{
var arr = accessTokenResponse.Split('&');
return new QQAccessTokenModel()
var accessTokenModelReponseText = await HttpRequestApi.PostStringAsync(
AccessTokenUrl,
BuildGetAccessTokenParams(authorizeCallbackParams)
);
if (string.IsNullOrEmpty(accessTokenModelReponseText))
{
throw new Exception("没有获取到正确的 AccessToken!");
}
var arr = accessTokenModelReponseText.Split('&');
return new DefaultAccessTokenModel()
{
AccessToken = arr[0],
ExpiresIn = int.Parse(arr[1])
};
}

protected override Dictionary<string, string> BuildGetUserInfoParams(DefaultAccessTokenModel accessTokenModel)
{
var openId = GetOpenId(accessTokenModel.AccessToken).ConfigureAwait(false).GetAwaiter().GetResult();
return new Dictionary<string, string>()
{
["access_token"] = accessTokenModel.AccessToken,
["oauth_consumer_key"] = oauthConfig.AppId,
["openid"] = openId,
};
}

/// <summary>
/// 获取用户 openId
/// </summary>
/// <param name="accessToken"></param>
/// <returns></returns>
public string GetOpenId(string accessToken)
public async Task<string> GetOpenId(string accessToken)
{
var response = API.Get($"{OPENID_URI}?access_token={accessToken}");
var response = await HttpRequestApi.GetStringAsync($"{OPENID_URI}?access_token={accessToken}");
return JsonSerializer.Deserialize<QQOpenIdModel>(ClearCallbackResponse(response)).OpenId;
}

Expand Down
3 changes: 0 additions & 3 deletions MrHuo.OAuth.QQ/QQOpenIdModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,5 @@ public class QQOpenIdModel
{
[JsonPropertyName("openid")]
public string OpenId { get; set; }

//[JsonPropertyName("client_id")]
//public string AppId { get; set; }
}
}
1 change: 1 addition & 0 deletions MrHuo.OAuth.QQ/QQUserInfoModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,6 @@ public class QQUserInfoModel : IUserInfoModel
/// </summary>
[JsonPropertyName("is_yellow_year_vip")]
public string IsYellowYearVip { get; set; }
public string ErrorMessage { get; set; }
}
}
11 changes: 9 additions & 2 deletions MrHuo.OAuth.sln
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MrHuo.OAuth.Gitlab", "MrHuo
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MrHuo.OAuth.Core", "MrHuo.OAuth.Core\MrHuo.OAuth.Core.csproj", "{897E1826-9E4D-41EE-B45E-04CA1C718560}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MrHuo.OAuth.Coding", "MrHuo.OAuth.Coding\MrHuo.OAuth.Coding.csproj", "{F6EC7E26-9D89-4C8E-9371-4EDBEB9C3BF8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MrHuo.OAuth.Coding", "MrHuo.OAuth.Coding\MrHuo.OAuth.Coding.csproj", "{F6EC7E26-9D89-4C8E-9371-4EDBEB9C3BF8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MrHuo.OAuth.SinaWeibo", "MrHuo.OAuth.SinaWeibo\MrHuo.OAuth.SinaWeibo.csproj", "{29AC55FA-2FD3-44A1-8A2F-B3716ECB0FA1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MrHuo.OAuth.SinaWeibo", "MrHuo.OAuth.SinaWeibo\MrHuo.OAuth.SinaWeibo.csproj", "{29AC55FA-2FD3-44A1-8A2F-B3716ECB0FA1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MrHuo.OAuth.OSChina", "MrHuo.OAuth.OSChina\MrHuo.OAuth.OSChina.csproj", "{3763AAFC-E922-453E-B68D-39F3CFD006EB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand Down Expand Up @@ -92,6 +94,10 @@ Global
{29AC55FA-2FD3-44A1-8A2F-B3716ECB0FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29AC55FA-2FD3-44A1-8A2F-B3716ECB0FA1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29AC55FA-2FD3-44A1-8A2F-B3716ECB0FA1}.Release|Any CPU.Build.0 = Release|Any CPU
{3763AAFC-E922-453E-B68D-39F3CFD006EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3763AAFC-E922-453E-B68D-39F3CFD006EB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3763AAFC-E922-453E-B68D-39F3CFD006EB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3763AAFC-E922-453E-B68D-39F3CFD006EB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -109,6 +115,7 @@ Global
{897E1826-9E4D-41EE-B45E-04CA1C718560} = {2421B9DA-FA42-4412-8ED6-452B745294A5}
{F6EC7E26-9D89-4C8E-9371-4EDBEB9C3BF8} = {2421B9DA-FA42-4412-8ED6-452B745294A5}
{29AC55FA-2FD3-44A1-8A2F-B3716ECB0FA1} = {2421B9DA-FA42-4412-8ED6-452B745294A5}
{3763AAFC-E922-453E-B68D-39F3CFD006EB} = {2421B9DA-FA42-4412-8ED6-452B745294A5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {24DE1505-2557-43FC-BF2C-9AAB19B51971}
Expand Down
Loading

0 comments on commit babf662

Please sign in to comment.