httpModel 实现页面url加密

     这其实是以前工作中的一个功能,当时觉得很好奇,是如何实现自动加密页面中的url的,如GridView中的链接绑定等。通过加密后的url的表现形式就如page.aspx?EncodingQuery=2IYZ2UW1bS2rPAuKZf4WWw==。今天在复习asp.net的基础常识时,既然想起,就来看看是如何实现的(这里主要还是参考DC.Web.HttpCompress)。

    1、首先,新建一个asp.net网站项目,在默认的页面上我们来绑定一个Gridview控件。

   

View Code
  <div>
        <asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" Height="285px" Width="638px">
            <Columns>
                <asp:HyperLinkField DataNavigateUrlFields="Id" DataNavigateUrlFormatString="~/page.aspx?id={0}" HeaderText="Title" DataTextField="Name" />
            </Columns>
        </asp:GridView>
    </div>

 2、 在页面的后台方法中进行绑定数据:

View Code
 1    List<LinkModel> list = new List<LinkModel>(2);
 2                 list.Add(new LinkModel()
 3                     {
 4                         Id ="11",
 5                         Name = "ltq"
 6                     });
 7                 list.Add(new LinkModel()
 8                 {
 9                     Id = "12"
10                     ,Name = "hb"
11                 });
12                 GridView1.DataSource = list;
13                 GridView1.DataBind();

3、 点击F5,然后查看生成的源代码:

可以看到,这里还是原始的未加密的url字符串。

4、 好,现在新增一个HttpModel.cs:

View Code
  1    public class HttpModule : IHttpModule
  2     {
  3         public void Dispose()
  4         {
  5 
  6         }
  7 
  8         public void Init(HttpApplication context)
  9         {
 10             
 11             context.BeginRequest += context_BeginRequest;
 12            
 13             context.PostReleaseRequestState += context_PostReleaseRequestState;
 14         }
 15 
 16 
 17         void context_BeginRequest(object sender, EventArgs e)
 18         {
 19             HttpApplication app = (HttpApplication) sender;
 20             HttpContext context = app.Context;
 21             string currentPath = context.Request.Url.PathAndQuery;
 22             int index = currentPath.IndexOf("?EncodingQuery=");
 23             if(index>0)
 24             {
 25                 string eQuery = currentPath.Substring(index+1);
 26                 string encryptQuery = currentPath.Substring(index + 15);
 27                 string query = AESUtil.Decrypt(encryptQuery,CommonUtil.AesKey );
 28                 currentPath = currentPath.Replace(eQuery,   query);
 29                 context .RewritePath(currentPath);
 30             }
 31         }
 32        
 33         private void context_PostReleaseRequestState(object sender, EventArgs e)
 34         {
 35             HttpApplication app = (HttpApplication) sender;
 36           
 37             if (app.Request["HTTP_X_MICROSOFTAJAX"] != null)
 38                 return;
 39 
 40             // fix to handle caching appropriately
 41             // see http://www.pocketsoap.com/weblog/2003/07/1330.html
 42             // Note, this header is added only when the request
 43             // has the possibility of being compressed...
 44             // i.e. it is not added when the request is excluded from
 45             // compression by CompressionLevel, Path, or MimeType            
 46             string realPath = "";
 47             Configuration settings = null;
 48             // get the config settings
 49           
 50             app.Context.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;
 51             string acceptedTypes = app.Request.Headers["Accept-Encoding"];
 52 
 53             // if we couldn't find the header, bail out
 54             if (acceptedTypes == null)
 55                 return;
 56 
 57             // Current response stream
 58 
 59             //Stream baseStream = app.Response.Filter;
 60             CompressionPageFilter filter = new CompressionPageFilter(app.Response.Filter);
 61             filter .AesKey =CommonUtil .AesKey;
 62             
 63             filter.App = app;
 64             app.Response.Filter = filter;
 65 
 66             // check for buggy versions of Internet Explorer
 67             if (app.Context.Request.Browser.Browser == "IE")
 68             {
 69                 if (app.Context.Request.Browser.MajorVersion < 6)
 70                     return;
 71                 else if (app.Context.Request.Browser.MajorVersion == 6 &&
 72                          !string.IsNullOrEmpty(app.Context.Request.ServerVariables["HTTP_USER_AGENT"]) &&
 73                          app.Context.Request.ServerVariables["HTTP_USER_AGENT"].Contains("EV1"))
 74                     return;
 75             }
 76             acceptedTypes = acceptedTypes.ToLower();
 77           
 78             if (filter.Compress != "none")
 79                 app.Response.AppendHeader("Content-Encoding", filter.Compress);
 80         }
 81 
 82         private class CompressionPageFilter : Stream
 83         {
 84 
 85             public string AesKey { get; set; }
 86             private HttpApplication app;
 87 
 88             public HttpApplication App
 89             {
 90                 get { return app; }
 91                 set { app = value; }
 92             }
 93 
 94             private string compress = "none";
 95 
 96             public string Compress
 97             {
 98                 get { return compress; }
 99                 set { compress = value; }
100             }
101 
102             private StringBuilder responseHtml;
103 
104      
105 
106             private const string _linkPattern =
107                 "(?<HTML><a[^>]*href\\s*=\\s*[\\\"\\']?(?<HREF>[^\"'>\\s]*)[\\\"\\']?[^>]*>)";
108 
109             public CompressionPageFilter(Stream sink)
110             {
111                 _sink = sink;
112                 responseHtml = new StringBuilder();
113             }
114 
115             private Stream _sink;
116 
117             #region Properites
118 
119             public override bool CanRead
120             {
121                 get { return true; }
122             }
123 
124             public override bool CanSeek
125             {
126                 get { return true; }
127             }
128 
129             public override bool CanWrite
130             {
131                 get { return true; }
132             }
133 
134             public override void Flush()
135             {
136                 _sink.Flush();
137             }
138 
139             public override long Length
140             {
141                 get { return 0; }
142             }
143 
144             private long _position;
145 
146             public override long Position
147             {
148                 get { return _position; }
149                 set { _position = value; }
150             }
151 
152             #endregion
153 
154             #region Methods
155 
156             public override int Read(byte[] buffer, int offset, int count)
157             {
158                 return _sink.Read(buffer, offset, count);
159             }
160 
161             public override long Seek(long offset, SeekOrigin origin)
162             {
163                 return _sink.Seek(offset, origin);
164             }
165 
166             public override void SetLength(long value)
167             {
168                 _sink.SetLength(value);
169             }
170 
171             public override void Close()
172             {
173                 _sink.Close();
174             }
175 
176             public override void Write(byte[] buffer, int offset, int count)
177             {
178                 string strBuffer = UTF8Encoding.UTF8.GetString(buffer, offset, count);
179 
180                 // ---------------------------------
181                 // Wait for the closing </html> tag
182                 // ---------------------------------
183                 Regex eof = new Regex("</html>", RegexOptions.IgnoreCase);
184 
185                 responseHtml.Append(strBuffer);
186 
187                 if (eof.IsMatch(strBuffer))
188                 {
189                     // when compressing the html, some end characters are cut off.  Add some spaces so it cuts the spaces off instead of important characters
190                     responseHtml.Append(Environment.NewLine + Environment.NewLine + Environment.NewLine +
191                                         Environment.NewLine + Environment.NewLine + Environment.NewLine +
192                                         Environment.NewLine + Environment.NewLine);
193                     string html = responseHtml.ToString();
194 
195                     // replace the css and js with HttpHandlers that compress the output       
196                     html = ReplaceLink(html);
197 
198 
199                     byte[] data = UTF8Encoding.UTF8.GetBytes(html);
200 
201 
202                     _sink.Write(data, 0, data.Length);
203                 }
204             }
205 
206             public string ReplaceLink(string html)
207             {
208                 // create a list of the stylesheets
209                 List<string> stylesheets = new List<string>();
210                 // create a dictionary used for combining css in the same directory
211                 Dictionary<string, List<string>> css = new Dictionary<string, List<string>>();
212 
213                 // create a base uri which will be used to get the uris to the css
214                 Uri baseUri = new Uri(app.Request.Url.AbsoluteUri);
215 
216                 // loop through each match
217                 foreach (Match match in Regex.Matches(html, _linkPattern, RegexOptions.IgnoreCase))
218                 {
219                     // this is the enire match and will be used to replace the link
220                     string linkHtml = match.Groups[0].Value;
221                     // this is the href of the link
222                     string href = match.Groups[2].Value;
223 
224                     // get a uri from the base uri, this will resolve any relative and absolute links
225                     Uri uri = new Uri(baseUri, href);
226                     string file = "";
227                     // check to see if it is a link to a local file
228                     if (uri.Host == baseUri.Host)
229                     {
230                         // check to see if it is local to the application
231                         if (uri.AbsolutePath.ToLower().StartsWith(app.Context.Request.ApplicationPath.ToLower()))
232                         {
233                             // this combines css files in the same directory into one file (actual combining done in HttpHandler)
234                             int index = uri.AbsolutePath.LastIndexOf("/");
235                             string path = uri.AbsolutePath.Substring(0, index + 1);
236                             file = uri.AbsolutePath.Substring(index + 1);
237                             if (!css.ContainsKey(path))
238                                 css.Add(path, new List<string>());
239                             css[path].Add(file + (href.Contains("?") ? href.Substring(href.IndexOf("?")) : ""));
240                             // replace the origianl links with blanks
241                             var query = uri.Query;
242                             if (query != "")
243                             {
244                                 string temp = query.Substring(1);
245                                 string encryQuery = "?EncodingQuery=" + AESUtil.Encrypt(temp, AesKey);
246                                 string newlinkHtml = linkHtml.Replace(query, encryQuery);
247                                 html = html.Replace(linkHtml, newlinkHtml);
248 
249                             }
250 
251                             continue;
252                         }
253                          
254                     }
255                 
256                 }
257 
258                 return html;
259             }
260 
261 
262 
263 
264 
265             #endregion
266 
267         }
268     }

代码较长,但应该很清晰,在代码中是通过AES加解密链接字符串的参数的。

5、注册这个HttpModel,在web.config中添加即可:

1   <system.webServer>
2     <handlers>
3     </handlers>
4     <modules>
5       <add name="HttpCompressModule" type="HttpModelTest.HttpModule"/>
6     </modules>
7   </system.webServer>

因为是在Vs2012下进行的测试,配置文件与在iis6中的配置是不同的。

6、再次F5进入调试,查看源代码:

可以看到,这里的参数都已经被加密了。

7、 我们再来测试看看能不能正确解密这个字符串,在page.aspx的后台代码中添加如下代码:

1   protected void Page_Load(object sender, EventArgs e)
2         {
3             string id = Request["id"];
4             Response.Write(id);
5         }

F5进入测试:

可以看到,正确输出id值。

8、总结:

a)加解密算法的选择是否正确,这个还得研究,毕竟感觉加密后的url的字符太多了。

b)正则获取url的是否正确,会不会把其他文本内容中的url也加密了?

c)性能,每次这样的遍历页面,进行匹配,对性能的影响有多大?

原文地址:https://www.cnblogs.com/liaotongquan/p/2991920.html