QQ 掃碼登錄的實現(無需註冊開發者)
效果展示:
核心實現
展示二維碼
public static (Stream, string) GetLoginQrCode()
{
var uri = new Uri(QrCodeUrl);
var request = new HttpRequestMessage(HttpMethod.Get, uri);
var cookieContainer = new CookieContainer();
var handler = new HttpClientHandler
{
CookieContainer = cookieContainer,
AllowAutoRedirect = true,
UseCookies = true
};
using var client = new HttpClient(handler);
var response = client.Send(request);
var stream = response.Content.ReadAsStreamAsync().Result;
var cookies = cookieContainer.GetCookies(uri).ToList();
var qrsig = cookies.FirstOrDefault(x => x.Name == "qrsig")?.Value;
return (stream, qrsig);
}
解析掃碼結果
public static (bool, string, ScanResult) GetQqScanResult(string qrsig)
{
var timeStamp = GetTimeStamp();
var ptqrToken = ParsePtqrToken(qrsig);
var uri = new Uri(string.Format(ScanResultUrl, ptqrToken, timeStamp));
var request = new HttpRequestMessage(HttpMethod.Get, uri);
var cookieContainer = new CookieContainer();
cookieContainer.Add(new Cookie("qrsig", qrsig) { Domain = uri.Host });
var handler = new HttpClientHandler
{
CookieContainer = cookieContainer,
AllowAutoRedirect = true,
UseCookies = true
};
using var client = new HttpClient(handler);
var response = client.Send(request);
var content = response.Content.ReadAsStringAsync().Result;
var result = ParsePtuiCbResult(content);
return result[0] == "0" ? (true, result[4], new ScanResult(ParseQqNumber(result[2]), result[5])) : (false, result[4], null);
}
登錄視圖
<h1>QQ Scan Login</h1>
<img src="@Url.Action("QrCode")" width="350" alt="二維碼失效?點擊刷新" onclick="javascript:this.src += '?_t='+ Math.random();" style="cursor: pointer;" />
<h1>QQ Scan Result</h1>
<textarea rows="3" cols="45" id="result"></textarea>
<form asp-action="Login" method="post" id="loginForm">
<input type="hidden" name="nick" id="nickName" />
<input type="hidden" name="number" id="qqNumber" />
</form>
登錄授權
配置Cookie認證策略
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
// options.Cookie.HttpOnly = true;
// options.ExpireTimeSpan = TimeSpan.FromHours(2);
// options.SlidingExpiration = true;
options.LoginPath = "/Account/Login";
options.AccessDeniedPath = "/Account/Login";
});
不要忘記使用策略: app.UseAuthentication();
創建用戶登錄標識
if (ModelState.IsValid)
{
// 創建用戶登錄標識,Cookie名稱與IServiceCollection中配置的一樣即可
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
// 添加之後,可使用User.Identity.Name獲取該值
identity.AddClaim(new Claim(ClaimTypes.Name, model.Nick));
// identity中還可以添加自定義數據
identity.AddClaim(new Claim("qq", model.Number));
// var customValue = User.Claims.SingleOrDefault(s => s.Type == "qq").Value;
await HttpContext.SignInAsync(new ClaimsPrincipal(identity));
return Redirect("~/");
}
用戶退出登錄
await HttpContext.SignOutAsync();
代碼開源
https://github.com/Run2948/QQScanLogin
如果代碼對大家有幫助,懇請大家留個 star, 感謝各位