本篇主要介绍为什么要用缓存,缓存有什么意义?常用的缓存中间件、优缺点。
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原创出品,转载请注明出处!
04/15/2020 00:40:05回复