转:ajax的AntiForgery和Authorize 以及ajax登录例子
版权声明:本文为博主原创文章,遵循 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登录例子的更多相关文章
- 对jquery的ajax进行二次封装以及ajax缓存代理组件:AjaxCache
虽然jquery的较新的api已经很好用了, 但是在实际工作还是有做二次封装的必要,好处有:1,二次封装后的API更加简洁,更符合个人的使用习惯:2,可以对ajax操作做一些统一处理,比如追加随机数或 ...
- 原生态AJAX详解和jquery对AJAX的封装
AJAX: A :Asynchronous [eI`sinkrenes] 异步 J :JavaScript JavaScript脚本语言 A: And X :XML 可扩展标记语言 AJAX现在 ...
- ajax学习笔记(原生js的ajax)
ajax是一个与服务器端语言无关的技术,可以使用在任何语言环境下的web项目(如JSP,PHP,ASP等). ajax优点: 1) 页面无刷新的动态数据交互 2) 局部刷新页面 3) 界面的美观 4) ...
- ajax Session失效如何跳转到登录页面
在Struts应用中,我们发出的请求都会经过 相应的拦截器进行相关处理,一般都会有一个用户登录拦截(Session失效拦截):一般请求的话,如果Session失效时,我们会跳到登录页面,可是如果我们采 ...
- 处理jquery的ajax请求session过期跳转到登录页面
首先需要在拦截器中判断是否是ajax请求,如果是 if(isAjaxRequest(request)){//ajax请求 response.setHeader("sessionstatus& ...
- 来了解一下Ajax是什么?Ajax的原理?Ajax与传统Web比较?Ajax的优缺点?Ajax的Post与Get比较
一.什么是Ajax Ajax(Asynchronous Java and XML的缩写)是一种异步请求数据的web开发技术,对于改善用户的体验和页面性能很有帮助.简单地说,在不需要重新刷新页面的情况下 ...
- Ajax轮询——“定时的通过Ajax查询服务端”
Ajax轮询——"定时的通过Ajax查询服务端". 概念: 轮询(polling):客户端按规定时间定时像服务端发送ajax请求,服务器接到请求后马上返回响应信息并关闭连接. 百闻 ...
- javascript AJAX简单原理及什么是ajax
AJAX简单原理供初学者理解 AJAX的原理: Ajax的原理简单来说通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM而更新页面.这其 ...
- 客户端调用服务器端方法——ASP.NET AJAX(Atlas)、Anthem.NET和Ajax.NET Professional实现之小小比较
前几天曾经发过一篇<ASP.NET AJAX(Atlas)和Anthem.NET——管中窥豹般小小比较>,Jeffrey Zhao说用ASP.NET AJAX中的UpdatePanel似乎 ...
随机推荐
- .Net Core 3.0 Api json web token 中间件签权验证和 Cors 中间件处理跨域请求
第一步:在Nuget上安装"Microsoft.AspNet.WebApi.Cors"包,并对api controller使用[EnableCors]特性以及Microsoft.A ...
- GhostVLAD for set-based face recognition
GhostVLAD for set-based face recognition 中提到了文章解决的是template-based face recognition. VLAD: vector of ...
- hackbar简单安装使用教程
安装hackbar: 在火狐的附加组件中搜索“hackbar”,将它添加到火狐浏览器中, 重启后Firefox后安装完成,按F9键打开我们就会看到在地址栏下面会出现一个大框框就是hackbar了 框框 ...
- 5中I/O模型
输入操作包括两个阶段1.等待网络数据到达,被复制到内核中的缓冲区2.从内核缓冲区复制到进程缓冲区5种I/O模型1.阻塞式I/O:包含数据被复制到内核缓冲区和应用进程缓冲区两个过程,调用recvfrom ...
- C++11 并发编程库
C++11 并发编程 C++11 新标准中引入了几个头文件来支持多线程编程,他们分别是: <atomic>:该头文主要声明了两个类, std::atomic 和 std::atomic_f ...
- java学习摘抄笔记mybaits2
mybatis第二天 高级映射 查询缓存 和spring整合 课程复习: mybatis是什么? mybatis是一人持久层框架,mybatis是一个不完全的ORM框架.sql语句需要程序员自己去编 ...
- (CSDN 迁移) jFinal找不到或无法加载主类
错误: 找不到或无法加载主类 com.demo.common.DemoConfig 项目上右键 -> Build Path -> Order and Export 修改顺序: 从上到下依次 ...
- [转帖]使用 Vagrant 打造跨平台开发环境
使用 Vagrant 打造跨平台开发环境 https://segmentfault.com/a/1190000000264347 Vagrant 是一款用来构建虚拟开发环境的工具,非常适合 php/p ...
- vue 项目不显示样式 排版错乱
vue中的css 样式都在index.html中 看这里是否有导入css
- 资源池-数据库连接池简单实现-JAVA版本
转载:https://www.jianshu.com/p/381c86bdbff6 看了看druid和dbcp2的原码,发现他们都有各自存储连接的方式. druid : private volatil ...