| 方法/工具 | 发布时间 | 所属框架 | 命名空间/依赖项 | 编码标准 | 空格处理 | 严格性 | 适用场景 | 现代项目支持(.NET 6+) |
|---|---|---|---|---|---|---|---|---|
| HttpUtility.UrlEncode | 2002 | .NET Framework 1.0+ | System.Web(需引用 DLL) | x-www-form-urlencoded | + | 宽松 | 传统 ASP.NET WebForms | ❌ |
| Server.UrlEncode | 2002 | .NET Framework 1.0+ | System.Web(ASP.NET 页面内) | x-www-form-urlencoded | + | 宽松 | ASP.NET WebForms 页面内编码 | ❌ |
| Uri.EscapeDataString | 2005 | .NET Framework 2.0+ | System(核心库) | RFC 3986 | %20 | 严格 | 构造 URI 组件(路径、查询参数) | ✔️ |
| WebUtility.UrlEncode | 2012 | .NET Framework 4.5+ | System.Net(跨平台) | x-www-form-urlencoded | + | 宽松 | 非 Web 环境或兼容旧代码 | ✔️ |
| UrlEncoder.Default.Encode | 2016 | .NET Core 1.0+ | System.Text.Encodings.Web | RFC 3986 | %20 | 严格 | 现代应用,严格 URI 编码 | ✔️ |
关键选择原则
兼容旧代码 → HttpUtility.UrlEncode 或 WebUtility.UrlEncode。
严格 URI 规范 → Uri.EscapeDataString 或 UrlEncoder。
ASP.NET Core → UrlEncoder。
非 Web 或跨平台 → 弃用 System.Web,选择 System.Net 或 System.Text.Encodings.Web 中的方法。
打开 .csproj 项目文件,在 <PropertyGroup> 标签内添加:
<Version>
1.0.$([System.Math]::Floor($([System.DateTime]::Now.Subtract($([System.DateTime]::Parse('2000-01-01T00:00:00Z'))).TotalDays))).$([MSBuild]::Divide($([System.Math]::Floor($([System.DateTime]::Now.TimeOfDay.TotalSeconds))), 2))
</Version>最终生成的版本号示例: 1.0.9238.28518
其中,Major 与 Minor 是固定的,Build 是2000年1月1日至今的天数,Revision 是今天的秒数 / 2 所得的值。(为了防止数值超过 65535)
程序中获取版本号:
var version = Assembly.GetExecutingAssembly().GetName().Version!; // 当前类库
var version = Assembly.GetEntryAssembly()?.GetName().Version!; // 入口项目从版本号获取发布时间:
DateTime versionTime = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);在解决方案资源管理器中找到 Properties/AssemblyInfo.cs 文件。该文件存放程序集版本信息。
修改版本号格式
将以下代码片段中的 AssemblyVersion 改为使用星号通配符(建议保留主版本和次版本号):
[assembly: AssemblyVersion("1.0.*")] // 自动生成构建号和修订号 // [assembly: AssemblyFileVersion("1.0.0.0")] // 注释或删除此行关闭确定性构建
用文本编辑器打开 .csproj 项目文件,在 <PropertyGroup> 标签内添加:
<Deterministic>false</Deterministic>此设置允许 MSBuild 生成动态版本号。
最终生成的版本号示例: 1.0.9238.28518
其中,Major 与 Minor 是固定的,Build 是2000年1月1日至今的天数,Revision 是今天的秒数 / 2 所得的值。(为了防止数值超过 65535)
程序中获取版本号:
var version = Assembly.GetExecutingAssembly().GetName().Version;从版本号获取发布时间:
DateTime versionTime = new DateTime(2000, 1, 1).AddDays(version.Build).AddSeconds(version.Revision * 2);查看 .NET Core / .NET 5+ 实现自动版本号的方法
命令提示符
打开记事本,粘贴下方命令,保存为 .bat 文件
@echo off iisreset pause命令提示符(管理员)
打开记事本,粘贴下方命令,保存为 .bat 文件
@echo off if not "%1"=="admin" (powershell start -verb runas '%0' admin & exit) iisreset pausePowerShell
创建一个快捷方式,目标为
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "Start-Process PowerShell -ArgumentList 'iisreset' -Verb RunAs"
Ollama 默认是仅本地访问,接口地址是:http://localhost:11434
开放外部访问需要设置两个环境变量:
OLLAMA_HOST=0.0.0.0
OLLAMA_ORIGINS=*第一步,设置环境变量
macOS:
在终端中运行命令
launchctl setenv OLLAMA_HOST "0.0.0.0"
launchctl setenv OLLAMA_ORIGINS "*"Windows:
打开“环境变量”配置框
添加两个用户变量:

Linux:
使用 systemctl 设置环境变量
调用 systemctl edit ollama.service 编辑 systemd 服务配置
在 [Service] 下方添加:
[Service]
Environment="OLLAMA_HOST=0.0.0.0"
Environment="OLLAMA_ORIGINS=*"第二步,重启 Ollama
环境变量配置完成后,重启 Ollama。
第三步,开放防火墙端口
Windows:
进入“高级安全 Windows Defender 防火墙” → “入站规则” → 新建规则 → 允许 TCP 端口 11434。
第四步,验证
获取本机局域网 IP。
Windows:ipconfig
Linux/macOS:ifconfig
访问网址:http://<ip>:11434
若返回 Ollama is running 则表示连接正常。
前几天实现了在 nginx 中使用 lua 实现远程鉴权,今天想试试在 IIS 中能不能实现相同的功能。查询资料发现需要使用 URL 重写和 HTTP 请求模块,没有深究。干脆使用 ASP.NET 中间件来实现吧。
在 StratUp.cs 的 Configure 方法中,或 Program.cs 文件中添加以下代码:
// 远程鉴权
app.Use(async (context, next) =>
{
var ip = context.Connection.RemoteIpAddress!.ToString();
var ua = context.Request.Headers.UserAgent.ToString();
var host = context.Request.Host.Host;
var uri = new Uri(context.Request.GetDisplayUrl()).PathAndQuery;
var client = new HttpClient();
client.Timeout = TimeSpan.FromSeconds(1); // 设置超时时间
try
{
var requestUrl = "https://鉴权地址/";
var requestMessage = new HttpRequestMessage(HttpMethod.Get, requestUrl);
requestMessage.Headers.Add("X-Real-IP", ip);
requestMessage.Headers.Add("User-Agent", ua);
requestMessage.Headers.Add("X-Forwarded-Host", host);
requestMessage.Headers.Add("X-Forwarded-Uri", uri);
// 发送请求
var response = await client.SendAsync(requestMessage);
// 检查响应状态码
if (response.StatusCode == HttpStatusCode.Forbidden)
{
// 如果返回403,则拒绝访问
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
await context.Response.WriteAsync("Access Denied");
}
else
{
// 如果返回其他状态码,则继续执行管道中的下一个中间件
await next();
}
}
catch (TaskCanceledException ex) when (ex.CancellationToken.IsCancellationRequested)
{
// 如果请求超时(任务被取消),则继续执行管道中的下一个中间件
await next();
}
catch
{
// 如果遇到错误,则继续执行管道中的下一个中间件
await next();
}
});代码很简单,使用 HttpClient 发送请求,若返回 403 则拒绝访问,其它情况继续执行业务逻辑,超时或报错的情况按需修改即可。
若鉴权接口在私网中,建议将鉴权接口域名和私网 IP 添加到 hosts 文件中。
在 access_by_lua_block 代码块中实现远程鉴权:
#鉴权-START #resolver 223.5.5.5; # cat /etc/resolv.conf access_by_lua_block { local http = require("resty.http") local httpc = http.new() httpc:set_timeout(500) -- 连接超时 local res, err = httpc:request_uri("https://鉴权地址/", { method = "GET", headers = { ["X-Real-IP"] = ngx.var.remote_addr, ["User-Agent"] = ngx.var.http_user_agent, ["X-Forwarded-Host"] = ngx.var.host, ["X-Forwarded-Uri"] = ngx.var.request_uri, }, ssl_verify = false, -- 禁用 SSL 验证 timeout = 500, -- 读取超时 }) if not res then ngx.log(ngx.ERR, "Failed to request: " .. err) end if res and res.status == 403 then ngx.exit(ngx.HTTP_FORBIDDEN) -- return ngx.redirect("https://一个显示403友好信息的页面.html") end } #鉴权-END注意更改接口地址和友情显示 403 页面地址。
本示例仅捕获 403 状态码,500、408 等其它异常情况视为允许访问,请根据业务需求自行添加状态码的判断。
若超时也会进入
if not res then代码块。建议将此代码部署在 nginx 主配置文件的 http 代码块中(宝塔面板中的路径:/www/server/nginx/nginx/conf/nginx.conf),如果你只想为单个网站鉴权,也可以放在网站配置文件的 server 块中。
若鉴权接口在私网中,建议将鉴权接口域名和私网 IP 添加到 hosts 文件中。
附
直接输出字符串
ngx.header.content_type = "text/plain"; ngx.say("hello world!")输出到日志
ngx.log(ngx.ERR, "Response status: " .. res.status)日志在网站的 站名.error.log 中查看。
宝塔面板查看方式:日志 - 网站日志 - 异常
若想获取服务器 CPU 使用率等信息并传递给远程鉴权接口,请参考此文。
常见问题
no resolver defined to resolve
原因:没有定义 DNS 解析器
解决方法:在 http 块或 server 块中添加
resolver 8.8.8.8 valid=30s;,推荐使用接入商自己的公共 DNS,如果走内网,推荐使用本机 DNS。unable to get local issuer certificate
原因:没有配置 SSL 证书信息
解决方法:添加 request_uri 参数:
ssl_verify = true, -- 启用 SSL 验证 ssl_trusted_certificate = "证书路径", -- 指定 CA 证书路径或
ssl_verify = false, -- 禁用 SSL 验证若您不想用 lua,可以用 nginx 原生自带的 auth_request 模块来实现。
鉴权方式有许多,譬如可以用 lua 的 access_by_lua 来实现,这里用 nginx 自带的 auth_request,虽然功能简单,但效率更高。
第一步,确保 nginx 已编译安装 auth_request 模块,见此文。
第二步,打开需要鉴权的网站的 nginx 配置文件,添加以下代码块:
#鉴权-START
location / {
auth_request /auth;
error_page 403 = @error403;
#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-**.conf;
#PHP-INFO-END
}
location = /auth {
internal;
proxy_pass https://鉴权地址;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header User-Agent $http_user_agent;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_intercept_errors on;
#proxy_read_timeout 1s; # 超时会报 500
}
location @error403 {
#default_type text/plain;
#return 403 'forbidden';
return 302 https://一个显示403友好信息的页面.html;
}
#鉴权-END一般放在所有的 location 之前。
这里自定义请求头 X-Forwarded-Host 与 X-Forwarded-Uri 用来传递 host 与 uri。API 应从 Header 中相应取值。
宝塔面板中是通过 include enable-php-**.conf; 的方式调用 PHP ,那么可以将此行移入上面的 location / 代码块中,因为此代码块能匹配所有的请求路径。
最后,若鉴权接口在私网中,将鉴权接口域名和私网 IP 添加到 hosts 文件中。
要在 Alibaba Cloud Linux 3 上设置开机启动 ossftp,你可以通过创建一个系统服务来实现。以下是具体步骤:
安装 ossftp:
按照阿里云官方文档安装 ossftp。
创建服务文件:
首先,你需要创建一个服务文件。使用以下命令创建一个新的服务文件:
sudo nano /etc/systemd/system/ossftp.service编辑服务文件:
在打开的编辑器中,添加以下内容:
[Unit]
Description=OSS FTP Service
After=network.target
[Service]
ExecStart=/bin/bash /root/ossftp-1.2.0-linux-mac/start.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target这里的 ExecStart 指向你的 start.sh 脚本的路径。
保存并退出。
重新加载系统服务:
运行以下命令以重新加载系统服务,使新创建的服务生效:
sudo systemctl daemon-reload启用服务开机启动:
使用以下命令启用服务,使其在系统启动时自动运行:
sudo systemctl enable ossftp.service启动服务:
你可以立即启动服务以测试其是否正常工作:
sudo systemctl start ossftp.service检查服务状态:
使用以下命令检查服务的状态,确保它正在运行:
sudo systemctl status ossftp.service如果一切设置正确,ossftp 应该会在每次系统启动时自动运行。
如果在你的系统上没有安装 nano 编辑器,你可以使用其他文本编辑器,比如 vi 或 vim。
如果你需要安装 nano,可以使用以下命令:
sudo yum install nano今天早上同事反映论坛某管理账号无法登录,于是我尝试用创始人账号登录,也不行,第一反应就是中招了。
于是进阿里云控制台,发现云安全中心有许多安全警告,类型是网站后门,幸好 nginx 中设置了仅部分文件可执行 PHP,这些后门文件无法被执行。
尝试在 config_global_default.php 文件中添加创始人,但账号必须是副站长等管理账号才能成为创始人。
于是借用一个小号,从表 pre_ucenter_members 中将这个小号的 password 和 salt 复制到创始人账号中,这样创始人账号就可以用这个小号的密码登录了。
进入论坛后台,在 工具-运行记录-系统记录-后台访问 中查看入侵时间段的记录(操作、时间、IP 等),可搜索。
发现基本上在操作模板管理和专题管理。
对比时间,发现进入后台操作在先,上传后门在后。
查询 web 访问日志,通过访问文件路径或 IP 查询,在进入论坛后台之间,他进入了 UCenter 的后台,但是再往前就没有记录了。
因此基本可以确定:
黑客从 UCenter 修改了某管理员账号的密码(可能是利用漏洞),然后登录论坛后台修改了创始人的密码(可能也是用 UCenter 改的),通过模板管理和专题管理功能的上传功能上传了后门文件。
索性他没有对数据进行破坏性处理,也没有挂马,只是发现后门文件无法执行就放弃了。