mvc filter

//C# - 我怎么能拦截HTML的一个ViewResult,修改它,并为它呢? -  http://www.16kan.com/question/detail/301423.html




//http://dinowang.blogspot.tw/2013/07/documentwrite-aspnet-mvc-viewresult.html
//跨網站利用 document.write 顯示 ASP.NET MVC ViewResult 內容, 使用 ActionFilter


//http://www.cnblogs.com/niuchenglei/archive/2010/08/15/1800179.html
//http://www.nsoff.com/post/2012/03/13/Controller%E8%8E%B7%E5%BE%97View%E5%86%85%E5%AE%B9%E8%A7%A3%E6%9E%90%E5%90%8E%E8%BE%93%E5%87%BA.aspx
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.IO;


namespace NSOFF.Core.Mvc {
    public static class ControllerExtensions {
        #region Render Partial to String
        public static string RenderPartialViewToString(this Controller controller) {
            return RenderPartialViewToString(null, null);
        }
 
        public static string RenderPartialViewToString(this Controller controller, string viewName) {
            return RenderPartialViewToString(controller, viewName, null);
        }
 
        public static string RenderPartialViewToString(this Controller controller, object model) {
            return RenderPartialViewToString(controller, null, model);
        }
 
        public static string RenderPartialViewToString(this Controller controller, string viewName, object model) {
            if (string.IsNullOrEmpty(viewName))
                viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
 
            controller.ViewData.Model = model;
 
            using (StringWriter sw = new StringWriter()) {
                ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
                ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);
 
                return sw.GetStringBuilder().ToString();
            }
        }
        #endregion
 
        #region Render View to String
        public static string RenderViewToString(this Controller controller) {
            return RenderViewToString(controller, null);
        }
 
        public static string RenderViewToString(this Controller controller, string viewName) {
            return RenderViewToString(controller, viewName, null);
        }
 
        public static string RenderViewToString(this Controller controller, object model) {
            return RenderViewToString(controller, null, model);
        }
 
        public static string RenderViewToString(this Controller controller, string viewName, object model) {
            return RenderViewToString(controller, viewName, model, string.Empty);
        }
 
        public static string RenderViewToString(this Controller controller, string viewName, object model, string masterName) {
            if (string.IsNullOrEmpty(viewName))
                viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
 
            controller.ViewData.Model = model;
 
            using (StringWriter sw = new StringWriter()) {
                ViewEngineResult viewResult = ViewEngines.Engines.FindView(controller.ControllerContext, viewName, masterName);
                ViewContext viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
                viewResult.View.Render(viewContext, sw);
 
                return sw.GetStringBuilder().ToString();
            }
        }
        #endregion
    }

}







using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Text;
using System.Web.Mvc;
using System.Text.RegularExpressions;


namespace ShippingRen.ServiceHosts.MVC.ActionFilter
{
    public class WhiteSpaceFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var request = filterContext.HttpContext.Request;
            var response = filterContext.HttpContext.Response;
            response.Filter = new WhiteSpaceFilter(response.Filter, s =>
            {
                s = Regex.Replace(s, @"\s+(?=<)|\s+$|(?<=>)\s+", "");


                //single-line doctype must be preserved
                var firstEndBracketPosition = s.IndexOf(">");
                if (firstEndBracketPosition >= 0)
                {
                    s = s.Remove(firstEndBracketPosition, 1);
                    s = s.Insert(firstEndBracketPosition, ">");
                }
                return s;
            });
        }
    }


    public class WhiteSpaceFilter : Stream
    {
        private Stream _shrink;
        private Func<string, string> _filter;


        public WhiteSpaceFilter(Stream shrink, Func<string, string> filter)
        {
            _shrink = shrink;
            _filter = filter;
        }


        public override bool CanRead { get { return true; } }
        public override bool CanSeek { get { return true; } }
        public override bool CanWrite { get { return true; } }
        public override void Flush() { _shrink.Flush(); }
        public override long Length { get { return 0; } }
        public override long Position { get; set; }
        public override int Read(byte[] buffer, int offset, int count)
        {
            return _shrink.Read(buffer, offset, count);
        }
        public override long Seek(long offset, SeekOrigin origin)
        {
            return _shrink.Seek(offset, origin);
        }
        public override void SetLength(long value)
        {
            _shrink.SetLength(value);
        }
        public override void Close()
        {
            _shrink.Close();
        }


        public override void Write(byte[] buffer, int offset, int count)
        {
            // capture the data and convert to string
            byte[] data = new byte[count];
            Buffer.BlockCopy(buffer, offset, data, 0, count);
            string s = Encoding.UTF8.GetString(buffer);


            // filter the string
            s = _filter(s);


            // write the data to stream
            byte[] outdata = Encoding.UTF8.GetBytes(s);
            _shrink.Write(outdata, 0, outdata.GetLength(0));
        }
    }
}




<think>好的,我需要解决用户的问题:在网关过滤器解密请求参数后,如何在MVC Filter的getParameter方法中获取解密后的参数。首先,我需要理解整个流程。 用户提到网关过滤器已经解密了请求参数,接下来的问题是如何让后续的MVC Filter通过getParameter方法获取这些解密后的参数。根据Spring MVC的处理流程,请求会先经过网关过滤器,然后是Servlet容器中的Filter链,最后到达DispatcherServlet。在这个过程中,请求参数的处理可能涉及不同的阶段。 首先,我需要回忆一下HttpServletRequest的相关知识。HttpServletRequest的参数通常是在解析请求体时填充的,比如对于application/x-www-form-urlencoded或multipart/form-data类型的请求,参数会被自动解析到参数Map中。但对于其他类型如application/json,参数可能需要通过InputStream读取,这时候getParameter方法可能无法直接获取参数,除非手动解析。 用户的情况是,请求已经被网关过滤器解密,可能修改了请求体中的内容。这时候,后续的Filter(比如HiddenHttpMethodFilter)如果要通过getParameter获取参数,可能需要确保解密后的参数已经被正确填充到请求对象的参数Map中。 参考引用[2],其中提到当使用application/json时,参数是通过@RequestBody接收的,通常使用InputStream处理,而不是通过参数Map。因此,默认情况下,getParameter可能无法获取JSON参数,需要手动处理。 解决方案可能涉及自定义一个HttpServletRequestWrapper,覆盖getParameter相关的方法,将解密后的参数存入参数Map中。这样,后续的Filter调用getParameter时就能获取到解密后的值。 另外,参考引用[1]中的HiddenHttpMethodFilter,它可能依赖于请求参数(比如_method)来决定HTTP方法,这说明如果参数在请求体中,需要确保被正确解析到参数Map中才能被该Filter读取。因此,自定义Wrapper需要处理这一点。 具体步骤可能是:在网关过滤器中,解密请求体后,将解密后的内容重新包装成一个新的HttpServletRequest,其中参数被正确解析并填充到参数Map中。这可以通过自定义的ServletRequestWrapper来实现,覆盖getParameter、getParameterMap等方法,或者将解密后的内容转换为键值对,并存入参数Map中。 需要注意的是,对于application/json类型的请求,通常不会自动解析到参数Map,因此需要手动解析JSON内容,并将所需的参数设置到请求对象的参数Map中。例如,如果解密后的内容是JSON字符串,可以将其解析为一个Map,然后通过自定义的ServletRequestWrapper将这些键值对暴露给getParameter方法。 总结步骤: 1. 在网关过滤器中解密请求体,得到解密后的参数。 2. 使用自定义的HttpServletRequestWrapper包装原始请求,重写getParameter等方法,返回解密后的参数值。 3. 将包装后的请求传递给后续的Filter链,这样在MVC Filter中调用getParameter时就能获取到解密后的参数。 需要确保在包装请求时正确处理不同内容类型,例如,如果是JSON,可能需要解析为Map,并填充到参数中。同时,要注意请求体的可读性,可能需要缓存请求体内容,以便多次读取。 这样处理后,后续的Filter和控制器就可以通过getParameter方法获取到解密后的参数了。</think>在网关过滤器解密请求参数后,若要在MVC Filter中通过`getParameter`获取解密后的参数,需通过**自定义请求包装类**和**参数覆盖**实现。以下是具体步骤和示例: --- ### 一、实现逻辑 1. **解密请求体**:网关过滤器读取原始请求的输入流,解密后生成新的请求体内容。 2. **包装请求对象**:使用`HttpServletRequestWrapper`创建自定义请求对象,覆盖`getParameter`等方法,使其返回解密后的参数。 3. **参数映射处理**:若请求类型为`application/json`,需将解密后的JSON字符串解析为键值对,并存入参数Map中。 --- ### 二、代码实现 #### 1. 网关过滤器解密并包装请求 ```java public class DecryptFilter implements Filter { @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; // 1. 读取并解密请求体 String encryptedBody = IOUtils.toString(req.getInputStream(), StandardCharsets.UTF_8); String decryptedBody = decrypt(encryptedBody); // 解密方法 // 2. 包装请求对象,支持多次读取Body CustomRequestWrapper wrappedRequest = new CustomRequestWrapper(req, decryptedBody); // 3. 传递包装后的请求 chain.doFilter(wrappedRequest, response); } } // 自定义请求包装类 class CustomRequestWrapper extends HttpServletRequestWrapper { private final String modifiedBody; private Map<String, String[]> parameterMap; public CustomRequestWrapper(HttpServletRequest request, String modifiedBody) { super(request); this.modifiedBody = modifiedBody; // 解析JSON到参数Map(示例) Map<String, String> params = parseJsonToMap(modifiedBody); this.parameterMap = new HashMap<>(); params.forEach((k, v) -> parameterMap.put(k, new String[]{v})); } @Override public String getParameter(String name) { String[] values = parameterMap.get(name); return values != null ? values[0] : null; } @Override public Map<String, String[]> getParameterMap() { return parameterMap; } @Override public ServletInputStream getInputStream() { ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(modifiedBody.getBytes()); return new ServletInputStream() { // 实现读取逻辑 public int read() { return byteArrayInputStream.read(); } // 其他方法需覆盖 }; } } ``` --- ### 三、关键点说明 1. **请求体解析**:对于`application/json`类型,需手动将JSON内容解析为键值对,并存入`parameterMap`[^2]。 2. **输入流覆盖**:通过重写`getInputStream`方法,确保后续读取的是解密后的内容。 3. **参数优先级**:`getParameter`方法会优先从`parameterMap`中取值,因此覆盖后可直接返回解密后的参数。 --- ### 四、验证场景 假设原始加密请求体为: ```json {"userId":"ENCRYPTED_123"} ``` 解密后为: ```json {"userId":"DECRYPTED_456"} ``` 在MVC Filter中调用`request.getParameter("userId")`将返回`DECRYPTED_456`。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值