版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ashcn2001/article/details/53409256
现有的mvc无法用无刷的形式来对数据进行验证 特别是对于ajax 进行数据访问,如果是机密信息则有很大的风险。现在可以用自定义attribute的方法来加入针对数据信息验证。

针对AntiForgery的验证方法
attrbute属性的定义

[AttributeUsage(AttributeTargets.Class)]
public class ValidateAntiForgeryTokenOnAllPosts : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;

// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];

var cookieValue = antiForgeryCookie != null
? antiForgeryCookie.Value
: null;

try {

AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
catch (Exception e) {
//filterContext.Result = new RedirectResult("/Account/Login?returnUrl=" +
// HttpUtility.UrlEncode(filterContext.HttpContext.Request.Url.ToString()));

ContentResult result = new ContentResult();
result.Content = "<div style='text-align:center;padding:1em;' >当前已经处于退出状态,请重新登录</div>";
filterContext.Result = result;

}
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
else {
throw new Exception("没有权限");
//base.HandleUnauthorizedRequest(filterContext);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
或者这里有令外一个替代方法用来备选,本质上是一样的 (备选)

public class ExtendedValidateAntiForgeryToken : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
if (request.HttpMethod != WebRequestMethods.Http.Post) return;
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null ? antiForgeryCookie.Value : null;
//从cookies 和 Headers 中 验证防伪标记
//这里可以加try-catch
try {

AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
catch (Exception e) {
//filterContext.Result = new RedirectResult("/Account/Login?returnUrl=" +
// HttpUtility.UrlEncode(filterContext.HttpContext.Request.Url.ToString()));

ContentResult result = new ContentResult();
result.Content = "<div style='text-align:center;padding:1em;' >当前已经处于退出状态,请重新登录</div>";
filterContext.Result = result;

}
}
else
{
new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
使用方法为
客户端 cshtml里面需要用js来发送post数据到服务器。

//获取防伪标记
var token = $('@Html.AntiForgeryToken()').val();
@*var token = $("[name='__RequestVerificationToken']").val();*@
var headers = {};
//防伪标记放入headers
//也可以将防伪标记放入data
headers["__RequestVerificationToken"] = token;
$(document).on("click", ".nav-tabs a", function (e) {

if ($(this).parent().parent().hasClass("nav")) {
$(".nav-tabs li").removeClass("active");
$(this).parent().addClass("active");
}
e.preventDefault();
//alert($(this).attr("href"));
$.ajax({
type: 'POST',
url: $(this).attr("href"),
cache: false,
headers: headers,
data: {},
beforeSend: function () {
$("#myTabContent").html("正在索取数据");
},

success: function (data) {
//alert(data)
$("#myTabContent").html(data);
},
error: function (data) {
$("#myTabContent").html(data);
}
});

})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
服务器端则可以使用
因为是在class上使用的属性 所以

[HealthCareCore.ValidateAntiForgeryTokenOnAllPosts]
public class AJAXController : Controller
{
public ActionResult Order(string tabName)
{
IQueryable<nongfuEntityframework.Info> quene = db.Info;
Regex reg = new Regex(@"page=.{1,}?(&|$)");//获取page的页数
var url = reg.Replace(Request.QueryString.ToString(), "");
switch (tabName)
{
case "allOrder":
return PartialView("Order_tab", quene);
case "notPaid":
quene= quene.Where(m => m.pay_status == 0);
return PartialView("Order_tab", quene);
}
return View();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
如何对登陆信息进行验证呢,这里可以使用

针对Authorize的验证方法
attribute属性的定义

public class AjaxAuthorizeAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext context)
{
if (context.HttpContext.Request.IsAjaxRequest())
{
var urlHelper = new UrlHelper(context.RequestContext);
context.HttpContext.Response.StatusCode = 403;
context.Result = new JsonResult
{
Data = new
{
Error = "NotAuthorized",
LogOnUrl = urlHelper.Action("LogOn", "Account")
},
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
else
{
base.HandleUnauthorizedRequest(context);
//throw new Exception("No enough right");
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
客户端cshtml的使用

$(function()
{
$(document).ajaxError(function(e, xhr) {
if (xhr.status == 403)
{
var response = $.parseJSON(xhr.responseText);
window.location = response.LogOnUrl;
}
});
});
1
2
3
4
5
6
7
8
9
10
服务器端的使用
在action上面加上[AjaxAuthorize]

服务器上ajax登录
在mvc当中我们使用jquery的ajax向服务器发送登录信息捎带手当然我们必须使用ValidateAntiForgeryToken来做方位认证,当然这里还有个问题,那就是我们用ajax所发出的数据是透明的,实际上在截获的发送数据中我们的用户名和密码都是明文的

使用ajax登录的技术为
ajax发送数据(带有用户名密码和forgerytoken)->
服务器进行登录,mvc内置的登陆中回想response写入登录cookie->
ajax接收相关登录成功信息,并自动从返回的信息中把cookie写到客户端

[HttpPost]
[ExtendedValidateAntiForgeryToken]
public ActionResult Login(LoginInfo model){
if(登录成功){
var httpCookie = System.Web.HttpContext.Current.Response.Cookies[key];
if (httpCookie == null) return;
httpCookie.Value = value;
httpCookie.Expires = expires;
return Json(登录成功!);
}else{
return Json(登录失败了!);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
综合演示
cshtml端

<!DOCTYPE html>
@{
Layout = null;
}
<html>
<head>
<title>Ajax Login</title>
</head>
<body>
username: @ViewBag.username
<div class="container">
<form id="login-form" action="#" method="POST">
@*生成防伪标记*@
@Html.AntiForgeryToken()
<div class="controls">
<label for="userName">用户名:</label>
<input type="text" name="userName" id="userName" placeholder="用户名" value="@ViewBag.UserName" />
</div>
<div class="controls">
<label for="password">密 码:</label>
<input type="password" name="password" id="password" placeholder="密码" />
</div>
<div class="controls">
<input type="checkbox" name="rememberMe" id="rememberMe" />
<label for="rememberMe">记住我?</label>
</div>
<input type="submit" value="登录" class="btn" />
</form>
</div>
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>

</body>
</html>
<script>

$("#login-form").validate({
rules: {
userName: {
required: true,
},
password: {
required: true,
rangelength: [8, 20]
}
},
messages: {
userName: "请输入用户名!",
password: {
required: "请输入密码!",
rangelength: "请输入{0}到{1}之间的密码!"
}
}, submitHandler: function (form) {
//获取防伪标记
var token = $('input[name=__RequestVerificationToken]').val();
var headers = {};
headers["__RequestVerificationToken"] = token;
var params = $(form).serialize();
$.ajax({
type: "POST",
url: "Login",
data: params,
headers: headers,
success: function (result) {
alert(result.msg);
},
error: function () {
alert("Error");
}
});
}
});
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
accountcontroller.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Helpers;
using System.Web.Mvc;
using MvcAjaxDemo.Models;

namespace MvcAjaxDemo.Controllers
{
public class AccountController : Controller
{
//
// GET: /Account/Login
public ActionResult Login()
{
ViewBag.UserName = Retrieve("UserName");

return View();
}

[HttpPost]
[ExtendedValidateAntiForgeryToken]
public ActionResult Login(LoginInfo model)
{
//是否为Ajax请求
if (!Request.IsAjaxRequest())
return View();
if (model.UserName == null)
return Json(GetResult(false, "用户名为空!", null));
//根据用户名获取用户
var user = UserService.GetUsers().SingleOrDefault(p => p.LoginName == model.UserName);

if (user == null)
return Json(GetResult(false, "用户名或密码错误!", null));
//验证密码
if (user.Password != model.Password)
return Json(GetResult(false, "用户名或密码错误!", null));

if (!string.IsNullOrWhiteSpace(model.RememberMe))
{
//保存帐户登录名
Save("UserName", model.UserName, DateTime.Now.AddDays(2));
}

return Json(GetResult(false, "登录成功!", null));

}

#region 辅助方法
/// <summary>
/// 获取结果集
/// </summary>
/// <param name="rel">状态</param>
/// <param name="msg">提示信息</param>
/// <param name="data">数据集</param>
/// <returns></returns>
public static object GetResult(bool rel, string msg, object data)
{
return new Dictionary<string, object> { { "rel", rel }, { "msg", msg }, { "obj", data } };
}

/// <summary>
/// 保存Cookie
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
/// <param name="expires">过期时间</param>
public void Save(string key, string value, DateTime expires)
{
var httpCookie = System.Web.HttpContext.Current.Response.Cookies[key];
if (httpCookie == null) return;
httpCookie.Value = value;
httpCookie.Expires = expires;
}
/// <summary>
/// 检索Cookie
/// </summary>
/// <param name="key">键</param>
/// <returns></returns>
public string Retrieve(string key)
{
var cookie = System.Web.HttpContext.Current.Request.Cookies[key];
return cookie != null ? cookie.Value : "";
}
#endregion
}

#region 防止CSRF攻击特性
/// <summary>
/// 防止CSRF攻击特性
/// </summary>
public class ExtendedValidateAntiForgeryToken : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
if (request.HttpMethod != WebRequestMethods.Http.Post) return;
if (request.IsAjaxRequest())
{
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null ? antiForgeryCookie.Value : null;
//从cookies 和 Headers 中 验证防伪标记
//这里可以加try-catch
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute().OnAuthorization(filterContext);
}
}
}
#endregion

//Model
public class User
{
public int Id { get; set; }
public string LoginName { get; set; }
public string Password { get; set; }
}

public class UserService
{
public static IList<User> GetUsers()
{
return new List<User>
{
new User
{
Id=1,
LoginName = "admin",
Password = "admin1234"
}
};
}
}
}
namespace MvcAjaxDemo.Models
{
public class LoginInfo
{
/// <summary>
/// 用户名
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
/// <summary>
/// 记住我?
/// </summary>
public string RememberMe { get; set; }
}
}
————————————————
版权声明:本文为CSDN博主「ashcn2001」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/ashcn2001/article/details/53409256

转:ajax的AntiForgery和Authorize 以及ajax登录例子的更多相关文章

  1. 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache

    虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...

  2. 原生态AJAX详解和jquery对AJAX的封装

    AJAX: A :Asynchronous [eI`sinkrenes] 异步 J :JavaScript    JavaScript脚本语言 A: And X :XML 可扩展标记语言 AJAX现在 ...

  3. ajax学习笔记(原生js的ajax)

    ajax是一个与服务器端语言无关的技术,可以使用在任何语言环境下的web项目(如JSP,PHP,ASP等). ajax优点: 1) 页面无刷新的动态数据交互 2) 局部刷新页面 3) 界面的美观 4) ...

  4. ajax Session失效如何跳转到登录页面

    在Struts应用中,我们发出的请求都会经过 相应的拦截器进行相关处理,一般都会有一个用户登录拦截(Session失效拦截):一般请求的话,如果Session失效时,我们会跳到登录页面,可是如果我们采 ...

  5. 处理jquery的ajax请求session过期跳转到登录页面

    首先需要在拦截器中判断是否是ajax请求,如果是 if(isAjaxRequest(request)){//ajax请求 response.setHeader("sessionstatus& ...

  6. 来了解一下Ajax是什么?Ajax的原理?Ajax与传统Web比较?Ajax的优缺点?Ajax的Post与Get比较

    一.什么是Ajax Ajax(Asynchronous Java and XML的缩写)是一种异步请求数据的web开发技术,对于改善用户的体验和页面性能很有帮助.简单地说,在不需要重新刷新页面的情况下 ...

  7. Ajax轮询——“定时的通过Ajax查询服务端”

    Ajax轮询——"定时的通过Ajax查询服务端". 概念: 轮询(polling):客户端按规定时间定时像服务端发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接. 百闻 ...

  8. javascript AJAX简单原理及什么是ajax

    AJAX简单原理供初学者理解 AJAX的原理: Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面.这其 ...

  9. 客户端调用服务器端方法——ASP.NET AJAX(Atlas)、Anthem.NET和Ajax.NET Professional实现之小小比较

    前几天曾经发过一篇<ASP.NET AJAX(Atlas)和Anthem.NET——管中窥豹般小小比较>,Jeffrey Zhao说用ASP.NET AJAX中的UpdatePanel似乎 ...

随机推荐

  1. docker build提示error checking context:can't stat xxx

    现象描述 使用docker build一个镜像的时候,提示下面的错误: ➜ docker build -t image_name -f xxx.dockerfile . error checking ...

  2. 查看apache httpd server中加载了哪些模块

    说明: 有的时候,需要查看当前apache中都加载了哪些模块,通过以下命令进行查看 [root@hadoop1 httpd-]# bin/apachectl -t -D DUMP_MODULES Lo ...

  3. Ubuntu 16.04 Roboware安装和使用

    博客参考:https://blog.csdn.net/qq_41450811/article/details/80305846 RoboWare Studio是一个ROS集成开发环境.它使 ROS开发 ...

  4. 【SQL骚操作】SqlServer数据库表生成C# Model实体类SQL语句

    已知现有表T1 想快速获取cs类结构 /// <summary> /// T1 /// </summary> public class T1 { /// <summary ...

  5. TensorFlow 8 bit模型量化

    本文基本参考自这篇文章:8-Bit Quantization and TensorFlow Lite: Speeding up mobile inference with low precision ...

  6. Windows删除文件夹下的指定格式文件(递归删除)

    问题描述: 今天遇到一个需求,需要对文件夹进行文件筛选.目录结构较为复杂(目录较多,层次较深),数据量较大(总共60GB左右). 鉴于上述情况,直接排除了人工处理方式(否则小伙伴们会打死我的). 解决 ...

  7. nginx deny 封IP

    官方文档地址:http://nginx.org/en/docs/http/ngx_http_access_module.html#deny Syntax: deny address | CIDR | ...

  8. Visual Studio 2017 Add WSDL

    Normal way Right click Project -> Add -> Web Reference -> Advanced Intranet way download ws ...

  9. Redis 的主从复制(Master/Slave)

    目录 1. 是什么 2. 能干嘛 3. Redis主从复制讲解 (1). info replication:查看 目标redis 主从情况 (2) . 配从库不配主库 (3). 常用策略 (4). 复 ...

  10. js生成条形码——JsBarcode

    原文地址:https://www.cnblogs.com/huangenai/p/6347607.html 介绍一下在GitHub生成条形码的js插件→JsBarcode 条码支持的有: CODE12 ...