博客 (122)

I`L8{$7ET7)3BUEREPIWIKB.png

ASP.NET MVC 项目发布到 IIS 上,出现服务器错误“403 - 禁止访问:访问被拒绝”,排除权限设置问题后,原因在于 MVC 的 URL 通常没有扩展名,IIS 并未将其交由 ASP.NET 托管处理。

经过各种找资料,各种尝试后,最终确定:项目本身没有问题,本地运行正常,发布到另一台服务器上正常。

删除服务器 IIS 上的该网站和应用程序池,重新创建网站,恢复正常。原因未知。

xoyozo 7 年前
7,960

在网站开发过程中遇到上传图片等文件的功能,需要在服务器上设置该目录可写入,并且必须防止被上传 .php 等可执行的脚本文件。

根据文件所有者的不同,我们分两种情况讨论:

一、程序上传的用户与执行 PHP 的用户不同(例如程序代码通过 SSH 上传(root 用户),而 PHP 以 www 身份运行)

由于 Linux 上的文件默认权限是 644,目录默认权限是 755,所以在这种情况下,PHP 不能修改 root 上传的程序文件,也不能将客户端上传的图片文件保存到服务器上。

例如我们将客户端上传的文件指定到 /upload/ 目录,那么,

第 1 步,赋予它写入权限:

chmod 777 upload

递归所有子目录请加 -R 参数,但会将文件也更改为 777,赋予了执行权限,这是不建议的。文件若需写入权限请设为 666。

第 2 步,设置该目录下不允许执行 PHP:

我们无法保证客户端上传完全符合我们要求的文件,那么必须禁止任何文件的执行权限。(此处指 PHP 的执行权限,注意与 sh 执行权限的区别,后者由 chmod 命令修改)

nginx 的 .conf 文件配置示例:

location ~ /upload/.*\.(php|php5)?$
{
    deny all;
}

Apache 的 .htaccess 文件配置示例:

RewriteRule upload/(.*).(php)$ – [F]

特别注意:上面的代码必须加在 PHP 引用配置的上方才有效(如 nginx 的 PHP 引用配置 include enable-php-**.conf;

默认 Linux 系统是大小写敏感的,所以规则中的正则表达式无须忽略大小写(但必须与实际的目录或文件名大小写一致),因为 MIME 类型中设置的是小写的 .php,那么类似大写的 .PHP 文件是不被 php-fpm 解释的,结果是被当作普通文本返回到客户端。

提问:有些目录需要设置为可写入,但里面还有正常的 php 文件,禁止执行会有问题吗?(例如 Discuz! 的 config 目录,ThinkPHP 的 Runtime 目录)

解答:以 Discuz! 为例,config 下面虽然有 config_*.php 等配置文件,但这些文件并非直接供客户端浏览,而是被其它 .php 文件引用(include 方式、IO 方式等),当 config 目录禁止执行 PHP 后并不会对它们造成影响。

我们在开发程序的过程中应避免在允许写入的目录下放置直接供客户端浏览的 .php 文件

二、程序上传的用户与执行 PHP 的用户相同(例如程序代码通过 FTP 上传,且和 PHP 一样,都使用 www 用户)

常见于虚拟空间。这种情况下,通过 PHP 上传的文件可以保存到该网站下面的任何目录下(甚至是网站目录之外,即传说中的跨站),原因大家都懂,默认 755 中第一个是“7”,即所有者拥有写入权限。

因此,除了做到上述设置,我们必须严格控制客户端上传文件的保存路径,做到以下几点:

必须更改客户端上传的文件名,而非直接使用原文件名;

不得从客户端文件名获取扩展名,或者只控制允许的后缀名。

最可靠的文件类型判别方式是分析文件签名,参考:文件签名表,以防篡改后缀名欺骗。

举个早期的栗子:上传文件名为 abc.asp;.jpg,未改文件名保存到服务器,浏览器直接访问该文件,IIS 6 当作 abc.asp 来解析。


xoyozo 7 年前
9,193

重点提前看:


https://xoyozo.net/Blog/Details/MySQL-on-Windows




Connector/Net 6.10.4(暂)不支持在 Visual Studio 2015/2017 添加 ADO.NET 实体数据模型时选择 MySQL Data Provider 数据源。并且,在编译项目时会出现“违反了继承安全性规则”的异常。


只能降回 Connector/Net 6.9.10,NuGet 中将 MySql.DataMySql.Data.Entity 用 6.9.10 和 6.10.4 版本皆可(除非遇到下文中提到的异常)。

重新生成或重启 VS 使之生效。


另外,MySql.DataMySql.Data.Entity 6.9.10 可以配合 EnityFrameworkEntityFramework.zh-Hans 6.1.x6.2.0 使用。


MySql.Data 和 MySql.Data.Entity 6.9.9 在创建/更新实体模型向导中会出现闪退,更换为 6.9.10 试试。

或重新安装 Connector/NET 和 MySQL for Visual Studio 并重启电脑试试。

仍然闪退,参此文:https://xoyozo.net/Blog/Details/mysql-for-vs-flashback


重要提醒,如果在添加 EF 模型时报错:

您的项目引用了最新版的实体框架;但是,找不到进行数据连接所需的与此版本兼容的实体框架数据库提供程序。请退出向导,安装兼容提供程序,重新生成您的项目,然后再执行此操作。

那么在菜单中选择:生成 - 清理解决方案,然后直接添加数据模型。如果在添加前生成了项目(bin 目录下有相关 .dll 文件),那么将出现上述错误。


类型“MySql.Data.MySqlClient.MySqlProviderServices”违反了继承安全性规则。派生类型必须与基类型的安全可访问性匹配或者比基类型的安全可访问性低。

将 MySql.Data 和 MySql.Data.Entity 从 6.10.4 退回 6.9.10 版本即可。


以上问题出现在:

VS 15.4.*

VS 15.4.4

VS 15.4.5

----------------

VS 15.5 已经可以在 EF 向导中连接 MySQL 数据库(Connector/Net 6.10.4),但 MySql.Data.Entity 6.10.4 编译仍然出现“违反了继承安全性规则”。另:MySQL 官网下架了 Connector/Net 6.10.4,退回提供 6.9.10 版本。

2017-12-9 发布的 Connector/Net 6.10.5 仍然存在无法在 EF 向导中连接 MySQL 数据源的问题。


服务器上安装 Connector/Net 6.10.4 没有任何问题。


表“TableDetails”中列“IsPrimaryKey”的值为 DBNull。怎么办?

xoyozo 7 年前
6,796

“/”应用程序中的服务器错误。


指定的参数已超出有效值的范围。
参数名: site

说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 

异常详细信息: System.ArgumentOutOfRangeException: 指定的参数已超出有效值的范围。
参数名: site

解决方法:安装 IIS

xoyozo 7 年前
6,432

状态:正在连接 *.*.*.*:21...

状态:连接建立,等待欢迎消息...

响应:220-FileZilla Server

响应:220-written by Tim Kosse (tim.kosse@filezilla-project.org)

响应:220 Please visit https://filezilla-project.org/

命令:AUTH TLS

错误:无法连接到服务器


最终,没有连接到任何服务器。

服务端已允许被动连接,并且 VS 中的网站发布功能正常(FTP 方式),所以从 FileZilla 客户端入手查找问题。

在站点管理器中发现“加密”项,默认是“如果可用,使用显式的 FTP over TLS”,更改为“只使用普通 FTP (不安全)”即可连接。

image.png

这个问题一般出现在换了网络环境的情况下,研究一下 FTP over TLS 很有必要。

打开 FillZilla Server - Edit - Settings - 切换到 FTP over TLS settings 选项卡

FTP over TLS.png

勾选 Enable FTP over TLS support (FTPS),点击 Generate new certificate...

填写需要生成的证书信息,其中“2-Digit country code”和“Save key and certificate to this file”必填,点击 Generate certificate 完成生成证书。

完成配置后 FillZilla Server 已支持 FTPS,启动页上的警告也会随之不见:

Warning: FTP over TLS is not enabled, users cannot securely log in.


xoyozo 7 年前
10,535

Session 有多种存储模式,默认是 InProc,顾名思义是“在进程内”,即在 IIS 中,随网站重启而重启,网站发布后(或改动 .dll 文件)会导致应用重新运行,Session 清空。

Session 可以使用 StateServer 来保存,需要服务器开启 ASP.NET State Service 服务,此种方式要求保存在 Session 的信息必须序列化,然后从 Session 中获取的时候也要反序列化,这就导致性能有略微的损失。

Session 还可以配置为 SQLServer,将 Session 存储在数据库中,同样需要序列化。

当配置为 Custom 时,可以在使用 Memcached、Redis 等第三方缓存技术来实现 Session 的管理,本文不作讨论。

Off 模式即关闭 Session,这种方式如果要实现用户登录功能,就必须依赖 Cookie 等来实现。

下面针对常见的三种模式进行比较:


InProcStateServerSQLServer
存储位置应用进程内ASP.NET State Service 服务SQL Server 数据库
远程存储不支持支持支持
存储格式
任意序列化的序列化的
可能导致重启(丢失)的情况

配置文件中 processModel 标签的 memoryLimit 属性;

Global.asax 或者 Web.config 文件被更改;

Bin 文件夹中的 Web 程序(DLL)被修改;

杀毒软件扫描了一些 .config 文件;

系统资源紧张进行资源回收导致 IIS 进程崩溃或重启等。

ASP.NET State Service 服务停止;-
Session_End() 事件
部署难度简单稍复杂

Web.config 配置示例

(<system.web> 节点内)

<sessionState mode="InProc" /><sessionState mode="StateServer" /><sessionState mode="SQLServer" sqlConnectionString ="data source=x.x.x.x; user id=[user]; password=[pwd]" />

因此,如果你仅仅为了标题所述的“每次发布后丢失 Session”而烦恼,那么推荐使用 StateServer 模式来存储 Session。


注:

如果 Session 的 Key 是在应用启动时随机生成的话,使用 StateServer 和 SQLServer 还是会“丢失” Session。

这是对 Session 的配置,对 Cache 无效。

xoyozo 7 年前
4,822

删除根目录的  PrecompiledApp.config 文件(记得备份)

在 IIS 中“重新启动”该网站

原因:之前应该是发布的时候选了“在发布期间预编译”。发布后,服务器上会有这个预编译相关的文件(包含 bin 目录下也会有),其实 Application_BeginRequest() 方法是执行的,只是重新发布后没有更新而已(猜的)。具体关于发布的配置请自行了解。

xoyozo 7 年前
3,768

在 IIS 中编辑网站绑定时,提示“至少一个其他网站正在使用同一 HTTPS 绑定,而此绑定用另一个证书配置。确实要重用此 HTTPS 绑定并将其他网站重新指定为使用新证书吗?”,那么所有网站都必须使用同一个域名证书吗?

否。只要在绑定 https 域名的时候勾选“需要服务器名称指示”就行了。


使用证书链检测工具检测结果证书链(Certificate chain)不完整怎么办?

这个问题我在两台相同版本 CentOS 和相同版本宝塔面板的 Linux 服务器上遇到过,一台证书链完整,一台证书链不完整。

使用宝塔自带的 SSL 证书导入的方式可能出现这种情况(个例),关闭之,并手动配置 nginx 的 conf 文件;而再有一台,手动配置不生效,宝塔自带 SSL 成功,因此请自行尝试。

我也在两台相同版本的 Windows Server 2012 R2 上(IIS 8.5)遇到过,一台证书链完整,一台证书链不完整。

解决思路:在命令提示符中键入 mmc,打开:文件 - 添加/添加管理单元,选择“证书”添加,选择“计算机帐户”,确定。展开“证书”

在“个人 - 证书”中可以看到我们导入的域名证书,查看它的颁发者,确保在“中间证书颁发机构 - 证书”(或“受信任的根证书颁发机构”)中能够找到,找到后继续找该证书的颁发者,一直找到根证书。一般会有多个中间证书,形成一个完整的证书链,如果证书有缺失,那么尝试重新导入域名证书,或向供应商索要中间证书。

有任何改动后,在命令提示符中执行 iisreset 来重启 IIS(IIS 管理器中的“重新启动”可能重启得不彻底),并且找到网站 - 绑定 - 删除 https 类型的绑定并重新添加,以使证书生效。

检测证书链完整后,继续摸索过程中发现,删除某中间证书,然后在 IIS 中重新绑定,会自动生成中间证书,难道是域名证书中已经包含了中间证书和根证书等完整的证书链,还是 Windows 会自动下载安装这些证书呢?


在开发支付宝支付/微信支付时回调 Url 无法接收数据。

可能是证书链不完整,建议用工具检测:GeoCerts™ SSL Checker,并用上述方法补全。


>> 遇到新问题将不断补充本文 <<

xoyozo 7 年前
6,753
  1. 下载 Senparc 官方 Sample


  2. 打开:\WeiXinMPSDK-master\src\Senparc.Weixin.MP.Sample\Senparc.Weixin.MP.Sample.sln


  3. 工具 - NuGet 包管理器 - 管理解决方案的 NuGet 程序包 - 更新

    选择所有的包(Microsoft.Net.Http 无法更新,暂不勾选),更新

    Microsoft.Net.Http 是个老顽固,无法更新也无法卸载,原因是它的语言包 Microsoft.Net.Http.zh-Hans 无法安装。我们切换到“已安装”选项卡,搜索“Microsoft.Net.Http”,选中 Microsoft.Net.Http.zh-Hans 并卸载它,现在我们可以更新 Microsoft.Net.Http 了。


  4. 【可能】运行报错:

    “/”应用程序中的服务器错误。

    配置错误

    说明: 在处理向该请求提供服务所需的配置文件时出错。请检查下面的特定错误详细信息并适当地修改配置文件。 

    分析器错误消息: 创建 system.web.webPages.razor/host 的配置节处理程序时出错: 未能加载文件或程序集“System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35”或它的某一个依赖项。找到的程序集清单定义与程序集引用不匹配。 (异常来自 HRESULT:0x80131040)

    源错误: 

    行 4:    <configSections>
    行 5:      <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
    行 6:        <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    行 7:        <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    行 8:      </sectionGroup>


    源文件: E:\WeiXinMPSDK-master\src\Senparc.Weixin.MP.Sample\Senparc.Weixin.MP.Sample\views\web.config    行: 


    展开 Senparc.Weixin.MP.Sample 引用,查看 System.Web.Razor 的属性,复制版本号。打开 \views\web.config,修改 System.Web.WebPages.Razor 的 Version(有 3 处)。


  5. 对于小型开发项目来说,我习惯将所有代码放在同一个项目(Project)中来,所以做了以下处理:(盛派官方分离这些代码是为了同时供 MVC 和 WebForms 重用)

    在 Senparc.Weixin.MP.Sample 中添加文件夹 CommonService,将 Senparc.Weixin.MP.Sample.CommonService 项目中的文件夹和文件(.config 除外)拖到 CommonService 文件夹中。

    卸载 Senparc.Weixin.MP.Sample.CommonService 项目并删除引用。


  6. 在解决方案的 Libraries 文件夹中,我们看到 Sample 项目了以下功能模块,这些就是 Senparc.Weixin 的源代码,如果不需要修改,可以卸载它们改为使用从 NuGet 获取,以便随时更新到最新版本:

    Senparc.WebSocket

    Senparc.Weixin

    Senparc.Weixin.MP

    Senparc.Weixin.MP.MvcExtension NuGet 中对应的包名为:Senparc.Weixin.MP.MVC

    Senparc.Weixin.Open

    Senparc.Weixin.Work

    Senparc.Weixin.WxOpen

    Senparc.Weixin.Cache.Memcached

    Senparc.Weixin.Cache.Redis

    卸载这些项目,并在 NuGet 中安装这些模块(搜索“Senparc.Weixin”第一页都在了,认准作者 Jeffrey Su)

    单元测试项目中的引用也按需更换,当然也可以卸载这些单元测试项目(视情况保留 Senparc.Weixin.MP.Sample.Tests) 。


  7. 【可能】运行报错


    HTTP Error 500.19 - Internal Server Error

    无法访问请求的页面,因为该页的相关配置数据无效。

    配置源:

    134:     </sessionState>

    135:   <sessionState customProvider="Memcached" mode="Custom">

    136: <providers>


    可以在 Global.asax 的 RegisterWeixinCache() 中修改 Memcached 配置。

    或者打开 Web.config,找到 Memcached 所在的 sessionState 标签,注释掉,这样程序自动使用上方的 InProc(应用进程内)。

    如果开启了 ASP.NET State Service 服务,那么建议改用 StateServer,与 Custom 一样需要序列化,方便日后改用 Memcached 或 Redis。


  8. 再次更新 NuGet,否则会提示无法加载 Enyim.Caching 的错误(报错行:MemcachedObjectCacheStrategy.RegisterServerList(memcachedConfig);)。


  9. 接下来,进入微信公众平台,在左侧 开发 - 基本配置 中设置相关参数(填写“服务器地址(URL)”如“https://weixin.xoyozo.net/weixin/”),打开 Sample 项目中的 Web.config,配置我们的公众号参数。


  10. 将项目发布到服务器上,尝试向公众号发送消息吧。


  11. 单元测试

    设置单元测试中的公众号配置项:打开 Senparc.Weixin.MP.Test/CommonAPIs/CommonApiTest.cs,在 AppConfig 方法中可以看到支持两种配置方式,在 Senparc.Weixin.MP.Test/Config/test.config 配置文件中配置,或直接在 CommonApiTest.cs 文件中配置,前者格式如下,后者建议只在个人测试项目中使用。

    <Config>
      <AppId>YourAppId</AppId>
      <Secret>YourSecret</Secret>
      <MchId>YourMchId</MchId>
      <TenPayKey>YourTenPayKey</TenPayKey>
      <TenPayCertPath>YourTenPayCertPath</TenPayCertPath>
      <!-- 小程序 -->
      <WxOpenAppId>YourOpenAppId</WxOpenAppId>
      <WxOpenSecret>YourWxOpenSecret</WxOpenSecret>
    </Config>

    另外,将 _testOpenId 值改为自己的微信号在本公众号上的 openid。


  12. 微信网页授权(OAuth2)

    打开 OAuth2Controller 控制器,将“Index”Action 中的盛派的网址(有 2 处)改成:

    Request.Url.Scheme + "://" + Request.Url.Authority + "/Oauth2/……


  13. 未完待续……

xoyozo 7 年前
6,097

上一篇介绍了如何创建用于 https 的 SSL 证书,本文讲述如何将创建好的 SSL 证书配置到 nginx 中。

 

导入证书

将 .key 文件和 .crt 文件上传到服务器,位置如:/etc/ssl/

 

配置 .conf

打开网站配置文件 *.conf,一般在 /usr/local/nginx/conf/vhost/

添加监听 443 端口:

listen 443 ssl;

添加 ssl 配置信息:

ssl_certificate /etc/ssl/yourdomain.com.crt;
ssl_certificate_key /etc/ssl/yourdomain.com.key;
ssl_prefer_server_ciphers on;

yourdomain.com.crt 和 yourdomain.com.key 改成真实的文件名

 

实现 http 自动跳转 https

配置非 443 端口请求跳转 443 端口访问:

if ($server_port !~ 443)
{
    rewrite ^(/.*)$ https://$host$1 permanent;
}

如果要求仅将 GET/HEAD 请求自动跳转(POST 请求自动跳转会丢失表单数据),那么改成:

set $redirect_https 0;
if ($server_port !~ 443)
{
    set $redirect_https 1;
}
if ($request_method ~ ^(GET|HEAD)$)
{
    set $redirect_https "${redirect_https}2";
}
if ($redirect_https = 12)
{
    rewrite ^(/.*)$ https://$host$1 permanent;
}


验证

最后来检查一下配置得对不对:https://www.geocerts.com/ssl_checker


扩展阅读

在 IIS 中部署 SSL

安装 SSL 证书遇到的一些问题

 


xoyozo 7 年前
5,429