发布:2021/8/26 16:03:48作者:管理员 来源:本站 浏览次数:981
在 Web 开发中,通常需要对前端(front-end)传到后端(back-end)的数据进行过滤和校验,以防范诸如 SQL 注入、XSS 注入之类的攻击。
在 Java 中,通过继承 HttpServletRequestWrapper 类可重新包装当前请求(Http Request)并将其替换,它的实现如下:
public class RequestWrapper extends HttpServletRequestWrapper {
private String AMP = "&";
private String queryString;
public RequestWrapper(HttpServletRequest request, String queryString)
{
super(request);
this.queryString = queryString;
}
public String getQueryString()
{
String query = null;
if (super.getQueryString() != null) {
query = super.getQueryString() + AMP + this.queryString;
} else {
query = this.queryString;
}
return query;
}
}
public class RequestHandler{
public void changeRequest{
RequestWrapper reqWrapper = new RequestWrapper(httpRequest, newQueryString() );
FilterChain.doFilter(reqWrapper, servletResponse); // this FilterChain guy helps to replace the old request to
// new request to runtime
}
}
然而,Asp.NET 中并没有类似的包装器实现,通常的做法是在每一个请求通过(ProcessRequest)后再进行合法性校验,它导致的问题是每个请求 Action 都需要重复调用过滤方法来过滤请求参数。这显然冗余且麻烦得不太合理。
Asp.NET 中的一种可行实现思路
在 IIS 7.0+ 中,可以通过 HttpModule 来实现。
前置知识
下面列举了一些可能需要提前了解的知识点
HttpRequest.Filter 微软给的简单示例
IIS 7.0的ASP.NET应用程序生命周期概述
为了有效地设置请求过滤器并应用它,应该在 BeginRequest 事件中进行设置,这是请求验证和 url 映射之后的第一个事件。
步骤
下面以在 .Net MVC 中配置示例
1. 配置
<?xml version="1.0" encoding="utf-8"?>
<configuration>
// ignore other configuration
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="httpModule" type="HttpRequestFilterModule" />
</modules>
</system.webServer>
</configuration>
2. 实现 HttpRequestFilterModule
using MvcApplication1.Filter;
using System.Web;
public class HttpRequestFilterModule : IHttpModule
{
public void Dispose()
{
throw new NotImplementedException();
}
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
}
public void Application_BeginRequest(object sender, EventArgs args)
{
HttpContext context = HttpContext.Current;
HttpRequest request = context.Request;
// 仅过滤 POST 请求
if (context.Request.HttpMethod != "POST")
{
return;
}
var requestCallback = new Func<string, string>(content => {
// may modify request content here
return "The request content is modified.";
});
context.Request.Filter = new RequestFilter(context.Request.Filter, context.Request.ContentEncoding, requestCallback);
}
}
RequestFilter.cs
using System;
using System.IO;
using System.Text;
namespace MvcApplication1.Filter
{
public class RequestFilter : Stream
{
//临时缓冲区用于优化加载
private MemoryStream ms;
//处理原始输出流
private Stream _stream;
//响应的编码方式
private Encoding _encoding;
//回调delegate
private Func<string, string> _callback;
public RequestFilter(Stream stream, Encoding encoding, Func<string, string> callback)
{
_stream = stream;
_encoding = encoding;
_callback = callback;
}
public override void Flush()
{
ms.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return ms.Seek(offset, origin);
}
public override void SetLength(long value)
{
ms.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
if (ms == null)
{
var sr = new StreamReader(_stream, _encoding);
string content = sr.ReadToEnd();
//回调执行
content = _callback(content);
byte[] bytes = _encoding.GetBytes(content);
ms = new MemoryStream();
ms.Write(bytes, 0, bytes.Length);
ms.Seek(0, SeekOrigin.Begin);
}
return ms.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return false; }
}
public override long Length
{
get { return ms.Length; }
}
public override long Position
{
get { return ms.Position; }
set { throw new NotSupportedException(); }
}
}
}
3. 验证结果
如果正常工作,访问下面 Get Action, 将得到 The request content is modified. 的输出结果。
public class HomeController : Controller
{
[HttpPost]
public ActionResult Get()
{
string requestBody = string.Empty;
using (StreamReader reader = new StreamReader(Request.InputStream))
{
requestBody = reader.ReadToEnd();
}
return Content(requestBody);
}
}
© Copyright 2014 - 2024 柏港建站平台 ejk5.com. 渝ICP备16000791号-4