对于大型站点,庞大的主题和帖子数据,分表放到一个主题表和一个帖子表中,已经成为影响性能的一个因素。因此,急需进行分表操作来避免 MySQL 对于大数据表的频繁操作。
1、后台分表
Disucz! X2 后台重新调整了分表的机制,使得分表效率和后期站点性能得到提升。具体分表设置在 后台 -> 站长 -> 主题分表(帖子分表)。
1)主题分表
主题分表分为两种类型,一种为主表,一种为存档表。主表只有一个,存档表可以有多个。我们进行分表操作,首先进行创建存档表的操作,然后进行主题移动,将指定条件的主题移动到存档表中。
a、创建存档表
打开 source/admincp/admincp_threadsplit.php 文件,找到创建存档表的条件分支
- elseif($operation == 'addnewtable')
复制代码
首先获取当前最大的主题表 id ,然后根据 forum_thread 的建表语句,生成新的存档表(id + 1),最后更新缓存。
b、主题移动
存档表建好后,下一步就是将主题移动到这个存档表中。在选择主题的时候,可以根据提供的搜索条件,特别是“更多选项”中的搜索条件,来转移符合条件的主题。这里主要是一个搜索的过程,转移数据的过程使用 REPLACE INTO … SELECT...FROM... 语句,比较简单。
2)帖子分表
帖子分表也是要分成两步,第一步先创建帖子分表,第二步转移数据。
打开 source/admincp/admincp_postsplit.php 文件,找到帖子分表的条件分支
- elseif($operation == 'split')
复制代码
如果是对主表进行分表操作,主表必须要大于400M,见下面的条件判断
- if($status && ((!$tableid && $status['Data_length'] > 400 * 1048576) || ($tableid && $status['Data_length'])))
复制代码
在站长提交分表表单后,程序会先根据 getmaxposttableid 函数获取当前帖子表最大的 id ,然后根据已有的帖子表结构,创建新分表,并更新缓存等信息。创建成功后,开始转移数据的操作。找到条件分支
- elseif($operation == 'movepost')
复制代码
,开始转移数据的操作。当从主表中转移数据时,是根据主题表中最后回复时间正序排列的主题 tid 来获取帖子数据的。
- $query = DB::query("SELECT tid FROM ".DB::table($table)." WHERE posttableid='0' AND displayorder>='0' ORDER BY lastpost LIMIT 0, 1000");
复制代码
然后,利用 movedate 函数进行转移数据。
当从从表中转移数据时,是根据给定帖子表的 id,获取此表中first=1的帖子所属 tid,
- $query = DB::query("SELECT tid FROM ".DB::table(getposttable($fromtableid))." WHERE `first`='1' LIMIT 0, 1000")
复制代码
然后利用 movedate 函数进行转移数据。
在 movedate 函数中,根据获取到的 tid ,将属于此 tid 的帖子,利用 INSERT INTO … SELECT … FROM ...来转移数据。在此过程中,更新主题表中 posttableid 这个字段,来标识帖子的存储表。
2、主题列表页分表读取
在主题列表页,只能看到主题主表中的主题。存档表中的主题都在存档区。
在这部分的代码(source/module/forum/forum_forumdisplay.php)中,所有涉及到的主题表都以 $threadtable 这个变量代替,$threadtable 这个变量的获取,又是根据用户是否查看存档区的标识 archiveid 来判定。
- $threadtable = $_G['gp_archiveid'] && in_array($_G['gp_archiveid'], $threadtableids) ? "forum_thread_{$_G['gp_archiveid']}" : 'forum_thread';
复制代码
当用户选择非存档内容时,archiveid = 0 或者不存在,这时,直接从 forum_thread 主表来读取主题列表。当用户选择存档内容时,archiveid = 1(1 表示存档表的 id,如果查看 id 为 2 的存档表,archiveid = 2),程序会根据 archiveid 来判断从哪个存档表中去获取主题列表。
3、帖子内容页分表读取
当用户浏览帖子内容页时,程序首先利用 loadforum 函数来获取当前的主题信息。在 loadforum 函数中,
- $_G['thread'] = get_thread_by_tid($tid, '*', $addcondiction, $archiveid);
复制代码
根据提供的 tid,get_thread_by_tid 函数到主表和存档表中分表去查找,直到找到对应的主题信息。
在 source/module/forum/forum_viewthread.php 文件中,根据
- $thread = & $_G['forum_thread'];
复制代码
- $threadtable = $thread['threadtable'];
- $posttableid = $thread['posttableid'];
- $posttable = $thread['posttable'];
复制代码
这两句来判定该主题应该去哪个帖子表中去获取帖子内容列表。
4、发新主题
发表新主题时,直接往主题主表中插入数据,对应的 posttableid = 0。然后,当插入帖子数据时,通过 insertpost 函数将数据插入帖子表中。
在 insertpost 函数中,会先去判断所属主题的 posttableid 值,得到目标帖子表,然后再往该帖子表中插入帖子数据。
5、发新回复
只有在主表的主题才能回复,因此,直接根据传递的tid去获取目标帖子表,然后插入数据。这个跟发新主题时,插入帖子内容过程相同。
6、编辑帖子
同样,只有在主表中的主题的帖子才能被编辑,因此,主题都在 forum_thread 表中。需要获取的是该主题的帖子在哪个帖子表中。打开 source/include/post/post_editpost.php 文件,找到
- $posttable = getposttablebytid($_G['tid']);
复制代码
程序在开始,通过这条语句来获取目标帖子表。在 getposttablebytid 函数中,程序根据 tid ,逐个主题表进行查找,找到对应的主题信息,获取目标帖子表,然后指向后续的编辑帖子操作。
8、取消存档
存在存档区的主题,如果想取消存档,可以通过页面底部的“取消存档”来执行。
打开 source/include/topicadmin/topicadmin_restore.php 文件,可以看到取消存档,实际上仅是将放在存档表中的主题移动到了主表中。同样,存档表的获取还是通过 archiveid 这个参数来决定的。
- $threadtable = $archiveid ? "forum_thread_$archiveid" : 'forum_thread';
复制代码
从这可以看出,存档的概念仅限于主题,帖子无所谓存档的概念。
目前找到一种途径可以顺利把 Fireworks 或 Photoshop 的矢量图导出 / 转换为 CorelDRAW 的曲线:
Fireworks 中的路径如果不需要后期改变形状,最好都能够组合路径,以减少图层数,或者新建子层,把它们都拖进去。
- 在 Fireworks 中,另存为,选择 *.psd 格式
- 在 Photoshop 中,选中图层或子层,右键,复制 SVG
- 在桌面上新建一个文本文档,打开,粘贴,保存,关闭
- 将该文本文档更改后缀名为 .svg(此步可忽略)
- 将该文档拖到 CorelDRAW 窗口中即可
将字符串作为文本文档输出:
Response.AddHeader("Content-Disposition", "attachment; filename=文件名.txt"); Response.Write(字符串内容); Response.End();
直接提供服务器文件下载:
FileInfo thefile = new FileInfo(path); Response.Clear(); Response.ClearHeaders(); Response.Buffer = false; Response.ContentType = "application/octet-stream"; Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode("刮刮卡参与") + id + ".csv"); Response.AppendHeader("Content-Length", thefile.Length.ToString()); Response.WriteFile(thefile.FullName); Response.Flush(); Response.End();
输出使用 NPOI 创建的 Excel(MemoryStream):
HSSFWorkbook book = new HSSFWorkbook(); …… MemoryStream ms = new MemoryStream(); book.Write(ms); Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}.xls", scene.d.drama + " " + scene.s.time_show.ToString("yyyy年MM月dd日HH时mm分"))); Response.BinaryWrite(ms.ToArray()); Response.End(); book = null; ms.Close(); ms.Dispose();
最后,如果要指定文件编码,加上这句就行:
Response.ContentEncoding = Encoding.xxx;
各位站长好:
根据苹果相关通知,从2017年1月1日起,所有上架AppStore的应用必须支持https协议。
仍然采用HTTP传输的站点APP,将无法在AppStore被用户下载使用,也无法进行升级更新等工作。
官方视频
https://developer.apple.com/videos/play/wwdc2016/706/
相关新闻
http://www.chinaz.com/news/2016/1028/602635.shtml
根据AppStore审核要求,站长需要在2017年1月1日之前,在APP服务器全面部署https。
尽管不升级支持https后果严重,但诸位也不必太过担心,马甲根据要求为各位提供一份服务器升级https的技术文档,供您参考。
https的优点:
1. 相对于http,https可以确保数据在网络传输过程中不被篡改(如禁止运营商插入广告),同时可以提升网站的安全性。
2. iOS可以实现微信内部浏览器直接启动并打开App对应页面。
APP网站升级https步骤:
1. 为APP域名申请购买SSL证书(可选免费型);
2. 将SSL证书部署到APP站点。
https证书申请方法:
1. 进入阿里云(独立服务器客户可注册一个阿里云账号,无须购买阿里云主机)https证书申请页面 https://www.aliyun.com/product/security/markets/aliyun/product/cas
2. 购买https证书,选择免费类型,点击购买(无需实际付款)
3. 购买完成后,进入控制台-CA证书服务页面,找到证书订单,点击“补全”
4. 填写证书对应的域名信息,免费证书只能用于一个域名(请填写完整域名例如:test.magapp.cc 而不是 magapp.cc)
5. 继续补全证书信息,注意域名验证类型选择DNS,邮箱填写自己常用邮箱即可,稍后系统会往邮箱发送域名解析信息。
6. 下一步生成证书请求文件(CSR),这里建议选择“系统生成CSR”,点击右侧创建,创建完成后,点击提交审核,开始申请https证书。
7. 稍后系统会向邮箱发送一份该邮件,邮件包含需要在域名管理后台解析的信息。
8. 到域名管理后台添加新的域名解析,注意解析类型为CNAME
9. 添加新域名解析完成后,系统会对您的申请进行审核(审核时间在几分钟到几个小时不确定),如果审核成功系统会为你签发https证书,失败也会有相关原因说明,如果失败可根据提示重新申请。
10. https证书申请成功后,下一步就可以下载并部署到APP服务器。
11. 点击下载后,可以根据阿里云提供的部署文档,进行相关的服务器部署工作。
12. 部署完成后,验证是否部署成功
第一步:使用https协议访问域名是否能正常访问,例如 https://test.magapp.cc
第二步:在线检测域名是否满足苹果审核要求,网址为:https://www.qcloud.com/product/ssl.html#userDefined10
填写自己申请https的域名
如果域名检测各项满足会显示如下图所示
部署注意事项:
1. https使用的是443端口而不是默认的80端口,需要在wdcp安全管理-iptables开启443端口。
2. https免费证书有效期为一年,请各位站长作好记录,提前重新申请。
3. 站点从http转到https完全过渡需要一段时间,建议在部署时站点同时支持http和https。
4. 部署过程遇到任何问题,可联系您的专属运维人员。
MAGAPP技术部
Repeater
索引 <%# Container.ItemIndex %>
输出项 <%# Container.DataItem %> 或 <%# GetDataItem() %>
ListView
索引 <%# Container.DataItemIndex %>
输出项 <%# GetDataItem() %>
以 fiels 的内容为 <span style="color: red;">你好</span> 为例:
语法 | HTML 源代码输出结果 | 浏览器展示结果 | 备注 |
<%# Eval("field") %> | <span style="color: red;">你好</span> | 你好 | 一般绑定 |
<%#: Eval("field") %> | <span style="color: red;">你好</span> | <span style="color: red;">你好</span> | HtmlEncode 效果绑定 |
windows 7和vista提高的系统的安全性,同时需要明确指定“以管理员身份运行”才可赋予被运行软件比较高级的权限,比如访问注册表等。否则,当以普通身份运行的程序需要访问较高级的系统资源时,将会抛出异常。
如何让程序在启动时,自动要求“管理员”权限了,我们只需要修改app.manifest文件中的配置项即可。
app.manifest文件默认是不存在的,我们可以通过以下操作来自动添加该文件。
(1)进入项目属性页。
(2)选择“安全性”栏目。
(3)将“启用ClickOnce安全设置”勾选上。
现在,在Properties目录下就自动生成了app.manifest文件,打开该文件,将trustInfo/security/requestedPrivileges节点的requestedExecutionLevel的level的值修改为requireAdministrator即可。如下所示:
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
</requestedPrivileges>
记住,如果不需要ClickOnce,可以回到项目属性页将“启用ClickOnce安全设置”不勾选。
接下来,重新编译你的程序就OK了。
string str = "abcd某某某"; int i = System.Text.Encoding.GetEncoding("GB2312").GetBytes(str).Length; int j = str.Length;
问:i = j =
答:i = 10, j = 7
成员名称 | 说明 |
---|---|
Accepted |
等效于 HTTP 状态 202。 Accepted 指示请求已被接受做进一步处理。 |
Ambiguous |
等效于 HTTP 状态 300。 Ambiguous 指示请求的信息有多种表示形式。默认操作是将此状态视为重定向,并遵循与此响应关联的 Location 标头的内容。 |
BadGateway |
等效于 HTTP 状态 502。 BadGateway 指示中间代理服务器从另一代理或原始服务器接收到错误响应。 |
BadRequest |
等效于 HTTP 状态 400。 BadRequest 指示服务器未能识别请求。如果没有其他适用的错误,或者不知道准确的错误或错误没有自己的错误代码,则发送 BadRequest。 |
Conflict |
等效于 HTTP 状态 409。 Conflict 指示由于服务器上的冲突而未能执行请求。 |
Continue |
等效于 HTTP 状态 100。 Continue 指示客户端可能继续其请求。 |
Created |
等效于 HTTP 状态 201。 Created 指示请求导致在响应被发送前创建新资源。 |
ExpectationFailed |
等效于 HTTP 状态 417。 ExpectationFailed 指示服务器未能符合 Expect 头中给定的预期值。 |
Forbidden |
等效于 HTTP 状态 403。 Forbidden 指示服务器拒绝满足请求。 |
Found |
等效于 HTTP 状态 302。 Found 指示请求的信息位于 Location 头中指定的 URI 处。接收到此状态时的默认操作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求将使用 GET 方法。 |
GatewayTimeout |
等效于 HTTP 状态 504。 GatewayTimeout 指示中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时。 |
Gone |
等效于 HTTP 状态 410。 Gone 指示请求的资源不再可用。 |
HttpVersionNotSupported |
等效于 HTTP 状态 505。 HttpVersionNotSupported 指示服务器不支持请求的 HTTP 版本。 |
InternalServerError |
等效于 HTTP 状态 500。 InternalServerError 指示服务器上发生了一般错误。 |
LengthRequired |
等效于 HTTP 状态 411。 LengthRequired 指示缺少必需的 Content-length 头。 |
MethodNotAllowed |
等效于 HTTP 状态 405。 MethodNotAllowed 指示请求的资源上不允许请求方法(POST 或 GET)。 |
Moved |
等效于 HTTP 状态 301。 Moved 指示请求的信息已移到 Location 头中指定的 URI 处。接收到此状态时的默认操作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求将使用 GET 方法。 |
MovedPermanently |
等效于 HTTP 状态 301。 MovedPermanently 指示请求的信息已移到 Location 头中指定的 URI 处。接收到此状态时的默认操作为遵循与响应关联的 Location 头。 |
MultipleChoices |
等效于 HTTP 状态 300。 MultipleChoices 指示请求的信息有多种表示形式。默认操作是将此状态视为重定向,并遵循与此响应关联的 Location 标头的内容。 |
NoContent |
等效于 HTTP 状态 204。 NoContent 指示已成功处理请求并且响应已被设定为无内容。 |
NonAuthoritativeInformation |
等效于 HTTP 状态 203。 NonAuthoritativeInformation 指示返回的元信息来自缓存副本而不是原始服务器,因此可能不正确。 |
NotAcceptable |
等效于 HTTP 状态 406。 NotAcceptable 指示客户端已用 Accept 头指示将不接受资源的任何可用表示形式。 |
NotFound |
等效于 HTTP 状态 404。 NotFound 指示请求的资源不在服务器上。 |
NotImplemented |
等效于 HTTP 状态 501。 NotImplemented 指示服务器不支持请求的函数。 |
NotModified |
等效于 HTTP 状态 304。 NotModified 指示客户端的缓存副本是最新的。未传输此资源的内容。 |
OK |
等效于 HTTP 状态 200。 OK 指示请求成功,且请求的信息包含在响应中。这是最常接收的状态代码。 |
PartialContent |
等效于 HTTP 状态 206。 PartialContent 指示响应是包括字节范围的 GET 请求所请求的部分响应。 |
PaymentRequired |
等效于 HTTP 状态 402。保留 PaymentRequired 以供将来使用。 |
PreconditionFailed |
等效于 HTTP 状态 412。 PreconditionFailed 指示为此请求设置的条件失败,且无法执行此请求。条件是用条件请求标头(如 If-Match、If-None-Match 或 If-Unmodified-Since)设置的。 |
ProxyAuthenticationRequired |
等效于 HTTP 状态 407。 ProxyAuthenticationRequired 指示请求的代理要求身份验证。Proxy-authenticate 头包含如何执行身份验证的详细信息。 |
Redirect |
等效于 HTTP 状态 302。 Redirect 指示请求的信息位于 Location 头中指定的 URI 处。接收到此状态时的默认操作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求将使用 GET 方法。 |
RedirectKeepVerb |
等效于 HTTP 状态 307。 RedirectKeepVerb 指示请求信息位于 Location 头中指定的 URI 处。接收到此状态时的默认操作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求还将使用 POST 方法。 |
RedirectMethod |
等效于 HTTP 状态 303。作为 POST 的结果,RedirectMethod 将客户端自动重定向到 Location 头中指定的 URI。用 GET 生成对 Location 标头所指定的资源的请求。 |
RequestedRangeNotSatisfiable |
等效于 HTTP 状态 416。 RequestedRangeNotSatisfiable 指示无法返回从资源请求的数据范围,因为范围的开头在资源的开头之前,或因为范围的结尾在资源的结尾之后。 |
RequestEntityTooLarge |
等效于 HTTP 状态 413。 RequestEntityTooLarge 指示请求太大,服务器无法处理。 |
RequestTimeout |
等效于 HTTP 状态 408。 RequestTimeout 指示客户端没有在服务器期望请求的时间内发送请求。 |
RequestUriTooLong |
等效于 HTTP 状态 414。 RequestUriTooLong 指示 URI 太长。 |
ResetContent |
等效于 HTTP 状态 205。 ResetContent 指示客户端应重置(或重新加载)当前资源。 |
SeeOther |
等效于 HTTP 状态 303。作为 POST 的结果,SeeOther 将客户端自动重定向到 Location 头中指定的 URI。用 GET 生成对 Location 标头所指定的资源的请求。 |
ServiceUnavailable |
等效于 HTTP 状态 503。 ServiceUnavailable 指示服务器暂时不可用,通常是由于过多加载或维护。 |
SwitchingProtocols |
等效于 HTTP 状态 101。 SwitchingProtocols 指示正在更改协议版本或协议。 |
TemporaryRedirect |
等效于 HTTP 状态 307。 TemporaryRedirect 指示请求信息位于 Location 头中指定的 URI 处。接收到此状态时的默认操作为遵循与响应关联的 Location 头。原始请求方法为 POST 时,重定向的请求还将使用 POST 方法。 |
Unauthorized |
等效于 HTTP 状态 401。 Unauthorized 指示请求的资源要求身份验证。WWW-Authenticate 头包含如何执行身份验证的详细信息。 |
UnsupportedMediaType |
等效于 HTTP 状态 415。 UnsupportedMediaType 指示请求是不支持的类型。 |
Unused |
等效于 HTTP 状态 306。 Unused 是未完全指定的 HTTP/1.1 规范的建议扩展。 |
UpgradeRequired |
等效于 HTTP 状态 426。 UpgradeRequired 指示客户端应切换为诸如 TLS/1.0 之类的其他协议。 |
UseProxy |
等效于 HTTP 状态 305。 UseProxy 指示请求应使用位于 Location 头中指定的 URI 的代理服务器。 |
苹果宣布 2017 年 1 月 1 日开始所有上架的应用必须启用 ATS 安全传输功能。ATS 要求服务器必须支持传输层安全(TLS)协议 1.2 以上版本;证书必须使用 SHA256 或更高的哈希算法签名;必须使用 2048 位以上 RSA 密钥或 256 位以上 ECC 算法等等,不满足条件的证书,ATS 都会拒绝连接。查看具体要求
微信小程序进入开发公测阶段,同样要求提供 HTTPS 方式安全连接。
证书类型对比
DV SSL 域名验证型 | OV SSL 组织验证型 | EV SSL 扩展验证型 | ||
申请条件 | 申请对象 | 个人 / 企业 | 企业 | 企业 |
证明域名所有权 | √ | √ | √ | |
价格 | 免费 / 低 | 中 | 高 | |
提交审核 | 提交资料 | 邮箱、姓名、手机等 | DV 所需资料以及: 组织机构资料(企业执照)等 | OV 所需资料以及: 法律相关文件 |
审核时间 | 自动审核 1小时内 | 人工审核 3~5工作日 | 人工审核 3~5工作日 | |
可信标识 | 地址栏挂锁 | √ | √ | √ |
地址栏公司名称 | × | × | √ | |
绿色地址栏(IE) | × | × | √ | |
保护范围 | 单域名 | √ | √ | √ |
多域名 | √ | √ | √ | |
通配符/泛域名 | √ | √ | × | |
推荐用途 | 个人及小型网站 | 一般组织或中小型企业 | 金融、电商、大型企业或受信组织 |
* 表格中,单域名指单个子域名(如:123.abc.com),多域名指多个子域名(可以不属于同一个顶级域名,如:123.abc.com / 456.abc.com / 456.def.com),通配符指单个顶级域名的所有子域名(如:*.abc.com)。
* 若 https 的网页中包含 http 资源,则地址栏的锁可能会消失。
* 浏览器上点击地址栏的锁可以查看具体的证书详情。
证书颁发机构(CA)
机构 | 简介 | 谁在用 |
Let's Encrypt | 公益组织,免费,每 90 天续约 | 越来越多的中小网站 |
Symantec | 赛门铁克 | 百度、支付宝、阿里云、Apple(EV)、微软 |
GlobalSign | 公众信任服务行业的领头羊 | 淘宝、天猫(OV)、阿里云、京东(OV) |
GeoTrust | 全球第二大? | 微信 |
Comodo | 价格实惠 | |
GoDaddy | 全球互联网域名注册商 | |
DigiCert | 不颁发 DV,在非 DV 市场份额中是老大 | Facebook、Twitter(EV)、Mozilla(EV)、GitHub(EV)等 |
沃通 WoSign | 国产 | 360搜索(EV) |
Other |
* 赛门铁克收购了 VeriSign,VeriSign 又收购了 GeoTrust,所以 Symantec 和 GeoTrust 在 SSL 认证服务上就不知道是什么关系了,请自行百度。
* 代理商也可以购买,或许价格优惠,或许申请方便,如:阿里云、腾讯云等,甚至上淘宝购买。
* 查看:Netcraft 统计的市场份额
* 网上说使用 Let's Encrypt 的 SSL 在遇到国内第三方 DNS 解析服务时会超时,我认为只是在申请证书时偶尔超时(DNS query timed out),重试即可,证书部署后访问网站时应该没有问题,请知情者告知实情。
下一步
上一篇介绍了如何创建用于 https 的 SSL 证书,本文讲述如何将创建好的 SSL 证书导入到 Windows,并在 IIS 中部署 HPPTS 的访问。
导入证书
GetSSL 整理的安装方法合集:https://www.getssl.cn/support/ssl安装教程/
下面介绍另一种方法:
准备好 pfx 格式的证书和密码。
开始 -> 运行 -> MMC
点击菜单栏的“添加/删除管理单元”,选择证书,添加,“本地计算机”或“计算机帐户”
左侧展开证书,个人,右键,所有任务,导入,键入密码,选择“根据证书类型,自动选择证书存储”
绑定网站域名
打开 IIS 管理器,选择相应的网站,“绑定”,添加,类型为“https”,选择证书
这样网站就能以 https:// 方式访问了
实现 http 自动跳转 https
方案一:推荐
打开 ASP.NET 网站,如果没有 Global.asax 则添加全局应用程序类
在 Application_BeginRequest() 方法中添加以下代码:
if (!Request.IsLocal && !Request.IsSecureConnection)
{
if (Request.HttpMethod == System.Net.WebRequestMethods.Http.Get || Request.HttpMethod == System.Net.WebRequestMethods.Http.Head)
{
Uri uri = Request.Url;
Response.Redirect("https://" + uri.Authority + uri.PathAndQuery + uri.Fragment);
HttpContext.Current.ApplicationInstance.CompleteRequest();
}
}
Response.RedirectPermanent 是 301 永久
Response.Redirect 是 302 临时
Webform 貌似没有 303、307 的 Redirect,可以判断 Method 来分别处理。
MVC 中可以直接指定状态码,例:
public ActionResult About()
{
HttpContext.Response.AddHeader("Location", "/Home/Contact");
return new HttpStatusCodeResult(307);
}
方案二:
需要“URL 重写”支持,以 IIS 7 为例,模块下载地址:x86 / x64,IIS 8 及以上版本自带该模块
打开“URL 重写”,添加规则,选择空白规则
填写名称,如“Redirect to HTTPS”
与模式匹配,正则表达式
模式:(.*)
添加两个条件:
条件输入“{HTTPS}”,“与模式匹配”,模式“^OFF$”,确定
条件输入“{HTTPS_HOST}”,“与模式不匹配”,模式“^(localhost)”,确定
操作类型“重定向”,
重定向 URL“https://{HTTP_HOST}/{R:1}”
重定向类型:请参考此文,所有请求跳转可选 303,仅 GET/HEAD 请求跳转可选 307(推荐,可防止 POST 请求跳转丢失数据)
这么多步骤,其实最终会在网站 web.config 的 <system.webServer /> 节点下插入以下配置:
<rewrite>
<rules>
<rule name="Redirect to HTTPS" enabled="true" stopProcessing="true">
<match url="(.*)"/>
<conditions>
<add input="{HTTPS}" pattern="^OFF$"/>
<add input="{HTTPS_HOST}" pattern="^(localhost)" negate="true"/>
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}" redirectType="Temporary"/>
</rule>
</rules>
</rewrite>
配置 Web.Release.config 转换语法
作为 ASP.NET 开发者,我们发现,当我们把这段 URL 重写规则复制到项目中的 web.config 后,在 VS 的本地调试中同样会自动跳转到 https://localhost/xxx,这可没法调试了呀。所以只能用 Web.Release.config 来实现本地调试用 http,发布用 https。
<system.webServer /> 节点是针对 IIS 7 的配置,干脆我把整个 <system.webServer /> 从 web.config 剪切到 web.release.config 中,然后给 <system.webServer> 加上属性和值:xdt:Transform="Insert",这样就能实现我们的目的了
详细的用于 Web 应用程序项目部署的 Web.config 转换语法参见此文
验证
最后我们来检查一下配置的对不对:https://www.geocerts.com/ssl_checker
参考资料