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 "";
}
}
}

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开发的时候网上资料相对较少,找了很多资料,有很多大牛的文章代码对我帮助很大,写博的时候很多创意、文章忘记出处,以后会留意。整理此篇备忘,希望对你有些许帮助。

net core体系-web应用程序-4asp.net core2.0 项目实战(1)-12基于cookie登录授权认证并实现前台会员、后台管理员同时登录的更多相关文章

  1. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-13基于OnActionExecuting全局过滤器,页面操作权限过滤控制到按钮级

    1.权限管理 权限管理的基本定义:百度百科. 基于<Asp.Net Core 2.0 项目实战(10) 基于cookie登录授权认证并实现前台会员.后台管理员同时登录>我们做过了登录认证, ...

  2. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-3项目架构说明

    本文目录1. 摘要2. 框架介绍 3. 权限管理之多一点说明4. 总结 1.  摘要 NCMVC角色权限管理框架是由最近练习Net Core时抽时间整理的系统,后续能不能发展成一个cms还要看朋友们是 ...

  3. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-1目录

    Asp.Net Core 2.0 项目实战(1) NCMVC开源下载了 Asp.Net Core 2.0 项目实战(2)NCMVC一个基于Net Core2.0搭建的角色权限管理开发框架 Asp.Ne ...

  4. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-11项目日志解决方案

    本文目录1. Net下日志记录2. NLog的使用    2.1 添加nuget引用NLog.Web.AspNetCore    2.2 配置文件设置    2.3 依赖配置及调用    2.4 日志 ...

  5. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-2项目说明和源码下载

    本文目录1. 摘要2. Window下运行 3.linux下运行4. 开发记录5. 总结 1.概要 写<Asp.Net Core 2.0 项目实战>系列断断续续已经很长时间了,期间很多朋友 ...

  6. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-10项目各种全局帮助类

    本文目录 1.  前沿2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装3.XmlHelper快速操作xml文档4.SerializationHe ...

  7. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-9项目各种全局帮助类

    本文目录 1.  前沿2.CacheHelper基于Microsoft.Extensions.Caching.Memory封装3.XmlHelper快速操作xml文档4.SerializationHe ...

  8. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-7项目缓冲方案( Redis)

    本文目录1. 摘要2. Redis配置3. RedisHelper4.使用实例 5. 总结 1.  摘要 由于內存存取速度远高于磁盘读取的特性,为了程序效率提高性能,通常会把常用的不常变动的数据存储在 ...

  9. net core体系-web应用程序-4asp.net core2.0 项目实战(1)-8项目加密解密方案

    本文目录1. 摘要2. MD5加密封装3. AES的加密.解密4. DES加密/解密5. 总结 1.  摘要 C#中常用的一些加密和解密方案,如:md5加密.RSA加密与解密和DES加密等,Asp.N ...

  10. net core体系-web应用程序-4asp.net core2.0 项目实战(任务管理系统)-2项目搭建

    系统要求 首先建议采用 Windows 10 专业版/企业版/教育版,且必须是64位操作系统,原因是docker装起来比较方便,Win7装起来比较麻烦,且不确定是否有其他问题(自己没有实践过) 其次W ...

随机推荐

  1. kubeadm的安装步骤(HA)

    准备3台主节点:km1/km2/km3 1.编辑kubeadm-config.yaml apiVersion: kubeadm.k8s.io/v1beta1 kind: ClusterConfigur ...

  2. BZOJ4977[Lydsy1708月赛]跳伞求生——贪心+堆+模拟费用流

    题目链接: 跳伞求生 可以将题目转化成数轴上有$n$个人和$m$个房子,坐标分别为$a_{i}$和$b_{i}$,每个人可以进一个他左边的房子,每个房子只能进一个人.每个房子有一个收益$c_{i}$, ...

  3. 【CF1133E】K Balanced Teams(动态规划,单调队列)

    [CF1133E]K Balanced Teams(动态规划,单调队列) 题面 CF 让你把一堆数选一些出来分成不超过\(K\)组,每一组里面的最大值和最小值之差不超过\(5\),求最多有多少个人元素 ...

  4. 一篇文章了解云安全领域的新宠CCSK

    这是一个人人谈"云"."大数据"的时代,作为一个IT民工,如果与同行间聊天时,不谈及这方面的内容,有人可能会觉得你落伍了,跟不上这个时代了.随云计算.云存储之后 ...

  5. epoll ET(边缘触发) LT(水平触发)

    EPOLL事件有两种模型: Edge Triggered (ET) 边缘触发只有数据到来,才触发,不管缓存区中是否还有数据.Level Triggered (LT) 水平触发只要有数据都会触发. 首先 ...

  6. Python 文件行数读取的三种方法

    Python三种文件行数读取的方法: #文件比较小 count = len(open(r"d:\lines_test.txt",'rU').readlines()) print c ...

  7. JDBC事务管理

    JDBC事务管理 概念回顾: 事务:一个包含多个步骤的业务操作,如果这个业务操作被事务管理,那么这个业务操作的多个步骤要么同时失败,要么同时成功 事务操作: 开启事务 提交事务 回滚事务 使用Conn ...

  8. 11招玩转黑客攻防——用Python,更安全

    Python真是无所不能,学习Python,一个暑假就够了 !! 入门Python,从黑客入手最好玩.最简单 !! 今天就推荐一本书<11招玩转网络安全——用Python,更安全> 内网攻 ...

  9. ORACLE使用CASE WHEN的方法

    先写草稿. 说下我的需求,ORACLE数据库有两个字段RECEIVER_MOBILE与RECEIVER_PHONE,同为联系方式.当RECEIVER_MOBILE为空的时候,需要用到RECEIVER_ ...

  10. SpringMVC中的数据绑定(也就是参数的接收)

    spirngMVC中的数据绑定类型,分为默认数据类型,简单数据类型,pojo类型,包装的pojo类型,绑定数组类型,绑定集合类型,还有自定定义数据绑定. 例如默认数据类型的绑定@RequestMapp ...