1 验证 

一般采用表单验证完成登陆验证,建议结合SSL使用。为限制控制器只能执行HTTPS,使用RequireHttpsAttribute

2 授权

对账户的权限的控制可以通过在控制器或控制器操作上加AuthorizeAttribute 属性。

扩展授权过滤器

扩展授权过滤器可以定义继承自AuthorizeAttribute的类,也可以定义同时继承自FilterAttribute, IAuthorizationFilter接口的类。

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)]
public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
public AuthorizeAttribute(); // 获取或设置有权访问控制器或操作方法的用户角色
public string Roles { get; set; } //获取此特性的唯一标识符。
public override object TypeId { get; } // 获取或设置有权访问控制器或操作方法的用户。
public string Users { get; set; } //重写时,提供一个入口点用于进行自定义授权检查
// 返回结果: 如果用户已经过授权,则为 true;否则为 false。
// 异常:System.ArgumentNullException:httpContext 参数为 null。
protected virtual bool AuthorizeCore(HttpContextBase httpContext); //处理未能授权的 HTTP 请求。
protected virtual void HandleUnauthorizedRequest(AuthorizationContext filterContext); //在过程请求授权时调用。
// 异常: System.ArgumentNullException:
//filterContext 参数为 null。
public virtual void OnAuthorization(AuthorizationContext filterContext); // 返回结果: 对验证状态的引用。
// 异常:System.ArgumentNullException:
// httpContext 参数为 null。
protected virtual HttpValidationStatus OnCacheAuthorization(HttpContextBase httpContext);
}

AuthorizeAttribute提供了三个可重新的虚方法AuthorizeCore,HandleUnauthorizedRequest,OnAuthorization,那么在执行授权动作的过程中他们是如何被调用的呢?看下源码的OnAuthorization方法,发现在这个方法中先调用AuthorizeCore,然后调用HandleUnauthorizedRequest被调用了。

        public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
//如果子操作的缓存处于活动状态,那么就抛出异常
if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
}
//判断控制器或控制器操作是否允许匿名访问,如果可以就return
bool skipAuthorization = filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)|| filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true); if (skipAuthorization)
{
return;
}
//进行权限验证
if (AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan());
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{//处理未通过权限验证的情形
HandleUnauthorizedRequest(filterContext);
}
}

当子操作缓存处于活动状态,那么抛出异常。然后检验是否可匿名访问,如果可以匿名访问就不进行验证;

综合以上分析,扩展AuthorizeAttribute要注意:

1)在子类AuthorizeCore中,调用父类的AuthorizeCore方法

base.OnAuthorization(filterContext);

2)在子类的AuthorizeCore方法中验证用户的权限。

3)通过子类的构造函数传入用户的权限值

代码示例如下:

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
private UserRole role;
public CustomAuthorizeAttribute(UserRole role)
{
this.role = role;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool ret = false; //获得用户信息(从本地Session或分布式缓存中获取)
var userInfo = ......
if(userInfo==null)
{
//信息为null,一般认为登陆超时或没有登陆
} if(userInfo.Role == UserRole.Org)
{
ret = true;
}
else
{
//提示无权限
} return ret;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
} if (filterContext.HttpContext.Request.IsAjaxRequest())
{//针对ajax请求进行处理 }
else
{//非aiax进行处理 //跳转到指定页面
string strUrl = ......;
filterContext.Result = new RedirectResult(strUrl);
}
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
}
}
public enum UserRole
{
Org = ,
Vip = ,
Guest =
}

3 安全

总的原则:

所有层或各个子系统各自负责好自己的安全。

任何用户数据和来自其他系统的数据都要经过检验。

在满足需求的情况下,尽量缩小账户的权限。

减少暴露的操作数量和操作参数。

关闭服务器不需要的功能。

4 防范攻击

4.1跨站脚本攻击(XSS)

被动注入:用户的输入含有恶意脚本,而网站又能够不加检验地接受这样的输入,进而保存到数据库中。

主动注入:用户将含有恶意脚本的内容输入到页面文本框中,然后在屏幕上显示出来。

防御方法:

1)使用Razor语法输出的内容已经被编码,可以不做任何其他处理

例如:

<h4>@Model.Field</h4>

Html.ActionLink,Html.Action等方法会将路由参数编码输出

2)大部分的XSS攻击可通过对输入内容进行编码来阻止:Html.Encode,Html.AttributeEncode,Url.Encode

3)对Js进行编码

使用Ajax.JavaScriptStringEncode

4)将AntiXSS库作为默认的编码器(不建议使用,不灵活)

ASP.NET 4.5 集成Anti-XSS Library,可以通过配置来对整个网站的输出进行编码。

<system.web>
<httpRuntime targetFramework="4.5" encoderType="System.Web.Security.AntiXss.AntiXssEncoder,System.Web"/>
</system.web>

4.2跨站请求伪造(CSRF/XSRF)

防御方法:

1)使用Html隐藏域存储用户令牌,令牌可以存储在Session里或者cookie里

2)在视图表单中使用@Html.AntiForgeryToken(),在控制器操作上添加属性[ValidateAntiForgeryToken],注意表单一定要使用@Html.BeginForm生成

实现机制:AntiForgeryToken方法向用户浏览器cookie中写入一个加密的数据,并在表单内插入一个隐藏栏位,每次刷新页面时隐藏栏位的值都不同,每次执行控制器操作前,都会验证隐藏栏位和浏览器cookie中的值是否相同,只有相同才允许执行控制器操作。

使用限制:

  • 客户端浏览器不能禁用cookie
  • 只对post请求有效
  • 若有XSS漏洞,则可轻易获取令牌
  • 对Ajax请求不能传递令牌,即对Ajax无效

3)使用幂等的Get请求,仅使用Post请求修改数据(仅仅是一定程度上限制这种攻击而已)

4)使用动作过滤器,验证UrlReferrer

扩展的动作过滤器:

public class CSRFFilter:AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext.HttpContext == null)
{
throw new HttpException("请求无效");
} if (filterContext.HttpContext.Request.UrlReferrer == null)
{
throw new HttpException("请求无效");
} if (filterContext.HttpContext.Request.UrlReferrer.Host != "sit.com")
{
throw new HttpException("来自非法网站");
}
}
}

4.3 cookie盗窃

cookie有两种形式

1)会话cookie:存储在浏览器内存中,浏览器每次请求通过Http头进行传递

2)持久性cookie:存储在硬盘上,同样通过Http头进行传递

二者的区别:会话cookie常在会话结束时失效,而持久性cookie在下一次访问站点时仍然有效。

被窃取的原因:依赖于XSS漏洞,注入一段恶意脚本就能窃取。

防御方法:

1)在web.config对cookie进行设置

<httpCookies httpOnlyCookies="true"/>,httpOnlyCookies指定为true表达仅服务器可以访问,浏览器无法访问

2)在编写代码时为每个cookie单独设置

Response.Cookies["cok"].Value = Guid.NewGuid().ToString();

Response.Cookies["cok"].HttpOnly = true;

4.4重复提交

防御方法:

1)使用bind特性,设置想要绑定的属性来,防止这种攻击。也可以设置不要绑定的字属性,但优先选择设置要绑定的属性。

例:

可以指定多个字段,用逗号分隔

public ActionResult TestViewData([Bind(Include = "Field,Field1,Field1")]ModelF mf)
{
......
}

2)使用UpdateModel或TryUpdateModel

3)使用ViewModel,明确规定View使用的数据模型

4.5开放重定向

防御方法:

使用Url.IsLocalUrl检测是否为本地url

4.6 SQL注入攻击

防御方法:

通过参数注入非法获得或修改网站数据。

使用参数化查询来防止SQL注入攻击。

参考:

1.Jess Chadwick/Todd Snyder/Hrusikesh Panda,徐雷/徐扬

译。ASP.NET MVC4 Web编程

2.Jon Galloway/Phil Haack/Brad Wilson/K. Scott Allen,孙远帅/邹权译  ASP.NET MVC4 高级编程(第四版)

3.黄保翕,ASP.NET MVC4开发指南

4.蒋金楠,ASP.NET MVC4框架揭秘

5.https://www.asp.net/mvc

转载与引用请注明出处。

时间仓促,水平有限,如有不当之处,欢迎指正。

ASP.NET MVC编程——验证、授权与安全的更多相关文章

  1. 七天学会ASP.NET MVC (四)——用户授权认证问题

    小编应各位的要求,快马加鞭,马不停蹄的终于:七天学会 Asp.Net MVC 第四篇出炉,在第四天的学习中,我们主要了学习如何在MVC中如何实现认证授权等问题,本节主要讲了验证错误时的错误值,客户端验 ...

  2. 通过扩展改善ASP.NET MVC的验证机制[实现篇]

    原文:通过扩展改善ASP.NET MVC的验证机制[实现篇] 在<使用篇>中我们谈到扩展的验证编程方式,并且演示了本解决方案的三大特性:消息提供机制的分离.多语言的支持和多验证规则的支持, ...

  3. ASP.NET MVC 编程参考

    ASP.NET MVC 编程参考   转载请注明出处:http://surfsky.cnblogs.com MVC    参考 http://msdn.microsoft.com/zh-cn/dd40 ...

  4. 七天学会ASP.NET MVC (四)——用户授权认证问题 【转】

    http://www.cnblogs.com/powertoolsteam/p/MVC_four.html 小编应各位的要求,快马加鞭,马不停蹄的终于:七天学会 Asp.Net MVC 第四篇出炉,在 ...

  5. ASP.NET MVC Model验证(五)

    ASP.NET MVC Model验证(五) 前言 上篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现, 然而在MVC框架中还给我们提供了其它 ...

  6. ASP.NET MVC Model验证(四)

    ASP.NET MVC Model验证(四) 前言 本篇主要讲解ModelValidatorProvider 和ModelValidator两种类型的自定义实现,前者是Model验证提供程序,而Mod ...

  7. ASP.NET MVC Model验证(三)

    ASP.NET MVC Model验证(三) 前言 上篇中说到在MVC框架中默认的Model验证是在哪里验证的,还讲到DefaultModelBinder类型的内部执行的示意图,让大家可以看到默认的M ...

  8. ASP.NET MVC Model验证(二)

    ASP.NET MVC Model验证(二) 前言 上篇内容演示了一个简单的Model验证示例,然后在文中提及到Model验证在MVC框架中默认所处的位置在哪?本篇就是来解决这个问题的,并且会描述一下 ...

  9. ASP.NET MVC Model验证(一)

    ASP.NET MVC Model验证(一) 前言 前面对于Model绑定部分作了大概的介绍,从这章开始就进入Model验证部分了,这个实际上是一个系列的Model的绑定往往都是伴随着验证的.也会在后 ...

随机推荐

  1. uploadify上传文件(1)--下载

    最近在给公司做一个软件版本迭代管理的软件,是一个asp.net网站开发项目.利用mvc框架,前端采用bootstrap,数据库是MySQL,数据库访问利用EF框架. 软件需求是公司软件开发项目多,版本 ...

  2. CDN网络架构

    CDN(content delivery network 内容分发网络) 本质上就是提供缓存,使得用户总是能访问离他最近的服务器,akamai是世界上的第一家做CDN的公司 实例:构建CDN分发网络架 ...

  3. jQuery手机发送验证码倒计时代码

    <!DOCTYPE> <html> <head> <meta charset="UTF-8"> <script type=&q ...

  4. equals 与 == 区别及用法

    ==: 1. ==操作符专门用来比较两个变量的值是否相等,也就是用于比较变量所对应的内存中所存储的数值是否相同: 2.如果要比较两个变量是否指向同一个对象,这时候就需要用==操作符进行比较: 注意:= ...

  5. R︱高效数据操作——data.table包(实战心得、dplyr对比、key灵活用法、数据合并)

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 由于业务中接触的数据量很大,于是不得不转战开始 ...

  6. 嵌入式linux------SDL移植(am335x下显示bmp图片)

    #include<stdio.h> #include "/usr/local/ffmpeg_arm/include/SDL/SDL.h" char *bmp_name[ ...

  7. MyEclipse弹出提示窗口

    MyEclipse弹出提示窗口 1.弹窗如下

  8. RAID卡技术简析

    经过一段时间的折腾,工作的事终于解决了,新工作一上来的第一件事就要熟悉RAID卡存储机制,先简单了解下RAID卡吧. 提到RAID卡就不得不提什么是RAID,RAID是英文Redundant Arra ...

  9. Django学习-13-simple_tag使用

    一些HTML方法                {{item.event_start | date:"Y-m-d H:i:s"}}                     {{bi ...

  10. 手机端仿ios的三级联动脚本四

    二,脚本 <script> $("#city-picker").cityPicker({ title: "选择省市区/县", onChange: f ...