ASP.NET MVC5登录之(一)Forms身份认证

ASP.NET身份认证过程

在ASP.NET中,身份认证过程分为两个部分:

  1. 认证:识别当前请求的用户是否为可识别(已登录)用户;
  2. 授权:根据认证中识别的用户决定是否允许当前用户的请求访问指定的资源。

其中Forms认证由FormsAuthenticationModule实现,URL授权检查由UrlAuthorizationModule实现

认证(登录与登出的实现)

//登录
public static bool SignOn(string username,string password,bool persist)
{
    InterfaceUserService userService = null;
    if (userService == null)
    {
        userService = new UserService();
    }
    //此处省略参数合法性验证   
  
    //验证用户名密码是否正确,若正确则设置Cookie
    if (userService.Validate(username, password))
    {
        SetAuthenticationTicket(username, persist);
        HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username,persist);
        HttpContext.Current.Response.Cookies.Remove(authCookie.Name);
        HttpContext.Current.Response.Cookies.Add(authCookie);
        return true;
    }
    else
    {
        return false;
    }
}

//登出
public static void LogOut()
{
    HttpCookie authCookie = new HttpCookie(FormsAuthentication.FormsCookieName);
    //使cookie强制过期
    authCookie.Expires = DateTime.Now.AddYears(-30);
    authCookie.Path = HttpContext.Current.Request.ApplicationPath;

    HttpContext.Current.Response.Cookies.Add(authCookie);
    //退出登录后执行页面重定向到主页操作
}

//获取登录用户名部分代码,AuthenticationMoudel类中的UserName属性
public string UserName
{
    get
    {
        var httpContext = HttpContext.Current;
        if (httpContext != null &&
            httpContext.Request != null &&
            httpContext.Request.IsAuthenticated)
        {
            try
            {
                return httpContext.User.Identity.Name;
            }
            catch
            {

            }
        }
        else
        {
            return null;    
        }
    }
}

对于Forms认证,我们需要在Web.config的<system.web>节点部分添加以下内容:

<authentication mode="Forms" >
    <forms cookieless="UseCookies" 
           name="LoginCookieName" 
           loginUrl="~/Default.aspx"/>
</authentication>

该部分指定了身份验证模式为Forms,Cookie的使用方式,Cookie名称,默认登录页面(当未认证或认证失败时会跳转到默认登录页)。

为何要设置Cookie呢?

因为Forms的身份认证是通过Cookie来维持的,且该Cookie是加密过的HttpOnly Cookie(无法在浏览器端更改的Cookie)

授权

授权的问题就是用户与用户组权限的问题,根据当前登录用户及其所属用户组的权限来判断当前用户的请求是否能够访问目标资源。

Forms身份认证的授权也需要在Web.config的<system.web>节点中配置,示例如下:

<authorization>
    <allow users="admin"/>
    <deny users="*"/>
</authorization>

自定义验证用户登录

一、Filter

ASP.NetMVC模式自带的过滤器Filter,是一种声明式编程方式,支持四种过滤器类型,分别是:Authorization(授权),Action(行为),Result(结果)和Exception(异常)。

​ 表1

过滤器类型 接口 描述
Authorization IAuthorizationFilter 此类型(或过滤器)用于限制进入控制器或控制器的某个行为方法
Action IActionFilter 用于进入行为之前或之后的处理
Result IResultFilter 用于返回结果的之前或之后的处理
Exception IExceptionFilter 用于指定一个行为,这个被指定的行为处理某个行为方法或某个控制器里面抛出的异常

但是默认实现它们的过滤器只有三种,分别是ActionFilter(方法),Authorize(授权),HandleError(错误处理);各种信息如下表所示:

​ 表2

过滤器 类名 实现接口
Authorize AuthorizeAttribute IAuthorizationFilter
HandleError HandleErrorAttribute IExceptionFilter
自定义 ActionFilterAttribute IActionFilter和IResultFilter

ASP.NET默认的身份验证过滤器是[Authorize]对应AuthorizeAttribute类

二、通过自定义过滤器实现登录验证

表2中只写了实现表1中的接口,实际上ActionFilterAttribute继承了FilterAttribute、IActionFilter和IResultFilter.

具体实现方法

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
public class AuthenticatedAttribute:FilterAttribute, IActionFilter
{  
    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
            
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //此处AuthenticationMoudel类中的UserName属性已在认证模块中定义
        if (string.IsNullOrEmpty(AuthenticationMoudel.UserName))
        {
            filterContext.Result = new HttpUnauthorizedResult();
        }
    }
}  

最后在需要登录验证的地方打下自定义的Filter的标签[Authenticated]

[Authenticated]
public class HomeController : Controller  
{  
    public ActionResult Index()  
    {  
        ViewBag.Message = "欢迎使用 ASP.NET MVC!";  
        return View();  
    }  
}

三、使用系统的AuthorizeAttribute验证登录

public class AuthenticationAttribute : AuthorizeAttribute
{
  public override void OnAuthorization(AuthorizationContext filterContext)
  {
    //base.OnAuthorization(filterContext);
    //如果控制器没有加AllowAnonymous特性或者Action没有加AllowAnonymous特性才检查
    if (!filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute),true) && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute),true))
    {
      //此处写判断是否登录的逻辑代码
      HttpCookie cookie = filterContext.HttpContext.Request.Cookies["Member"];
      if (!(cookie!=null && cookie.Values["name"] == "test" && cookie.Values["pass"] == "123"))       {
        filterContext.Result = new RedirectResult("/Member/Login");
      }
    }
  }
}

若加了Authentication过滤器的控制器中有需要匿名访问的方法,可以在方法前面添加[AllowAnonymous]过滤器

另一种写法是继承FilterAttribute 并实现接口IAuthorizationFilter,方式与系统的AuthorizeAttribute类似

参考文章:1. 细说ASP.NET Forms身份认证

​ 2. ASP.Net MVC Filter验证用户登录

菜鸟一枚,还望大家多多指教

补充:在运行上述代码时,发现配置了Forms认证后登录不成功,匿名用户访问需要认证的页面时不能跳转到登录页面,解决方案如下:
在Web.Config文件的<system.webServer>节添加下面两句

<remove name="FormsAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />

刚开始我只有第一句<remove name="FormsAuthentication" />,添加第二句后解决问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容