mvcmvc6在哪个vs版本里版本有漏洞

微软asp.net所有版本被发现严重安全漏洞2416728
[问题点数:40分]
本版专家分:63
结帖率 97.67%
CSDN今日推荐
本版专家分:25489
2011年10月 Java大版内专家分月排行榜第二2011年9月 Java大版内专家分月排行榜第二
本版专家分:11876
2014年7月 其他开发语言大版内专家分月排行榜第一2013年3月 其他开发语言大版内专家分月排行榜第一2013年2月 其他开发语言大版内专家分月排行榜第一2013年1月 其他开发语言大版内专家分月排行榜第一2012年10月 其他开发语言大版内专家分月排行榜第一2012年9月 其他开发语言大版内专家分月排行榜第一2012年8月 其他开发语言大版内专家分月排行榜第一2012年7月 其他开发语言大版内专家分月排行榜第一2012年6月 其他开发语言大版内专家分月排行榜第一2012年5月 其他开发语言大版内专家分月排行榜第一
本版专家分:74370
2010年6月 扩充话题大版内专家分月排行榜第一
本版专家分:218873
2010年11月 扩充话题大版内专家分月排行榜第一2010年10月 扩充话题大版内专家分月排行榜第一
2010年12月 扩充话题大版内专家分月排行榜第二2010年8月 扩充话题大版内专家分月排行榜第二2010年7月 扩充话题大版内专家分月排行榜第二2010年6月 扩充话题大版内专家分月排行榜第二
2010年6月 Java大版内专家分月排行榜第三2010年5月 扩充话题大版内专家分月排行榜第三2010年4月 扩充话题大版内专家分月排行榜第三
本版专家分:5497
本版专家分:1523
本版专家分:17
本版专家分:1470
2012年10月 Linux/Unix社区大版内专家分月排行榜第二2010年4月 Linux/Unix社区大版内专家分月排行榜第二2010年3月 Linux/Unix社区大版内专家分月排行榜第二2010年1月 Linux/Unix社区大版内专家分月排行榜第二2009年12月 Linux/Unix社区大版内专家分月排行榜第二
2012年5月 Linux/Unix社区大版内专家分月排行榜第三2010年10月 Linux/Unix社区大版内专家分月排行榜第三2010年2月 Linux/Unix社区大版内专家分月排行榜第三
本版专家分:1509
匿名用户不能发表回复!|
CSDN今日推荐Spring MVC防御CSRF、XSS和SQL注入攻击 - Mainz - 博客园 - IT瘾
关于互联网、软件开发的网页收藏、分享、发现
Log me in using
本文说一下SpringMVC如何防御(Cross-site request forgery跨站请求伪造)和(Cross site script跨站脚本攻击)。
对来说,其实、、Rails、等都已经支持自动在涉及POST的地方添加Token(包括FORM表单和AJAX POST等),似乎是一个tag的事情,但如果了解一些实现原理,手工来处理,也是有好处的。因为其实很多人做web开发,但涉及到web安全方面的都是比较资深的开发人员,很多人安全意识非常薄弱,所以对他们来说,已经是比较高深的东西了。先说说什么是?你这可以这么理解攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。一般都是利用你的已登录已验证的身份来发送恶意请求。比较著名的一个例子就是2009年黑客利用Gmail的一个漏洞成功获取好莱坞明星Vanessa Hudgens的独家艳照。其攻击过程非常简单,给该明星的gmail账户发了一封email,标题是某大导演邀请你来看看这个电影,里面有个图片:&img src=&https://mail.google.com/mail?ui=2&fw=true&fwe=&&,结果她登录Gmail,打开邮件就默默无闻的中招了,所有邮件被转发到黑客的账号。因为当时Gmail设置转发的设置页面有漏洞,其设置方法是打开一个窗口,点击确定后实际URL是https://mail.google.com/mail?ui=2&fw=true&fwe=:
其实即使不是在同一个页面打开,在不同的tab打开也是一样可以通过网站登录验证的,因为受害者首先已经登录了网站,在浏览网站的过程中,若网站设置了Session cookie,那么在浏览器进程的生命周期内,即使浏览器同一个窗口打开了新的tab页面,Session cookie也都是有效的,他们在浏览器同一个窗口的多个tab页面里面是共享的(注:现在Gmail支持多个tab同时持有多个SessionID)。所以攻击步骤是,第一,受害者必须在同一浏览器窗口(即使不是同一tab)内访问并登陆目标站点;第二,这使得Session cookie有效,从而利用受害者的身份进行恶意操作。&
再举个实际的例子,假设我们界面上有删除某一项的链接,例如:&a href=&javascript:void(0)& onclick=&region_del.do?name=0000001&&Delete&/a&;
其Java Spring MVC后台有个函数是删除某个item,注意是GET不是POST:
@RequestMapping(value&=&&region_del.do&,&method&=&RequestMethod.GET)
public&String&regionDel(@RequestParam&String&name,&Locale&locale)
&&&&//Delete&region&name=@name....
&&&&return&&redirect:/region.html&;
点击界面上那个&a href=&javascript:void(0)& onclick=&region_del.do?name=0000001&&Delete&/a&链接,就后台删除某项,看起来非常正常啊。&
好,现在你登录你的网站,然后在另外一个tab打开这个html文件:
&!DOCTYPE&html&PUBLIC&&-//W3C//DTD&XHTML&1.0&Transitional//EN&&&http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&&
&html&xmlns=&http://www.w3.org/1999/xhtml&&xml:lang=&en&&lang=&en&&
&&&&&meta&http-equiv=&Content-Type&&content=&text/&charset=utf-8&&/&
&&&&&title&hack&/title&
&&&img&src=&http://localhost/testsite/region_del.do?name=0000001&/&
发现同样被删除了某项。试想,如果是网银,你的钱已经被转账......(除了referer不一样,session cookie被利用)
好了,现在 后台改成POST(写操作尽量用POST),前台界面那个删除的链接改成Form提交:
&form&action=&region_del.do&&method=&POST&&
&&input&type=&hidden&&name=&name&&value=&0000001&&
&&&&&&&&&input&type=&submit&&value=&Delete&&/&
看起来安全多了。OK,现在你登录你的网站,然后在另外一个tab打开这个html文件:
&!DOCTYPE&html&PUBLIC&&-//W3C//DTD&XHTML&1.0&Transitional//EN&&&http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&&
&html&xmlns=&http://www.w3.org/1999/xhtml&&xml:lang=&en&&lang=&en&&
&&&&&title&Hack&/title&
&&&&&script&
&&&&&&function&steal(){
&&&&&&&&var&mySubmit&=&document.getElementById('steal_form');
&&&&&&&&mySubmit.submit();
&&&&&/script&
&&&body&onload='steal()'&
&form&id&=&&steal_form&&method=&POST&&action=&http://localhost/testsite/region_del.do&&
&&&&input&type=&hidden&&name=&func&&value=&post&&
&input&type=&hidden&&name=&name&&value=&0000001&&
发现同样被删除了某项。试想,如果是网银,你的钱已经被转账......
当然,你如果前台还是用链接,但改成js,用AJAX POST提交,也是一样的效果:
&type:&&POST&,
解决办法就是在Form表单加一个hidden field,里面是服务端生成的足够随机数的一个Token,使得黑客猜不到也无法仿照Token。&
先写一个类,生成足够随机数的Token(注:Java的Random UUID已经足够随机了,参考和这个)&
package&com.ibm.cn.web.
import&java.util.UUID;
import&javax.servlet.http.HttpServletR
import&javax.servlet.http.HttpS
*&A&manager&for&the&CSRF&token&for&a&given&session.&The&{@link&#getTokenForSession(HttpSession)}&should&used&to
*&obtain&the&token&value&for&the&current&session&(and&this&should&be&the&only&way&to&obtain&the&token&value).
public&final&class&CSRFTokenManager&{
&&&&&*&The&token&parameter&name
&&&&static&final&String&CSRF_PARAM_NAME&=&&CSRFToken&;
&&&&&*&The&location&on&the&session&which&stores&the&token
&&&&public&static&final&&String&CSRF_TOKEN_FOR_SESSION_ATTR_NAME&=&CSRFTokenManager.class
&&&&&&&&&&&&.getName()&+&&.tokenval&;
&&&&public&static&String&getTokenForSession(HttpSession&session)&{
&&&&&&&&String&token&=&null;
&&&&&&&&//&I&cannot&allow&more&than&one&token&on&a&session&-&in&the&case&of&two
&&&&&&&&//&requests&trying&to
&&&&&&&&//&init&the&token&concurrently
&&&&&&&&synchronized&(session)&{
&&&&&&&&&&&&token&=&(String)&session
&&&&&&&&&&&&&&&&&&&&.getAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME);
&&&&&&&&&&&&if&(null&==&token)&{
&&&&&&&&&&&&&&&&token&=&UUID.randomUUID().toString();
&&&&&&&&&&&&&&&&session.setAttribute(CSRF_TOKEN_FOR_SESSION_ATTR_NAME,&token);
&&&&&&&&&&&&}
&&&&&&&&return&
&&&&&*&Extracts&the&token&value&from&the&session
&&&&&*&@param&request
&&&&&*&@return
&&&&public&static&String&getTokenFromRequest(HttpServletRequest&request)&{
&&&&&&&&return&request.getParameter(CSRF_PARAM_NAME);
&&&&private&CSRFTokenManager()&{
打开Form页面的时候在服务端生成Token并保存到Session中,例如:model.addAttribute(&csrf&, CSRFTokenManager.getTokenForSession(this.session));
然后在Form中添加Hidden field:&
&input type=&hidden& name=&CSRFToken& value=&${csrf}& /&
然后在后台提交的时候验证token :
@RequestMapping(value&=&&region_del.do&,&method&=&RequestMethod.GET)
public&String&regionDel(@RequestParam&String&name,&@RequestParam&String&CSRFToken,&Locale&locale)
&&&&&&&&if(CSRFToken&==&null&||&!CSRFToken.equals(session.getAttribute(CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME).toString())){
&&&&&&&&&&&&&&&&logger.debug(&CSRF&attack&detected.&URL:&region_edit.do&);
&&&&&&&&&&&&&&&&return&&redirect:/login.form&;
&&&&&&&&}&
&&&&&&&&&&&&&&&&
&&&&//Delete&region&name=@name....
&&&&return&&redirect:/region.html&;
你还可以把上面的步骤写到BaseController里面,或者写到拦截器里面,拦截所有POST请求,验证CSRF Token。这里掠过....
如果你用AJAX POST的方法,那么后台一样,前台也要有Hidden field保存Token,然后在提交AJAX POST的时候加上该csrf参数即可。(更多csrf参考和。)
AJAX POST的CSRF防御
首先在页面进入的时候从后台生成一个Token(每个session),放到一个Hidden input(用Spring tag或freemarker可以写) 。然后在ajax post提交的时候放到http请求的header里面:
&&&&var&headers&=&{};
&&&&headers['__RequestVerificationToken']&=&$(&#CSRFToken&).val();
&&&&$.ajax({
&&&&&&&&type:&&POST&,
&&&&&&&&headers:&headers,
&&&&&&&&cache:&false,
&&&&&&&&url:&base&+&&ajax/domain/delete.do&,
&&&&&&&&data:&&id=123&,
&&&&&&&&dataType:&json&,
&&&&&&&&async:&true,
&&&&&&&&error:&function(data,&error)&{},
&&&&&&&&success:&function(data)
&&&&&&&&&&&&
然后在后台controller里面校验header里面这个token,也可以把这个函数放到baseController里面:
protected&boolean&isValidCsrfHeaderToken()&{
&&&&&&&&if&(getRequest().getHeader(&__RequestVerificationToken&)&==&null
&&&&&&&&&&&&&&&&||&session
&&&&&&&&&&&&&&&&&&&&&&&&.getAttribute(CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME)&==&null
&&&&&&&&&&&&&&&&||&!this.getRequest()
&&&&&&&&&&&&&&&&&&&&&&&&.getHeader(&__RequestVerificationToken&)
&&&&&&&&&&&&&&&&&&&&&&&&.equals(session
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.getAttribute(
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&CSRFTokenManager.CSRF_TOKEN_FOR_SESSION_ATTR_NAME)
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.toString()))&{
&&&&&&&&&&&&return&false;
&&&&&&&&return&true;
关于xss的介绍可以看和网页,具体我就讲讲Spring MVC里面的预防:
web.xml加上:
&context-param&
&&&&param-name&defaultHtmlEscape&/param-name&
&&&&param-value&true&/param-value&
&/context-param&
Forms加上:
&spring:htmlEscape defaultHtmlEscape=&true& /&
更多信息查看的
第二种方法是手动escape,例如用户可以输入:&script&alert()&/script& 或者输入&h2&abc&h2&,如果有异常,显然有xss漏洞。
首先添加一个jar包:commons-lang-2.5.jar ,然后在后台调用这些函数:StringEscapeUtils.escapeHtml(string); StringEscapeUtils.escapeJavaScript(string); StringEscapeUtils.escapeSql(string);
前台js调用escape函数即可。
第三种方法是后台加Filter,对每个post请求的参数过滤一些关键字,替换成安全的,例如:& & ' & \ /& # &&
方法是实现一个自定义的HttpServletRequestWrapper,然后在Filter里面调用它,替换掉getParameter函数即可。
首先添加一个XssHttpServletRequestWrapper:
package&com.ibm.web.
import&java.util.E
import&javax.servlet.http.HttpServletR
import&javax.servlet.http.HttpServletRequestW
public&class&XssHttpServletRequestWrapper&extends&HttpServletRequestWrapper&{&&
&&&&public&XssHttpServletRequestWrapper(HttpServletRequest&servletRequest)&{
&&&&&&&&super(servletRequest);
&&&&public&String[]&getParameterValues(String&parameter)&{
&&&&&&String[]&values&=&super.getParameterValues(parameter);
&&&&&&if&(values==null)&&{
&&&&&&&&&&&&&&&&&&return&null;
&&&&&&&&&&}
&&&&&&int&count&=&values.
&&&&&&String[]&encodedValues&=&new&String[count];
&&&&&&for&(int&i&=&0;&i&&&&i++)&{
&&&&&&&&&&&&&&&&&encodedValues[i]&=&cleanXSS(values[i]);
&&&&&&return&encodedV
&&&&public&String&getParameter(String&parameter)&{
&&&&&&&&&&String&value&=&super.getParameter(parameter);
&&&&&&&&&&if&(value&==&null)&{
&&&&&&&&&&&&&&&&&return&null;
&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&return&cleanXSS(value);
&&&&public&String&getHeader(String&name)&{
&&&&&&&&String&value&=&super.getHeader(name);
&&&&&&&&if&(value&==&null)
&&&&&&&&&&&&return&null;
&&&&&&&&return&cleanXSS(value);
&&&&private&String&cleanXSS(String&value)&{
&&&&&&&&&&&&&&&&//You'll&need&to&remove&the&spaces&from&the&html&entities&below
&&&&&&&&value&=&value.replaceAll(&&&,&&&&&).replaceAll(&&&,&&&&&);
&&&&&&&&value&=&value.replaceAll(&\\(&,&&&(&).replaceAll(&\\)&,&&&)&);
&&&&&&&&value&=&value.replaceAll(&'&,&&&'&);
&&&&&&&&value&=&value.replaceAll(&eval\\((.*)\\)&,&&&);
&&&&&&&&value&=&value.replaceAll(&[\\\&\\\'][\\s]*javascript:(.*)[\\\&\\\']&,&&\&\&&);
&&&&&&&&value&=&value.replaceAll(&script&,&&&);
&&&&&&&&return&
然后添加一个过滤器XssFilter :
package&com.ibm.web.
import&java.io.IOE&&
import&javax.servlet.F&&
import&javax.servlet.FilterC&&
import&javax.servlet.FilterC&&
import&javax.servlet.ServletE&&
import&javax.servlet.ServletR&&
import&javax.servlet.ServletR&&
import&javax.servlet.http.HttpServletR&&
import&javax.servlet.http.HttpServletR
public&class&XssFilter&implements&Filter&{
&&&&FilterConfig&filterConfig&=&null;
&&&&public&void&init(FilterConfig&filterConfig)&throws&ServletException&{
&&&&&&&&this.filterConfig&=&filterC
&&&&public&void&destroy()&{
&&&&&&&&this.filterConfig&=&null;
&&&&public&void&doFilter(ServletRequest&request,&ServletResponse&response,
&&&&&&&&&&&&FilterChain&chain)&throws&IOException,&ServletException&{
&&&&&&&&chain.doFilter(new&XssHttpServletRequestWrapper(
&&&&&&&&&&&&&&&&(HttpServletRequest)&request),&response);
最后在web.xml里面配置一下,所有的请求的getParameter会被替换,如果参数里面 含有敏感词会被替换掉:
&&&filter&
&&&&&&filter-name&XssSqlFilter&/filter-name&
&&&&&&filter-class&com.ibm.web.beans.XssFilter&/filter-class&
&&&/filter&
&&&filter-mapping&
&&&&&&filter-name&XssSqlFilter&/filter-name&
&&&&&&url-pattern&/*&/url-pattern&
&&&&&&dispatcher&REQUEST&/dispatcher&
&&&/filter-mapping&
&(这个Filter也可以防止SQL注入攻击)&
登录页面的攻击例子
假设登录页面有个输入用户名和密码的输入框,可以有很多Xss/csrf/注入钓鱼网站/SQL等的攻击手段,例如:
&输入用户名 :&&& &&'&&script&alert(1779)&/script&
&输入用户名:&&&& usera&&'&&img src=&javascript:alert(23664)&&
&输入用户名:&&&& &'&&IMG SRC=&/WF_XSRF.html--end_hig--begin_highlight_tag--hlight_tag--&&
&输入用户名:&&&& usera'&&&iframe src=http://demo.testfire.net--en--begin_highlight_tag--d_highlight_tag--&
Web安全漏洞检测工具
推荐使用IBM Rational AppScan(、版权购买和破解、注册码自己解决)
可以录制脚本,设置URL,如果网站需要登录,可以设置自动登录:
检测结果还可以保持为专业的pdf检测报告&
业界安全编程标准最佳实践
于日 下午04时05分00秒发布
于日 下午12时14分30秒评论
HTML : b, strong, i, em, blockquote, br, p, pre, a href="", ul, ol, li, sub, sup
OpenID Login
电邮地址不会公开在网页上,您留下的电子邮件仅用于本文有新评论时通知您(以后可以随时拿掉)。只有全力以赴,方显轻松自如
ASP.NET MVC Tip #46 – 勿使用Delete链接,会造成安全漏洞
看到篇文章,里面说了个不知道的事儿,很粗糙生硬的翻了一下,记在这里,回头研究。
路过的朋友,如感兴趣,请直接看原文,以免耽误了您的时间。
我创建了一个 ASP.NET MVC 示例程序, 打算公布在
. 当 ASP.NET MVC 专题小组对该程序进行代码审查时 , 一个惊人的缺陷显现出来.
该程序极其简单。它包含了一个呈现数据库记录列表的视图。每条记录下面是一个Edit链接和一个Delete链接(见图1)。很标准的东西。或者,所以我想...
图1-- 一个数据库记录表格
这里就是缺陷。你不应该用链接来删除一条记录。使用Delete链接就打开了一个安全漏洞。
某人可以发一封包含一个image的邮件给你。该image通过如下标签被嵌入到邮件中:
&img src=”http://www.theApp.com/Home/Delete/23” _fcksavedurl=””http://www.theApp.com/Home/Delete/23”” /&
注意,src属性指向了Home控制器类的Delete() 方法。打开邮件(并且允许邮件客户端显示image)将在无警告的情况下删除23号记录。这是不好的。这是安全漏洞。
我曾经遇到过这种安全问题,但没有多想。REST纯粹主义者会捍卫Get请求不应该改变程序状态的想法。换句话说,执行Get请求应该是安全的,无副作用的。
比如,您不会希望搜索引擎在抓取您网站的时候删除您程序中的所有记录。执行Get请求不应该对您的程序有持久性影响。
删除一条记录的时候,适当的Http操作是 HTTP DELETE。HTTP 协议支持如下HTTP操作:
.OPITIONS - 返回可用的通信可选项的信息(幂等)。
返回请求的任何信息(幂等)。
.HEAD - 与 GET 执行同样的操作,只是没有消息体(幂等)。
.POST - 发布新信息或更新已有信息(非幂等)。
.PUT - 发布新信息或更新已有信息(幂等)。
.DELETE - 删除信息(幂等)。
.TRACE - 执行一个消息循环 (幂等)。
.CONNECT -
用于SSL通道。
这些操作被定义为HTTP 1.1 标准的一部分,您可以在这里看到.
注意,对 HTTP POST 和 HTTP PUT 的描述是相同的。为了解 POST 和 PUT 的区别,你需要明白幂等的含义。一个幂等操作无论执行多少次,都有相同的结果。比如,您执行一个POST操作来创建一条新的数据库记录,那么您每次都可以创建一条新的数据库记录。POST操作是非幂等的,因为每次操作的执行都会对您的程序有不同影响。
另一方面,如果您执行PUT操作,那么操作的执行都必须创建相同的数据库记录。PUT 操作是幂等的,应为执行PUT操作1000次与执行1次是一样的。
注意,HTTP DELETE 操作也是幂等的。多次执行HTTP DELETE 操作对您程序的影响应该是相同的。比如,请求 /Home/Delete/23 应该删除23号数据库记录,而不是其他记录,无论请求执行多少次。
HTML 只支持 GET和POST
所以,删除一条数据库记录时,恰当的做法是执行HTTP DELETE操作。执行一个HTTP DELETE操作不会打开安全漏洞,且不违背REST原则。
不幸的是,标准的HTML不支持GET、POST外的其他操作。链接总是执行GET操作,表单能执行GET或POST操作。HTML不支持其他的HTTP操作。
根据HTML 3.1 规范,HTML只支持GET和POST。参见。此外,IE只支持GET和POST。参见。
执行 Ajax Deletes
如果您想超越标准HTML,您可以利用Ajax来执行HTTP DELETE操作。XmlHttpRequest对象支持任何HTTP操作。因此,如果您愿意您的程序依赖于Javascript,您可以以正确的方式做一切。
清单1中的Home 控制器包含Index()和Delete()方法。Index()方法从Movies数据库返回所有的movies,Delete()方法通过特定的Id删除特定的movie(此控制器使用Entity Framework)。
清单1 - ControllersHomeController.cs
using System.Collections.G
using System.L
using System.W
using System.Web.M
using Tip46.M
namespace Tip46.Controllers
[HandleError]
public class HomeController : Controller
private MoviesDBEntities _entities = new MoviesDBEntities();
public ActionResult Index()
ViewData.Model = _entities.MovieSet.ToList();
return View();
[AcceptVerbs(HttpVerbs.Delete)]
public ActionResult Delete(int id)
var movieToDelete = (from m in _entities.MovieSet
where m.Id == id
select m).FirstOrDefault();
_entities.DeleteObject(movieToDelete);
_entities.SaveChanges();
return RedirectToAction("Index");
注意,Delete()方法声明了AcceptVerbs特性。Delete()方法只能被HTTP DELETE操作调用。
清单2中的Index视图通过HTML table显示来自Movies数据库表中的数据。每个movie记录下呈现一个Delete链接。
清单2 - ViewsHomeIndex.aspx
&%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage&IEnumerable&Tip46.Models.Movie&&" %&
&asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"&
&script src="../../Scripts/MicrosoftAjax.js" type="text/javascript"&&/script&
&script type="text/javascript"&
function deleteRecord(recordId)
// Perform delete
var action = "/Home/Delete/" + recordId;
var request = new Sys.Net.WebRequest();
request.set_httpVerb("DELETE");
request.set_url(action);
request.add_completed(deleteCompleted);
request.invoke();
function deleteCompleted()
// Reload page
window.location.reload();
&h2&Index&/h2&
&% foreach (var item in Model) { %&
&%-- Ajax Delete --%&
&a onclick="deleteRecord(&%= item.Id %&)" href="JavaScript:void(0)"&Delete&/a&
&%-- GET Delete: Security Hole
&%= Html.ActionLink("Delete", "Delete", new { id=item.Id })%&--%&
&%= Html.Encode(item.Id) %&
&%= Html.Encode(item.Title) %&
&%= Html.Encode(item.Director) %&
&%= Html.Encode(item.DateReleased) %&
&/asp:Content&
Delete通过Ajax调用执行。Delete链接调用Javascript deleteRecord()函数。该函数使用 Microsoft ASP.NET AJAX WebRequest 对象来执行Ajax调用。该WebRequest对象执行HTTP DELETE操作。
Delete操作执行完毕后,Javascript deleteCompleted()方法被调用。该方法重新加载了当前页面(这里将来会有一个更优雅的方式是使用下一个ASP.NET Ajax版本带来的ASP.NET Ajax模板功能,那样的话就只更新表格,而不用重新加载整个页面了)。
图2 - Index 视图
但是,我不想依赖于Javascript
很多开发人员不想自己的网站依赖于Javacript。回句话说,他们希望Javascript被关闭时,他们的网站一样可以工作。他们的需求是有些合理性的。不是所有移动设备都支持Javascript(尽管大多数做到了),并且Javascript还有可访问性问题(尽管Aria应该修正这些可访问性问题)。
如果您想自己的网站在Javascript被禁用时能工作,那么删除记录时,不能执行HTTP DELETE操作。而应该执行HTTP POST操作,HTTP POST不会像HTTP GET那样暴露出安全漏洞。
您可以使用AcceptVerbs特性来防止控制器动作被HTTP POST之外的操作调用。所以, Delete()动作看起来应该是这样的:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Delete(int id)
var movieToDelete = (from m in _entities.MovieSet
where m.Id == id
select m).FirstOrDefault();
_entities.DeleteObject(movieToDelete);
_entities.SaveChanges();
return RedirectToAction("Index");
不幸的是,通过标准HTML来执行HTTP POST操作的唯一途径是使用&form&标签。并且,您必须还用一个&input type="submit"&,&input type="image"&,或者&input type="button"&标签来为删除记录创建一个按钮。
这里最好的选择是&input type="image"&。那样的话,您可以在展示数据库记录表格时,使得Edit和Delete链接看起来一样。因为我不想我的示例程序依赖于Javascript,所以我打算采用此方式。
清单3中是无Javascript依赖的Index视图。
清单3 - ViewsHomeIndex.aspx (无 JavaScript)
&%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage&IEnumerable&Tip46.Models.Movie&&" %&
&asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"&
&h2&Index&/h2&
&% foreach (var item in Model) { %&
&a href='&%= Url.Action("Edit", "Home", new { id = item.Id })%&'&&img src="Content/Edit.png" alt="edit" border="0" /&&/a&
&% using (Html.BeginForm("Delete", "Home", new { id = item.Id }))
&input type="image" src="Content/Delete.png" /&
&%= Html.Encode(item.Id) %&
&%= Html.Encode(item.Title) %&
&%= Html.Encode(item.Director) %&
&%= Html.Encode(item.DateReleased) %&
&%= Html.ActionLink("Create New", "Create") %&
&/asp:Content&
我从Visual Studio 图片库中获取了为Edit和Delete链接使用的图片(见图3)。您可以在您硬盘的这个位置拿到这些图片集:
C:Program FilesMicrosoft Visual Studio 9.0Common7VS2008ImageLibrary
图3 - 为Edit和Delete使用图片
为使图片正确对齐,我为表格单元格增加了垂直对齐的样式。我使用了下面的样式:
border-collapse:
vertical-align:
padding:10
border-bottom: solid 1
不要使用Delete链接来删除数据库记录。潜在的,可能有人在您未知情的情况下通过执行GET请求来删除。
最好的选择是使用Javascript来执行HTTP DELETE 操作。使用Javascript能让您避开安全漏洞。使用Javascript可以让您最终HTTP协议的语义。
如果您不想您的程序依赖于Javascript,那第二个最好的选择执行HTTP POST来替代HTTP DELETE。执行HTML POST 需要您使用HTML表单。这个是丑陋的,然而,您可以通过使用&input type="image"&并添加样式表来改进外观。
没有更多推荐了,
加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!

我要回帖

更多关于 springmvc 版本 的文章

 

随机推荐