HTTPS跳转框架HTTP Security–Asp.net和ASP.NET MVC下可自由配置URL的HTTPS跳转框架

简介

一个简单易扩展的HTTP跳转HTTPS的框架。由配置文件配置规则,然后在HTTPMODULE里截获请求进行规则验证是否跳转HTTPS.

组成:

  1. web.config,用来配置规则
  2. HttpsConfiguration,用于读取配置文件
  3. HttpSecurityModule,用来截获请求触发规则验证
  4. RequestProcessor,用既有规是验证请求
  5. PathsMatcher,多路径(URL)匹配器
  6. PathMatcher,单URL路径匹配器
  7. PathMatcherFactory,用于创建StartsWith或Exact具体URL路径,可进行更多扩展,如正则表达式匹配。
  8. SecureRedirection,跳转HTTPS

WEB.CONFIG

 

[html][/html] view plaincopy在CODE上查看代码片派生到我的代码片

  1. <configSections>
  2.     <section name=”HttpsConfiguration” type=”ICStars2_0.Common.ConfigSections.HttpsConfiguration, ICStars2_0.Common, Version=1.0.0.0, Culture=neutral” />
  3.   </configSections>
  4.  <HttpsConfiguration mode=”On”>
  5.     <paths>
  6.       <add path=”/Test” />
  7.       <add path=”/Account” security=”Ignore” />
  8.       <add path=”/Account/Check.aspx” matchType=”Exact” />
  9.       <add path=”/Member” matchType=”StartsWith” />
  10.     </paths>
  11.   </HttpsConfiguration>

mode选项On/Off, 开启或不开启HTTPS跳转

 

<add path=””/>, 添加一个URL验证规则。 默认security=”Secure”并且matchType=”StartsWith”

<add path=”” security=”” matchType=”” />,添加一个URL验证规则并设置具体选项。security选项Secure/Ignore,进行HTTPS跳转或忽略当前设置。matchType选项Exact/StartsWith,进行完全匹配或仅匹配开始字串。

 

HttpsConfiguration

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. namespace ICStars2_0.Common.ConfigSections
  2. {
  3.     public enum Mode
  4.     {
  5.         On,
  6.         Off
  7.     }
  8.     public enum RequestSecurity
  9.     {
  10.         Secure,
  11.         Ignore
  12.     }
  13.     public enum PathMatchType
  14.     {
  15.         Exact,
  16.         StartsWith
  17.     }
  18.     internal sealed class ElementNames
  19.     {
  20.         internal const string Mode = “mode”;
  21.         internal const string Paths = “paths”;
  22.         internal const string MatchType = “matchType”;
  23.         internal const string Path = “path”;
  24.         internal const string Security = “security”;
  25.     }
  26.     public class HttpsConfiguration : ConfigurationSection
  27.     {
  28.         [ConfigurationProperty(ElementNames.Mode, DefaultValue = Mode.On)]
  29.         public Mode Mode
  30.         {
  31.             get { return this[ElementNames.Mode] is Mode ? (Mode) this[ElementNames.Mode] : Mode.On; }
  32.         }
  33.         [ConfigurationProperty(ElementNames.Paths, IsRequired = true)]
  34.         public HttpsPathCollection Paths
  35.         {
  36.             get
  37.             {
  38.                 return this[ElementNames.Paths] as HttpsPathCollection;
  39.             }
  40.         }
  41.     }
  42.     public class HttpsPathCollection:ConfigurationElementCollection
  43.     {
  44.         public HttpsPath this[int index]
  45.         {
  46.             get
  47.             {
  48.                 return base.BaseGet(index) as HttpsPath;
  49.             }
  50.             set
  51.             {
  52.                 if (base.BaseGet(index) != null)
  53.                 {
  54.                     base.BaseRemoveAt(index);
  55.                 }
  56.                 this.BaseAdd(index, value);
  57.             }
  58.         }
  59.         protected override ConfigurationElement CreateNewElement()
  60.         {
  61.             return new HttpsPath();
  62.         }
  63.         protected override object GetElementKey(ConfigurationElement element)
  64.         {
  65.             return ((HttpsPath)element).Path;
  66.         }
  67.     }
  68.     public class HttpsPath:ConfigurationElement
  69.     {
  70.         [ConfigurationProperty(ElementNames.Path)]
  71.         public string Path
  72.         {
  73.             get
  74.             {
  75.                 return this[ElementNames.Path] as string;
  76.             }
  77.         }
  78.         [ConfigurationProperty(ElementNames.MatchType, DefaultValue=PathMatchType.StartsWith)]
  79.         public PathMatchType MatchType
  80.         {
  81.             get
  82.             {
  83.                 return this[ElementNames.MatchType] is PathMatchType ? (PathMatchType) this[ElementNames.MatchType] : PathMatchType.Exact;
  84.             }
  85.         }
  86.         [ConfigurationProperty(ElementNames.Security,DefaultValue=RequestSecurity.Secure)]
  87.         public RequestSecurity Security
  88.         {
  89.             get
  90.             {
  91.                 return this[ElementNames.Security] is RequestSecurity ? (RequestSecurity) this[ElementNames.Security] : RequestSecurity.Secure;
  92.             }
  93.         }
  94.     }
  95. }

用于读取相应WEB.CONFIG中的信息。

 

HttpSecurityModule

 

[html][/html] view plaincopy在CODE上查看代码片派生到我的代码片

  1. <httpModules>
  2.       <add name=”SecuritySwitchModlue” type=”ICStars2_0.Framework.HttpSecurity.HttpSecurityModule, ICStars2_0.Framework, Version=1.0.0.0, Culture=neutral” />
  3.  </httpModules>

 

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. namespace ICStars2_0.Framework.HttpSecurity
  2. {
  3.     public class HttpSecurityModule : IHttpModule
  4.     {
  5.         private HttpsConfiguration _config { get; set; }
  6.         public void Init(HttpApplication context)
  7.         {
  8.             _config = ConfigurationManager.GetSection(“HttpsConfiguration”) as HttpsConfiguration; ;
  9.             if (_config == null || _config.Mode == Mode.Off)
  10.             {
  11.                 return;
  12.             }
  13.             context.BeginRequest += context_AcquireRequestState;
  14.         }
  15.         void context_AcquireRequestState(object sender, EventArgs e)
  16.         {
  17.             var application = sender as HttpApplication;
  18.             RequestProcessor rp=new RequestProcessor(application.Context,_config);
  19.             rp.Process();
  20.         }
  21.         public void Dispose()
  22.         {
  23.         }
  24.     }
  25. }

配置HTTPMODULE,读取HTTPS跳转框架配置信息HttpsConfiguration,把截获的请求和读取的配置文件传递给请求处理器RequestProcessor。

 

 

RequestProcessor

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. namespace ICStars2_0.Framework.HttpSecurity
  2. {
  3.     internal class RequestProcessor
  4.     {
  5.         public HttpContext Context { get; set; }
  6.         public HttpsConfiguration Config { get; set; }
  7.         public RequestProcessor(HttpContext context,HttpsConfiguration config)
  8.         {
  9.             Context = context;
  10.             Config = config;
  11.         }
  12.         public void Process()
  13.         {
  14.             if (Context.Request.IsSecureConnection) return;
  15.             IEnumerable<HttpsPath> pathLIst = Config.Paths.Cast<HttpsPath>();
  16.             var ignorePaths = pathLIst.Where(p => p.Security == RequestSecurity.Ignore);
  17.             var securePaths = pathLIst.Where(p => p.Security == RequestSecurity.Secure);
  18.             PathsMatcher ignoreMatcher = new PathsMatcher(Context,ignorePaths);
  19.             if (ignoreMatcher.IsMatch()) return;
  20.             PathsMatcher secureMatcher = new PathsMatcher(Context, securePaths);
  21.             if (!secureMatcher.IsMatch()) return;
  22.             SecureRedirection secureRedirection=new SecureRedirection(Context,null);
  23.             secureRedirection.Go();
  24.         }
  25.     }
  26. }

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. if (Context.Request.IsSecureConnection) return;

如果当前请求是HTTPS,则忽略。

 

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. var ignorePaths = pathLIst.Where(p => p.Security == RequestSecurity.Ignore);

获取需要被忽略的URL规则集合

 

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. var securePaths = pathLIst.Where(p => p.Security == RequestSecurity.Secure);

获取需要进行HTTPS跳转的URL规则集合

 

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. PathsMatcher ignoreMatcher = new PathsMatcher(Context,ignorePaths);
  2.             if (ignoreMatcher.IsMatch()) return;

创建忽略规则匹配器并使用需要被忽略的URL规则集合初始化,如果当前求匹配到任何一个忽略规则,则不进行HTTPS跳转。

 

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. PathsMatcher secureMatcher = new PathsMatcher(Context, securePaths);
  2.             if (!secureMatcher.IsMatch()) return;
  3.             SecureRedirection secureRedirection=new SecureRedirection(Context,null);
  4.             secureRedirection.Go();

创建需要进行HTTPS跳转的URL规则匹配器并初始化, 如果当前请求匹配到任何一个安全规则,则由SecureRedirection进行HTTPS跳转。

 

PathsMatcher

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. namespace ICStars2_0.Framework.HttpSecurity
  2. {
  3.     class PathsMatcher
  4.     {
  5.         public HttpContext Context { get; set; }
  6.         public IEnumerable<HttpsPath> Paths { get; set; }
  7.         public PathsMatcher(HttpContext context, IEnumerable<HttpsPath> paths)
  8.         {
  9.             Context = context;
  10.             Paths = paths;
  11.         }
  12.         public bool IsMatch()
  13.         {
  14.             return Paths.Any(p => PathMatcherFactory.CreatePathMatcher(Context.Request.Url.AbsolutePath, p).IsMatch());
  15.         }
  16.     }
  17. }

 

多路径匹配器

 

PathMatcher

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. namespace ICStars2_0.Framework.HttpSecurity
  2. {
  3.     interface IPathMatcher
  4.     {
  5.         bool IsMatch();
  6.     }
  7. }
  8. namespace ICStars2_0.Framework.HttpSecurity
  9. {
  10.    internal class ExactPathMatcher:IPathMatcher
  11.     {
  12.         public string Path { get; set; }
  13.         public string Pattern { get; set; }
  14.         public ExactPathMatcher(string path, string pattern)
  15.         {
  16.             Path = path;
  17.             Pattern = pattern;
  18.         }
  19.        public bool IsMatch()
  20.        {
  21.            return Path.Equals(Pattern, StringComparison.InvariantCultureIgnoreCase);
  22.        }
  23.     }
  24. }
  25. internal class StartsWithPathMatcher:IPathMatcher
  26.     {
  27.         public string Path { get; set; }
  28.         public string Pattern { get; set; }
  29.         public StartsWithPathMatcher(string path, string pattern)
  30.         {
  31.             Path = path;
  32.             Pattern = pattern;
  33.         }
  34.         public bool IsMatch()
  35.         {
  36.             return Path.StartsWith(Pattern, StringComparison.InvariantCultureIgnoreCase);
  37.         }
  38.     }

单一路径匹配器,可扩展更多的匹配器

 

PathMatcherFactory

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. internal class PathMatcherFactory
  2.     {
  3.         public static IPathMatcher CreatePathMatcher(string path, HttpsPath httpsPath)
  4.         {
  5.             switch (httpsPath.MatchType)
  6.             {
  7.                     case PathMatchType.StartsWith:
  8.                     return new StartsWithPathMatcher(path, httpsPath.Path);
  9.                     case PathMatchType.Exact:
  10.                     return new ExactPathMatcher(path, httpsPath.Path);
  11.             }
  12.             return null;
  13.         }
  14.     }

匹配器工厂

 

SecureRedirection

 

[csharp][/csharp] view plaincopy在CODE上查看代码片派生到我的代码片

  1. internal class SecureRedirection
  2.     {
  3.         public HttpContext Context { get; set; }
  4.         public string TargetUrl { get; set; }
  5.         public SecureRedirection(HttpContext context, string targetUrl)
  6.         {
  7.             Context = context;
  8.             TargetUrl = targetUrl;
  9.         }
  10.         public void Go()
  11.         {
  12.             Context.Response.StatusCode = 301;
  13.             Context.Response.RedirectLocation = TargetUrl ?? Context.Request.Url.AbsoluteUri.Replace(“http://”, “https://”);
  14.             Context.Response.End();
  15.         }
  16.     }

将HTTP请求301重定向成HTTPS请求

 

 

总结

如果面对复杂的使用HTTPS的需求,这个框架能基本满足所有需要。当然由于我没有需求使用正则表达式验证,所以没有添加。但非常简单,可以在matchType里加一个“Regex”选项,创建一个新PathMather并在IsMatch中实现正则验证就行了。

标签