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. Python开发入门14天集训营-第一章

    python第一章 python变量 变量的作用 存数据 被程序调用和操作 标记数据 声明变量 name = "Ydh" 变量名 = 变量值 变量定义规范: 变量名只能是 字母.数 ...

  2. SQL中partition关键字的使用

    最近在写后台语句时候,运用到了partition这样一个关键字. 先大致说一下背景,有一种数据表,如下 现在需要取出,每一个人最近的一次打卡时间. 思路是,先把数据按照人名分组,然后在每个组里面按照时 ...

  3. 关于 frame的一些基本知识

    关于 frame的一些基本知识只是摘抄了一部分,供初学者参考. b.帧速率: 帧速率是每秒显示的图像数.标准影片(NTSC) 是29.97 帧第秒 (fps),电影是每秒24 帧fps.欧洲标准是(P ...

  4. VC中基于 Windows 的精确定时

    在工业生产控制系统中,有许多需要定时完成的操作,如定时显示当前时间,定时刷新屏幕上的进度条,上位 机定时向下位机发送命令和传送数据等.特别是在对控制性能要求较高的实时控制系统和数据采集系统中,就更需要 ...

  5. Windows平台的PHP之开启COM配置

    Windows平台的PHP如果未配置COM,调用COM组件,错误如下 Fatal error: Class 'COM' not found in XXXXXXXXX php 根目录的 ext 文件夹下 ...

  6. dojo报错总结

    dojo报错总结 1.错误一 neteaseTracker is not defined dojo.js(第15行) 2.错误二 _10 is undefined _SearchMixin.js(第5 ...

  7. Caused by: The Result type [json] which is defined in the Result annotation on the class

    1.错误描述 严重: Dispatcher initialization failed Unable to load configuration. - [unknown location] at co ...

  8. 小白学爬虫-批量部署Splash负载集群

    整体目录如下: study@study:~/文档/ansible-examples$ tree Splash_Load_balancing_cluster Splash_Load_balancing_ ...

  9. POI生成word文档完整案例及讲解

    一,网上的API讲解 其实POI的生成Word文档的规则就是先把获取到的数据转成xml格式的数据,然后通过xpath解析表单式的应用取值,判断等等,然后在把取到的值放到word文档中,最后在输出来. ...

  10. 异常-----Can't convert the date to string, because it is not known which parts of the date variable are in use. Use ?date, ?time or ?datetime built-in, or ?string.\u003Cformat> or ?string(format) built-

    1.错误描述 五月 27, 2014 12:07:05 上午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严重: Template proc ...