之前写过一篇ASP.NET MVC使用QQ登录的案例,该篇主要将的是ASP.NET Core中使用QQ第三方认证登录。由于Nuget上已经有人上传了第三方认证的包,所以我们开发起来相对较简单。
首页> 学海无涯> .NET Core> ASP.NET Core第三方认证之QQ登录
ASP.NET Core第三方认证之QQ登录
摘要 之前写过一篇ASP.NET MVC使用QQ登录的案例,该篇主要将的是ASP.NET Core中使用QQ第三方认证登录。由于Nuget上已经有人上传了第三方认证的包,所以我们开发起来相对较简单。

1.在Web项目中引用Nuget包:Microsoft.AspNetCore.Authentication.QQ  




2.添加配置信息

        在appsettings.json添加如下配置:

{
"Authentication": {
"QQ": {
"AppId": "你的AppId",
"AppKey": "你的AppKey"
}
}
}


3.配置Startup.cs

        注册认证服务:在ConfigureServices方法添加以下代码

//注册认证服务
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
//这里填写一些配置信息,默认即可
}) //添加Cookie认证
.AddQQ(qqOptions =>
{
qqOptions.AppId = Configuration["Authentication:QQ:AppId"]; //QQ互联申请的AppId
qqOptions.AppKey = Configuration["Authentication:QQ:AppKey"]; //QQ互联申请的AppKey
qqOptions.CallbackPath = "/user/callback"; //QQ互联回调地址
//自定义认证声明
qqOptions.ClaimActions.MapJsonKey(MyClaimTypes.QQOpenId, "openid");
qqOptions.ClaimActions.MapJsonKey(MyClaimTypes.QQName, "nickname");
qqOptions.ClaimActions.MapJsonKey(MyClaimTypes.QQFigure, "figureurl_qq_1");
qqOptions.ClaimActions.MapJsonKey(MyClaimTypes.QQGender, "gender");
});

 使用认证中间件:在Configure方法添加以下代码 

//使用验证中间件
app.UseAuthentication();

4.登录处理

        在UserController中需要写两个Action,一个用来触发QQ登录,一个用来处理登录成功后的逻辑。例如:

public IActionResult Login(string provider = "QQ", string returnUrl = null)
{
//第三方登录成功后跳转的地址
var redirectUrl = Url.Action(nameof(ExternalLoginCallbackAsync), new { returnUrl });
var properties = new AuthenticationProperties()
{
RedirectUri = redirectUrl
};
return Challenge(properties, provider);
}
[Authorize]
public async Task ExternalLoginCallbackAsync(string returnUrl = null)
{
//QQ认证后会默认登录,如果你想自定义登录,可以先注销第三方登录的身份
//await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
string openId = "", name = "", figure = "", gender = "";
//从当前登录用户的身份声明中获取信息(是否有些眼熟,MyClaimTypes就是在Startup里面自定义的那些)
foreach (var item in HttpContext.User.Claims)
{
switch (item.Type)
{
case MyClaimTypes.QQOpenId:
openId = item.Value;
break;
case MyClaimTypes.QQName:
name = item.Value;
break;
case MyClaimTypes.QQFigure:
figure = item.Value;
break;
case MyClaimTypes.QQGender:
gender = item.Value;
break;
default:
break;
}
}
//获取到OpenId后进行登录或者注册(以下作为示范,不要盲目复制粘贴)
if (!openId.IsNullOrEmpty())
{
//去数据库查询该QQ是否绑定用户
User user = await _dbContext.User.Where(s => s.QQOpenId == openId).FirstOrDefaultAsync();
if (user != null)
{
#region 存在则登陆
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Sid, user.Id.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Name, user.Name));
identity.AddClaim(new Claim(MyClaimTypes.Avator, user.Avatar));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.Now.Add(TimeSpan.FromDays(int.Parse(Configuration["AppSettings:LoginExpires"]))) // 有效时间
});
user.LastLoginIP = HttpContext.GetUserIP();
user.LastLoginTime = DateTime.Now;
//更新登录信息
_dbContext.User.Update(user);
await _dbContext.SaveChangesAsync();
#endregion
if (returnUrl != null)
return Redirect(returnUrl);
else
return RedirectToAction("index", "home");
}
else
{
User userModel = new User();
userModel.QQOpenId = openId;
userModel.Name = name;
userModel.Avatar = figure;
userModel.Gender = gender;
userModel.CreateTime = DateTime.Now;
//注册
await _dbContext.User.AddAsync(userModel);
if (await _dbContext.SaveChangesAsync() > 0)
{
#region 注册后自动登陆
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Sid, userModel.Id.ToString()));
identity.AddClaim(new Claim(ClaimTypes.Name, userModel.Name));
identity.AddClaim(new Claim(MyClaimTypes.Avator, userModel.Avatar));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity), new AuthenticationProperties
{
IsPersistent = true,
ExpiresUtc = DateTimeOffset.Now.Add(TimeSpan.FromDays(int.Parse(Configuration["AppSettings:LoginExpires"]))) // 有效时间
});
userModel.LastLoginIP = HttpContext.GetUserIP();
userModel.LastLoginTime = DateTime.Now;
//更新登录信息
_dbContext.User.Update(userModel);
await _dbContext.SaveChangesAsync();
#endregion
if (returnUrl != null)
return Redirect(returnUrl);
else
return RedirectToAction("index", "home");
}
else
throw new Exception("Add User failed");
}
}
else
throw new Exception("OpenId is null");
}

4.开始使用

        在页面上放置触发QQ登录的按钮,如:

<a href="/user/login?provider=QQ&returnUrl=@returnUrl" >
<i class="fa fa-qq"></i>
</a>

  provider=QQ是必须的,returnUrl一般写当前页面,这样登录成功后就可以跳转回当前页面。


5.结语

        该案例使用的是微软的认证组件,上文提到的provider需要注意,QQ登录必须写QQ。

        微软自身提供了Microsoft账号、Google账号等国外账号的认证组件,用法应该和上述类似,有兴趣的去Github下载asp.net源码看看呗。

        此外Microsoft.AspNetCore.Authentication.QQ这个包在Github上也有源码,大家可以看看别人是怎么实现的,也能够知晓provider必须写QQ的原因,顺便自己封装个微博、微信登录也是可以的。

版权声明:本文由Contione原创出品,转载请注明出处!

本文链接:https://contione.cn/article/detail/8

本文配乐
来说两句吧
最新评论
  • 不想知道!
    不想知道!
    后续分享下redis集群的搭建

  • 不想知道!
    不想知道!

    本篇主要介绍为什么要用缓存,缓存有什么意义?常用的缓存中间件、优缺点。