1.登陆的实现
登陆功能实现起来有哪些经常使用的方式,你们首先想到的确定是cookie或session或cookie+session,固然还有其余模式,今天主要探讨一下在Asp.net core 2.0下实现以cookie登陆受权,与net freamwork框架下经常使用的开发方式有所不一样的是之前开发不论是webform仍是mvc模式,大多数开发者会封装成第三方操做类,方便项目全局调用;在net core 2.0 下的登陆方式发生了点变化,大概流程是先经过依赖注入相关配置,再经过Action登陆受权,而后Authentication相关属性认证,具体怎么实现让咱们一块儿一步步操做一下。
2.Cookie开发回顾
进行net core 2.0 cookie编程前,首先回顾一下原来作asp.net项目开发经常使用的操做cookie封装的一些封装。封装好的cookiehelper类库,能够很方便的在项目中调用,如写入cookie的时候直接调用CookieHelper.WriteCookie(名称,值)这样key/value形式写入cookie,读取cookie的时候直接使用CookieHelper.GetCookie(名称)就能够获取到cookie值。
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Net;
using System.Configuration;
using System.Web;
using System.Security.Cryptography;
namespace ZZ.Common
{
public class CookieHelper
{
/// <summary>
/// 写cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <param name="strValue">值</param>
public static void WriteCookie(string strName, string strValue)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
if (cookie == null)
{
cookie = new HttpCookie(strName);
}
cookie.Value = UrlEncode(strValue);
HttpContext.Current.Response.AppendCookie(cookie);
}
/// <summary>
/// 写cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <param name="strValue">值</param>
public static void WriteCookie(string strName, string key, string strValue)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
if (cookie == null)
{
cookie = new HttpCookie(strName);
}
cookie[key] = UrlEncode(strValue);
HttpContext.Current.Response.AppendCookie(cookie);
}
/// <summary>
/// 写cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <param name="strValue">值</param>
public static void WriteCookie(string strName, string key, string strValue, int expires)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
if (cookie == null)
{
cookie = new HttpCookie(strName);
}
cookie[key] = UrlEncode(strValue);
cookie.Expires = DateTime.Now.AddMinutes(expires);
HttpContext.Current.Response.AppendCookie(cookie);
}
/// <summary>
/// 写cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <param name="strValue">值</param>
/// <param name="strValue">过时时间(分钟)</param>
public static void WriteCookie(string strName, string strValue, int expires)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[strName];
if (cookie == null)
{
cookie = new HttpCookie(strName);
}
cookie.Value = UrlEncode(strValue);
cookie.Expires = DateTime.Now.AddMinutes(expires);
HttpContext.Current.Response.AppendCookie(cookie);
}
/// <summary>
/// 读cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <returns>cookie值</returns>
public static string GetCookie(string strName)
{
if (HttpContext.Current.Request.Cookies != null && HttpContext.Current.Request.Cookies[strName] != null)
return UrlDecode(HttpContext.Current.Request.Cookies[strName].Value.ToString());
return "";
}
/// <summary>
/// 读cookie值
/// </summary>
/// <param name="strName">名称</param>
/// <returns>cookie值</returns>
public static string GetCookie(string strName, string key)
{
if (HttpContext.Current.Request.Cookies != null && HttpContext.Current.Request.Cookies[strName] != null && HttpContext.Current.Request.Cookies[strName][key] != null)
return UrlDecode(HttpContext.Current.Request.Cookies[strName][key].ToString());
return "";
}
}
}
CookieHelper
3.NET Core2.0 下Cookie的使用
3.1添加Nuget相关依赖


我这里使用 Microsoft.AspNetCore.All大而全的,逐项引用这里不作过多探讨,适合本身的就是最好的。
参照搜狐网上看到的一段话:
Microsoft.AspNetCore.All包,它是一个元数据包,包含了大量的东西,其中包括:Authorization, Authentication, Identity, CORS, Localization, Logging, Razor, Kestrel 等,除了这些它还附加了 EntityFramework, SqlServer, Sqlite 等包。有些同窗可能会以为这样会引用了不少项目中使用不到的程序集,致使发布后的程序变得很庞大,不过我要告诉你没必要担忧,发布后的程序集不但不会变得很大,反而会小不少,由于 Microsoft 把全部的这些依赖所有都集成到了sdk中,也就是说当你安装sdk的以后,MVC相关的包就已经安装到了你的系统上。
3.2配置
3.2.1首先在Startup.cs中ConfigureServices添加Cookie中间件,使用自定义Scheme
//Cookie(1)添加 Cookie 服务
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
//后台管理员cookie服务
.AddCookie(AdminAuthorizeAttribute.AdminAuthenticationScheme, options =>
{
options.LoginPath = "/admin/Login/Index";//登陆路径
options.LogoutPath = "/admin/Login/LogOff";//退出路径
options.AccessDeniedPath = new PathString("/Error/Forbidden");//拒绝访问页面
options.Cookie.Path = "/";
})
//前台用户cookie服务
.AddCookie(UserAuthorizeAttribute.UserAuthenticationScheme, options =>
{
options.LoginPath = "/Login/Index";
options.LogoutPath = "/Login/LogOff";
options.AccessDeniedPath = new PathString("/Error/Forbidden");//拒绝访问页面
options.Cookie.Path = "/";
});
在ConfigureServices方法中添加受权支持,并添加使用Cookie的方式,配置登陆页面、登出页面和没有权限时的跳转页面。AdminAuthorizeAttribute、UserAuthorizeAttribute为自定义AuthorizeAttribute类,两个登陆方案,同时类中实现虚方法OnAuthorization过滤,若是系统中只有一个登陆受权所有使用默认便可。
//Cookie(1)添加 Cookie 服务
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) //后台管理员cookie服务
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.LoginPath = "/admin/Login/Index";//登陆路径
options.LogoutPath = "/admin/Login/LogOff";//退出路径
options.AccessDeniedPath = new PathString("/Error/Forbidden");//拒绝访问页面
options.Cookie.Path = "/";
});

3.2.2在Configure使用Cookie中间件
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//Cookie(2)使用Cookie的中间件
app.UseAuthentication();
}
3.3[自定义AuthorizeAttribute]特性
添加一个登陆方案(Scheme)
CookieAuthenticationDefaults.AuthenticationScheme,这是系统已经定义好的一个默认的登陆方案,添加一个新的来实现一个不一样的身份登陆。代码以下:
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Abstractions;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NC.MVC
{
/// <summary>
/// 跳过检查属性
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class SkipUserAuthorizeAttribute : Attribute, IFilterMetadata
{
}
/// <summary>
/// 前台登陆验证
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class UserAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public const string UserAuthenticationScheme = "UserAuthenticationScheme";//自定义一个默认的登陆方案
public UserAuthorizeAttribute()
{
this.AuthenticationSchemes = UserAuthenticationScheme;
}
public virtual void OnAuthorization(AuthorizationFilterContext filterContext)
{
//获取对应Scheme方案的登陆用户呢?使用HttpContext.AuthenticateAsync
var authenticate = filterContext.HttpContext.AuthenticateAsync(UserAuthorizeAttribute.UserAuthenticationScheme);
//authenticate.Wait();
if (authenticate.Result.Succeeded || this.SkipUserAuthorize(filterContext.ActionDescriptor))
{
return;
}
//若是是默认Scheme可使用
//if (filterContext.HttpContext.User.Identity.IsAuthenticated || this.SkipUserAuthorize(filterContext.ActionDescriptor))
//{
// return;
//}
HttpRequest httpRequest = filterContext.HttpContext.Request;
string url = filterContext.HttpContext.Content("~/login");
url = string.Concat(url, "?returnUrl=", httpRequest.Path);
RedirectResult redirectResult = new RedirectResult(url);
filterContext.Result = redirectResult;
return;
}
protected virtual bool SkipUserAuthorize(ActionDescriptor actionDescriptor)
{
bool skipAuthorize = actionDescriptor.FilterDescriptors.Where(a => a.Filter is SkipUserAuthorizeAttribute).Any();
if (skipAuthorize)
{
return true;
}
return false;
}
}
}
这里有一个点须要注意登陆多个用户,filterContext.HttpContext.User.Identity这里会默认AddAuthentication(Scheme)中的Scheme, 网上看到“若是你的Controller或者Action上有使用AuthorizeAttribute,那这个Attribute使用的登陆方案是哪一个,则这个HttpContext.User对应的就是那个方案的登陆用户。若是没有使用,则AddAuthentication()方法默认指它的方案(Scheme)所登陆的用户,就是这个HttpContext.User”这里跟我实际测试的有所不一样,你们能够多测试一下。
因此获取对应方案的登陆用户,这里用的是
var authenticate = filterContext.HttpContext.AuthenticateAsync(UserAuthorizeAttribute.UserAuthenticationScheme);
if (authenticate.Result.Succeeded){return;}
若是您有更好的方案请留言告知!
3.4登陆受权实现
配置文件中处理完成以后,接下来就是在登陆Action中实现登陆。添加一个Controller,如LoginController,再添加一个Action,如 Login,所配置的路由,要与上面的配置对应,否则跳转登陆时会跳错页面。
下面展现前台会员登陆类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
namespace NC.MVC.Controllers
{
public class LoginController : Controller
{
public IActionResult Index()
{
return View();
}
/// <summary>
/// 用户登陆
/// </summary>
/// <param name="userName">用户ID</param>
/// <param name="passWord">用户密码</param>
/// <param name="rememberMe">是否记住密码</param>
/// <returns></returns>
[HttpPost]
public IActionResult Login(string userName, string passWord, string rememberMe, string txtCode)
{
var user = new ClaimsPrincipal(
new ClaimsIdentity(new[]
{
new Claim("UserName","UserNameValue"),
new Claim("UserPwd","UserPwdValue"),
}, UserAuthorizeAttribute.UserAuthenticationScheme)
);
HttpContext.SignInAsync(UserAuthorizeAttribute.UserAuthenticationScheme, user, new AuthenticationProperties
{
ExpiresUtc = DateTime.UtcNow.AddMinutes(60),// 有效时间
//ExpiresUtc = DateTimeOffset.Now.Add(TimeSpan.FromDays(7)), // 有效时间
IsPersistent = true,
AllowRefresh = false
});
return new RedirectResult("~/Home/Index");//登陆成功
}
}
}
这里要注意的是HttpContext.SignInAsync(AuthenticationType,…) 所设置的Scheme必定要与前面的配置同样,这样对应的登陆受权才会生效。
3.5认证验证
登陆完成后,进入须要受权才能进入的管理页面,在作限制的Controller上加上[自定义AuthorizeAttribute]特性来作限制。这里咱们自定义了两个AuthorizeAttribute;UserAuthorizeAttribute和AdminAuthorizeAttribute,结合3.3的实现,咱们使用UserAuthorizeAttribute在Contoller或Action上加特性。这里咱们先在HomeController上加上[UserAuthorize]
using Microsoft.AspNetCore.Mvc;
using System.Data;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authorization;
namespace NC.MVC.Controllers
{
[UserAuthorize]
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
}
}
3.6退出登陆
若是是多用户登陆的系统,退出的时候须要指定方案退出。
public async Task Logout(string returnurl)
{
await HttpContext.SignOutAsync(UserAuthorizeAttribute.UserAuthenticationScheme);
return Redirect(returnurl ?? "~/");
}
4.总结
以上就是我对net core 2.0 cookie受权登陆实际编程测试遇到的坑点以及编程过程当中用到的部分代码,后端管理员登陆相关代码以及AdminAuthorizeAttribute和前端会员UserAuthorizeAttribute代码基本一致,这里限于时间及篇幅不作过多处理,本身动手是学习技术最快的方式,没有之一。
在进行netcore2.0编程或者学习的时候,必定要抛却固有的一些编程形式、思惟。新的事物总会对旧有规则,旧有思惟产生必定的冲击,必定要学会适应,提醒你们同时警醒本身。Net core 开源跨平台总的来讲是属因而良性的变化,变得更方便,更容易扩展,NET阵营须要咱们你们共同去努力。
感谢ace chloe core开源、zkea cms core开源,在学习Asp.Net Core 2.0开发的时候网上资料相对较少,找了不少资料,有不少大牛的文章代码对我帮助很大,写博的时候不少创意、文章忘记出处,之后会留意。整理此篇备忘,但愿对你有些许帮助。