2020年5月30日,AddTrust External CA Root 过期,虽然不影响客户端浏览器访问网站,但服务器端调用接口(file_get_contents)会出现问题,原因是证书链中根证书过期(必须使用检测工具检查服务端的证书链,而不是查看客户端浏览器上的证书信息,因为客户端浏览器上看到的的根证书是客户端系统上的根证书,是随着系统自动更新的)。

这里,Windows Server 的 IIS 与 CentOS 中的 nginx 又有所区别,咱们分开来讲:
如何更新 Windows Server 的 IIS 中的网站的根证书?
Windows Server 本身相当于一个客户端,会自动更新根证书,只不过 IIS 中的网站证书未同步更新。
打开 IIS,进入对应网站的“绑定”界面,重新绑定即可生效。简单的方法是简单修改主机名,确定,再改回原主机名,确定。

如何更新 CentOS 的 nginx 中的网站的根证书?
nginx 中使用的域名证书(pem 文件),即 conf 文件中设置的 ssl_certificate 路径对应的证书文件,是包含根证书信息的:

因此保留第一段域名证书信息,用新的根证书信息替换掉除第一段的其它内容即可。
| 返回状态 | ASP.NET MVC | ASP.NET Core | ASP.NET Web API |
| 200 视图 | return View(); | return View(); | - |
| 200 带模型的视图 | return View(Model); | return View(Model); | - |
| 200 空内容 | return new EmptyResult(); | return Ok(); | return Ok(); |
| 200 文本 | return Content(string); | return Ok(string); return Content(string); | return Ok(string); return Content(string); |
| 200 JSON | return Json(object); | return Json(T); // 强制 JSON return Ok(T); // 请求时可指定 Content-Type | return Json(T); // 强制 JSON return Ok(T); // 请求时可指定 Content-Type |
| 200 JaveScript | return JavaScript(string script); | ||
| 200 文件 | return File(); | return File(); return PhysicalFile(); | return File(); return PhysicalFile(); |
| 201 已创建 | return Created(location, content); 用于 Post 接口 | ||
| 301 永久跳转 | return RedirectPermanent(url); return RedirectToActionPermanent(url); return RedirectToRoutePermanent(object); | return RedirectPermanent(url); return RedirectToActionPermanent(url); return RedirectToRoutePermanent(object); | |
| 302 临时跳转 | return Redirect(url); return RedirectToAction(url); return RedirectToRoute(object); | return Redirect(url); return RedirectToAction(url); return RedirectToRoute(object); | return Redirect(url); return RedirectToRoute(object); |
| 400 错误的请求 | return new HttpStatusCodeResult(System.Net.HttpStatusCode.BadRequest); | return BadRequest(msg); | return BadRequest(msg); |
| 401 未授权 | return new HttpUnauthorizedResult("描述"); | return Unauthorized(msg); | return Unauthorized(msg); |
| 404 找不到文件或目录 | return HttpNotFound(); | return NotFound(msg); | return NotFound(msg); |
| 直接指定状态码 | return new HttpStatusCodeResult(HttpStatusCode.*); public enum HttpStatusCode { // // 摘要: // 等效于 HTTP 状态 100。 System.Net.HttpStatusCode.Continue 指示客户端可能继续其请求。 Continue = 100, // // 摘要: // 等效于 HTTP 状态 101。 System.Net.HttpStatusCode.SwitchingProtocols 指示正在更改协议版本或协议。 SwitchingProtocols = 101, // // 摘要: // 等效于 HTTP 状态 200。 System.Net.HttpStatusCode.OK 指示请求成功,且请求的信息包含在响应中。 这是最常接收的状态代码。 OK = 200, // // 摘要: // 等效于 HTTP 状态 201。 System.Net.HttpStatusCode.Created 指示请求导致在响应被发送前创建新资源。 Created = 201, // // 摘要: // 等效于 HTTP 状态 202。 System.Net.HttpStatusCode.Accepted 指示已接受请求做进一步处理。 Accepted = 202, // // 摘要: // 等效于 HTTP 状态 203。 System.Net.HttpStatusCode.NonAuthoritativeInformation 指示返回的元信息来自缓存副本而不是原始服务器,因此可能不正确。 NonAuthoritativeInformation = 203, // // 摘要: // 等效于 HTTP 状态 204。 System.Net.HttpStatusCode.NoContent 指示已成功处理请求并且响应已被设定为无内容。 NoContent = 204, // // 摘要: // 等效于 HTTP 状态 205。 System.Net.HttpStatusCode.ResetContent 指示客户端应重置(而非重新加载)当前资源。 ResetContent = 205, // // 摘要: // 等效于 HTTP 状态 206。 System.Net.HttpStatusCode.PartialContent 指示响应是包括字节范围的 GET 请求所请求的部分响应。 PartialContent = 206, // // 摘要: // 等效于 HTTP 状态 300。 System.Net.HttpStatusCode.MultipleChoices 指示请求的信息有多种表示形式。 默认操作是将此状态视为重定向,并遵循与此响应关联的 // Location 标头的内容。 MultipleChoices = 300, // // 摘要: // 等效于 HTTP 状态 300。 System.Net.HttpStatusCode.Ambiguous 指示请求的信息有多种表示形式。 默认操作是将此状态视为重定向,并遵循与此响应关联的 // Location 标头的内容。 Ambiguous = 300, // // 摘要: // 等效于 HTTP 状态 301。 System.Net.HttpStatusCode.MovedPermanently 指示请求的信息已移到 Location // 头中指定的 URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 MovedPermanently = 301, // // 摘要: // 等效于 HTTP 状态 301。 System.Net.HttpStatusCode.Moved 指示请求的信息已移到 Location 头中指定的 URI // 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求将使用 GET 方法。 Moved = 301, // // 摘要: // 等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Found 指示请求的信息位于 Location 标头中指定的 URI // 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求将使用 GET 方法。 Found = 302, // // 摘要: // 等效于 HTTP 状态 302。 System.Net.HttpStatusCode.Redirect 指示请求的信息位于 Location 标头中指定的 // URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求将使用 GET 方法。 Redirect = 302, // // 摘要: // 等效于 HTTP 状态 303。 作为 POST 的结果,System.Net.HttpStatusCode.SeeOther 将客户端自动重定向到 Location // 标头中指定的 URI。 用 GET 生成对 Location 标头所指定的资源的请求。 SeeOther = 303, // // 摘要: // 等效于 HTTP 状态 303。 作为 POST 的结果,System.Net.HttpStatusCode.RedirectMethod 将客户端自动重定向到 // Location 标头中指定的 URI。 用 GET 生成对 Location 标头所指定的资源的请求。 RedirectMethod = 303, // // 摘要: // 等效于 HTTP 状态 304。 System.Net.HttpStatusCode.NotModified 指示客户端的缓存副本是最新的。 未传输此资源的内容。 NotModified = 304, // // 摘要: // 等效于 HTTP 状态 305。 System.Net.HttpStatusCode.UseProxy 指示请求应使用位于 Location 标头中指定的 // URI 的代理服务器。 UseProxy = 305, // // 摘要: // 等效于 HTTP 状态 306。 System.Net.HttpStatusCode.Unused 是未完全指定的 HTTP/1.1 规范的建议扩展。 Unused = 306, // // 摘要: // 等效于 HTTP 状态 307。 System.Net.HttpStatusCode.TemporaryRedirect 指示请求信息位于 Location // 标头中指定的 URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求还将使用 POST // 方法。 TemporaryRedirect = 307, // // 摘要: // 等效于 HTTP 状态 307。 System.Net.HttpStatusCode.RedirectKeepVerb 指示请求信息位于 Location // 标头中指定的 URI 处。 接收到此状态时的默认操作为遵循与响应关联的 Location 标头。 原始请求方法为 POST 时,重定向的请求还将使用 POST // 方法。 RedirectKeepVerb = 307, // // 摘要: // 等效于 HTTP 状态 400。 System.Net.HttpStatusCode.BadRequest 指示服务器未能识别请求。 如果没有其他适用的错误,或者不知道准确的错误或错误没有自己的错误代码,则发送 // System.Net.HttpStatusCode.BadRequest。 BadRequest = 400, // // 摘要: // 等效于 HTTP 状态 401。 System.Net.HttpStatusCode.Unauthorized 指示请求的资源要求身份验证。 WWW-Authenticate // 标头包含如何执行身份验证的详细信息。 Unauthorized = 401, // // 摘要: // 等效于 HTTP 状态 402。 保留 System.Net.HttpStatusCode.PaymentRequired 以供将来使用。 PaymentRequired = 402, // // 摘要: // 等效于 HTTP 状态 403。 System.Net.HttpStatusCode.Forbidden 指示服务器拒绝满足请求。 Forbidden = 403, // // 摘要: // 等效于 HTTP 状态 404。 System.Net.HttpStatusCode.NotFound 指示请求的资源不在服务器上。 NotFound = 404, // // 摘要: // 等效于 HTTP 状态 405。 System.Net.HttpStatusCode.MethodNotAllowed 指示请求的资源上不允许请求方法(POST // 或 GET)。 MethodNotAllowed = 405, // // 摘要: // 等效于 HTTP 状态 406。 System.Net.HttpStatusCode.NotAcceptable 指示客户端已用 Accept 标头指示将不接受资源的任何可用表示形式。 NotAcceptable = 406, // // 摘要: // 等效于 HTTP 状态 407。 System.Net.HttpStatusCode.ProxyAuthenticationRequired 指示请求的代理要求身份验证。 // Proxy-authenticate 标头包含如何执行身份验证的详细信息。 ProxyAuthenticationRequired = 407, // // 摘要: // 等效于 HTTP 状态 408。 System.Net.HttpStatusCode.RequestTimeout 指示客户端没有在服务器期望请求的时间内发送请求。 RequestTimeout = 408, // // 摘要: // 等效于 HTTP 状态 409。 System.Net.HttpStatusCode.Conflict 指示由于服务器上的冲突而未能执行请求。 Conflict = 409, // // 摘要: // 等效于 HTTP 状态 410。 System.Net.HttpStatusCode.Gone 指示请求的资源不再可用。 Gone = 410, // // 摘要: // 等效于 HTTP 状态 411。 System.Net.HttpStatusCode.LengthRequired 指示缺少必需的 Content-length // 标头。 LengthRequired = 411, // // 摘要: // 等效于 HTTP 状态 412。 System.Net.HttpStatusCode.PreconditionFailed 指示为此请求设置的条件失败,且无法执行此请求。条件是用条件请求标头(如 // If-Match、If-None-Match 或 If-Unmodified-Since)设置的。 PreconditionFailed = 412, // // 摘要: // 等效于 HTTP 状态 413。 System.Net.HttpStatusCode.RequestEntityTooLarge 指示请求太大,服务器无法处理。 RequestEntityTooLarge = 413, // // 摘要: // 等效于 HTTP 状态 414。 System.Net.HttpStatusCode.RequestUriTooLong 指示 URI 太长。 RequestUriTooLong = 414, // // 摘要: // 等效于 HTTP 状态 415。 System.Net.HttpStatusCode.UnsupportedMediaType 指示请求是不受支持的类型。 UnsupportedMediaType = 415, // // 摘要: // 等效于 HTTP 状态 416。 System.Net.HttpStatusCode.RequestedRangeNotSatisfiable 指示无法返回从资源请求的数据范围,因为范围的开头在资源的开头之前,或因为范围的结尾在资源的结尾之后。 RequestedRangeNotSatisfiable = 416, // // 摘要: // 等效于 HTTP 状态 417。 System.Net.HttpStatusCode.ExpectationFailed 指示服务器未能符合 Expect // 标头中给定的预期值。 ExpectationFailed = 417, // // 摘要: // 等效于 HTTP 状态 426。 System.Net.HttpStatusCode.UpgradeRequired 指示客户端应切换为诸如 TLS/1.0 // 之类的其他协议。 UpgradeRequired = 426, // // 摘要: // 等效于 HTTP 状态 500。 System.Net.HttpStatusCode.InternalServerError 指示服务器上发生了一般错误。 InternalServerError = 500, // // 摘要: // 等效于 HTTP 状态 501。 System.Net.HttpStatusCode.NotImplemented 指示服务器不支持请求的函数。 NotImplemented = 501, // // 摘要: // 等效于 HTTP 状态 502。 System.Net.HttpStatusCode.BadGateway 指示中间代理服务器从另一代理或原始服务器接收到错误响应。 BadGateway = 502, // // 摘要: // 等效于 HTTP 状态 503。 System.Net.HttpStatusCode.ServiceUnavailable 指示服务器暂时不可用,通常是由于过多加载或维护。 ServiceUnavailable = 503, // // 摘要: // 等效于 HTTP 状态 504。 System.Net.HttpStatusCode.GatewayTimeout 指示中间代理服务器在等待来自另一个代理或原始服务器的响应时已超时。 GatewayTimeout = 504, // // 摘要: // 等效于 HTTP 状态 505。 System.Net.HttpStatusCode.HttpVersionNotSupported 指示服务器不支持请求的 // HTTP 版本。 HttpVersionNotSupported = 505 } |
附 ASP.NET Form 相关:
400:
Response.StatusCode = 400;
Response.Write("错误提示");
Response.End();经 2020.02.22 提交工单咨询回复,阿里云控制台暂无法针对 CDN 的域名或 OSS 的 Bucket 来区分费用账单,但 ECS、RDS 可根据实例 ID 来查询:

虽然不能准确查询 CDN 各域名的消费情况,但我们可以在 CDN 的统计分析中查询域名排行,从而可以按流量占比再结合 CDN 的总体费用来计算各域名的大致费用:

当然,能把 HTTPS 等增值服务和资源包等因素考虑进去会更加合理。
原标题:为什么Discuz论坛新注册会员不能发帖
1、后台 -> 用户 -> 用户组 -> 新手上路 -> 详情 -> 帖子相关 -> 允许发新话题:是
2、后台 -> 全局 -> 注册与访问 -> 访问控制 -> 新手见习期限(分钟): 0
刚开始,新增了名为 video 的用户群组,新增了名为 tv 的用户帐号,关联到这个群组,是能够在 DS video 中登录的。但今天登录却提示:
帐号或密码有误。请再试一次。

在勾选了这个帐号的所有权限和应用程序仍然无果后,尝试关联到 administrators 群组能正常登录。当然为了安全性,这个群组是不能随便关联的。
查阅了官网关于 DS video 的文档 https://www.synology.com/zh-cn/knowledgebase/Mobile/help/DSvideo,如果登录失败,请进行以下操作:请以 admin(或属于 administrators 群组的用户)的身份登录到 DSM,然后进入控制面板 > 权限以检查用户帐户是否有使用 Video Station 的权限。
既然官方建议使用 administrators 群组,那基本上没有其它的好办法了。
tv 帐号关联到 administrators 群组,并将所有权限“禁止访问”,将除“Video Station”外的所有其它应用程序设置为“拒绝”。
最后,尝试在 DSM 上登录 tv 帐号,提示:
您没有权限使用本项服务。
那就放心了。
本教程教你如何升级 ASP.NET 项目中的 MySql.Data 和服务器安装的 Connector/NET 版本至 8.0.18。
使用 MySQL Application Configuration 升级 MySql.Data
双击打开 .edmx 文件后,解决方案资源管理器上会有 MySQL Application Configuration 的图标。(如果没有,点开“从数据库更新模型”一下即可)

勾选“Use MySQL with Entity Framework”,安装完成。

完成后发现,Nuget 中会自动安装或升级下面两个组件:
MySql.Data 8.0.18
MySql.Data.EntityFramework 8.0.18
并且在 Web.config 中会自动添加以下节点:
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=8.0.18, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>这段代码使 MySql.Data 8.0.18 的项目能够兼容运行在 Connector/NET 6.10.x 环境中。方便我们挨个升级服务器上的项目。
8.0.18 已经不再需要 MySql.Data.Entity 组件了,可以从 Nuget 中手动卸载。
* 若无特殊注明,本文中的“手机”包含平板电脑
判断网页是否在移动设备中打开
Web Form:
public static bool IsMobileDevice
{
get
{
return (HttpContext.Current.Request.Browser?.IsMobileDevice ?? false)
|| (HttpContext.Current.Request.UserAgent?.Contains("Mobile") ?? false);
}
}ASP.NET Core:
好像还没有找到,可能是因为随着响应式布局的流行以及电脑和手机之间的界线越来越不明朗,取消了这个判断?
判断网页是否在微信浏览器中打开(宽松)
Web Form:
public bool IsInWechat
{
get
{
return HttpContext.Current.Request.UserAgent?.Contains("MicroMessenger") ?? false;
}
}ASP.NET Core:
需注入 IHttpContextAccessor
public bool IsInWechat
{
get
{
string ua = httpContextAccessor.HttpContext.Request.Headers[HeaderNames.UserAgent];
return ua?.Contains("MicroMessenger") ?? false;
}
}判断网页是否在微信浏览器中打开(严谨)
使用 JS-SDK 网页授权来判断

使用 myssl.com 检测证书状态,显示握手失败(No FS No SNI):

发现 XP 上的 IE6 和 IE8 均无法访问该站点,原因是 XP 不支持 FS,不支持 SNI。
可以尝试在 IIS 的站点的“绑定”中更改“需要服务器名称指示”来实现正常访问。
步骤参阅:https://xoyozo.net/Blog/Details/wxpay-notify-url-https
当然,前提是服务器上必须已启用相关的协议版本和加密方式(按需启用),建议使用 IISCrypto。
