华为S2300系列交换机配置web登录界面

mikel阅读(414)

来源: 华为S2300系列交换机配置web登录界面

最近感觉自己太菜了 搞了几台设备组网玩 过几天AR1200到手 到时候折腾路由xD

整天连着根console有点傻,想搞个web界面来管理,于是就有了这篇水文~

设备型号:Quidway  S2326TP-EI (线下淘来的 还蛮新)

Desc: Quidway S2326TP-EI-CX4Z126AM-S2326TP-EI Mainframe(24 10/100 BASE-T ports and 2 Combo GE(10/100/1000 BASE-T+100/1000 Base-X) ports and AC 110/220V)

首先既然是web console,我们需要一个IP地址,可以利用vlanif功能来实现给交换机配置一个IP地址。

首先 初始配置的情况下需要通过交换机的console口登录到设备上进行配置 。

首先在用户模式下

<Quidway> system-view //进入system-view
[Quidway] vlan 1
[Quidway] interface vlanif 1
[Quidway-Vlanif1] ip address 172.28.96.40 27 //IP和掩码可以自己定义,和PC同网段即可。
[Quidway-Vlanif1] quit

之后要把web控制台相关的文件通过FTP上传到交换机里,因为只有16M的FLASH,默认没有带web控制台的文件xD

<Quidway> system-view
[Quidway]ftp server enable //启动FTP服务
[Quidway]aaa //配置AAA认证
[Quidway-aaa] local-user admin password cipher 123456 //配置登录用户名、鉴权方式、密码加密方式、密码
[Quidway-aaa] local-user admin service-type ftp //配置用户admin的登录类型
[Quidway-aaa] local-user admin privilege level 15 //配置用户admin的登录权限。注意默认登录权限是3,很可能造成登录失败,建议设置为15
[Quidway-aaa] local-user admin privilege level 15 //配置用户admin的默认FTP目录,此处设置为闪存根目录
[Quidway-aaa] return
[Quidway]user-interface vty 0 4 //进入认证配置模式
[Quidway-ui-vty0-4]authentication-mode aaa //设置AAA认证

之后用电脑登录交换机的FTP服务器上传web控制台文件即可。(二者须同网段,电脑不一定要插在交换机上)

C:\Users\IPP>ftp 172.28.96.40
连接到 172.28.96.40。
220 FTP service ready.
530 Please login with USER and PASS.
用户(172.28.96.40:(none)): ipp
331 Password required for ipp.
密码:
230 User logged in.
ftp> put D:\web.zip
200 Port command okay.
150 Opening ASCII mode data connection for web.zip.
226 Transfer complete.
ftp: 发送 132897 字节,用时 4.53秒 29.34千字节/秒。
ftp> bye
221 Server closing.

此时文件已经成功上传到设备闪存,退出FTP。

在交换机用户模式下通过命令dir确认是否存在web.zip文件,存在则表示文件正确传输到设备上。

之后继续在console操作。准备载入控制台文件,启动HTTP服务

<Quidway> system-view
[Quidway]http server load web.zip //使http服务器加载zip包
[Quidway]http server enable //启动http服务器
[Quidway]Undo ftp server //关闭FTP服务器
[Quidway]quit
reboot
Info: The system is now comparing the configuration, please wait. Info: Save current configuration?[Y/N]:
//连续两个Y保存配置并重启交换机

重启后检查http服务是否已经启动,之后即可用IP登录web控制台,S2300系列没有HTTPS~

C#.Net筑基-模式匹配汇总 - 安木夕 - 博客园

mikel阅读(278)

来源: C#.Net筑基-模式匹配汇总 – 安木夕 – 博客园

image.png

01、模式匹配概述

C#7开始支持的 模式匹配 语法(糖,挺甜),可非常灵活的对数据进行条件匹配和提取,经过多个版本的完善,已经非常强大了。

C# 支持多种模式,包括声明、类型、常量、关系、属性、列表、var 和弃元等,在isswitch语句、switch表达式中使用,还可以使用布尔逻辑关键字 andor 和 not 组合多个模式,极大的简化了代码编写,可读性也还不错。

标题 说明 示例/备注
类型和声明模式 如果类型兼容,则申明并赋值变量 if (age is int i)
常量模式 检查表达式值是否等于、不等于(not)常量值 if(age is null &#124;&#124; age is 0)
关系模式>< 使用关系运算符<><= 或 >=匹配 case 0 or <=6
逻辑模式 not>and >or连接多个模式表达式 case < 12 and ( >6 or 6)
属性模式{:} 对实例的属性、字段进行模式匹配:{属性/字段:匹配模式} if (b is { Year: < 2000, Month: 1 or 11 })
位置模式(解构) 基于解构赋值进行模式匹配:(解构参数) if(point is (_,>0,>0))
var 模式 var申明(捕获)任意局部变量 if(point is var p && p.X>0)
弃元模式_ 弃元模式 来匹配任何(其他)表达式 表示不要的
列表模式[] 对数组(列表)进行匹配,在中括号[]中匹配列表中的项 if(numbers is [_, 2, 3, ..])

📢 模式匹配基本都是语法糖,味道都不错!C#在编译时会输出原本的基础代码,可通过 https://sharplab.io/ 在线查看编译后的代码。


02、模式匹配

2.1、类型和声明模式

检查类型是否匹配,同时申明变量,如果类型兼容则申明并赋值变量,该变量在后面代码作用域中有效。

object age = “123”;
if (age is int i) //类型匹配+申明变量i
{
Console.WriteLine($”age1 = {i});
}
switch (age)
{
case string: //类型匹配
Console.WriteLine($”type is string”);
break;
case int iage: //类型匹配+申明变量iage
Console.WriteLine($”age2 = {iage});
break;
}
//上面is语句编译后的代码效果:
if (obj is int)
{
int value = (int)obj;
}

2.2、常量模式

检查表达式值是否等于、不等于(not)常量值,常量值包括字面量常量,也包括const常量值。传统的Switch语句就是常量模式匹配。

object age = null;
if (age is not null && age is 100) //age is 100 等同于 age is int && (int)age==100
{
Console.WriteLine($”age1 = {age});
}
var type = age switch{
1 or 2 or 3=>“婴儿”,
4 => “幼儿”,
null or not 5 => “unknow”,
_=>“”,
};

2.3、关系模式><

用关系运算符来匹配表达式,就是对常量数值进行大小比较运算,使用关系运算符<><= 或 >=,多个表达式可用andor连接,当然也支持括号。

object age = 6;
if (age is int n and >= 6)
{
Console.WriteLine(“666”);
}
switch (age)
{
case 0 or <=6:
Console.WriteLine(“幼儿”);
break;
case < 12 and ( >6 or 6):
Console.WriteLine(“青少年”);
break;
}

2.4、逻辑模式not/and/or

用 notand 和 or 模式连结符来创建逻辑模式,连接多个模式表达式。

  • 优先级顺序:not>and >or
  • 推荐使用(括号)显示控制优先顺序,可读性更好。
object age = 6;
if (age is int n and (not 6 or >5) )
{
Console.WriteLine(“666”);
}

2.5、属性模式{:}

对实例的属性、字段进行模式匹配,可以嵌套其他模式匹配,非常的强大,属性匹配用大括号来包装{属性/字段:匹配模式}

  • 多个属性/字段都匹配为true时,最终才会匹配成功。
  • 可以结合类型申明模式使用。
  • 可嵌套使用,会递归匹配。
DateTime birthday = new DateTime(1999, 11, 12);
if (birthday is { Year: < 2000, Month: 1 or 11 })
{
Console.WriteLine(“年龄、星座不合适”);
}
//嵌套使用
public record Point(int X, int Y);
public record Segment(Point Start, Point End);
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start: { Y: 0 } } or { End: { Y: 0 } };
static bool IsAnyEndOnXAxis(Segment segment) =>
segment is { Start.Y: 0 } or { End.Y: 0 };

2.6、位置模式(解构)

基于解构赋值进行模式匹配:

  • Tuplerecord 和 DictionaryEntry是内置支持解构的,关于解构赋值可参考相关内容。
  • 用括号()报装,这也是 解构(Deconstruct)的语法形式。
  • 可以嵌套其他模式匹配,如常量、关系、逻辑、属性模式等。
void Main()
{
Point point = new Point(“sam”, 12, 13);
var len = point switch
{
//类型匹配、属性模式、位置模式:Name属性必须为string,且长度为0,X、Y值为0
(string { Length: <= 0 }, 0, 0) => 0,
(_, > 0, 0) => point.X, //X值大于0,Y值为0
(_, 0, > 0) => point.Y, //Y值大于0,X值为0
(_, 10 or > 10, 10 or > 10) p => p.X * p.Y,
_ => 0,
};
}
public record Point(string Name, int X, int Y);

2.7、var 模式

var申明(捕获)任意局部变量,把表达式的结果分配给var临时变量。算是类型模式的变种,将类型名替换成了var

void Main()
{
Point point = new Point(“sam”, 12, 13);
if(point is var p && p.X>0 && p.Y>0){ //is var
Console.WriteLine(“OK”);
}
var len = point switch
{
var (_,x,y) when x>0 && y>0 => true,// var
};
}
public record Point(string Name, int X, int Y);

2.8、弃元模式_

弃元模式(Discard Pattern),字面理解就是被遗弃、没人要的。可以将弃元模式看做是一个占位符,表示一个没人用的变量,可匹配任意类型,用来简化代码。语法是用下划线“_”表示。

常用场景

  • 1、解构时的占位符。
  • 2、在Switch中匹配任意其他模式,类似default的作用。
  • 3、在out参数中占位,表示一个没人用的out参数。
  • 4、独立弃元,接收无用的表达式输出。
var tuple = new Tuple<int, int>(3, 4);
var (x, _) = tuple; //1、只需要第一个参数,其他就用“_”来占位
Console.WriteLine(x); //3
_= x switch
{
2 or <2 => “small”,
int and <18=>“young”,
_=>“other”, //2、匹配其他模式,效果同default
};
int.TryParse(“”, out _); //3、不用的out变量,实际上是申明了变量的
async void Print(object arg)
{
_ = arg ?? throw new ArgumentException(); //4、接收无用的返回,效果同下
if (arg == null) throw new ArgumentException();
_ = Task.Run(()=>Console.WriteLine(“task run”)); //接收一个不用的返回
}

弃元模式_是一个提供给编译器用的符号,告诉编译这个变量不用了,编译器会根据情况进行优化处理。在对out参数使用时,编译器会自动创建变量,如下代码:

int.TryParse(“”,out _);
//实际编译后的代码如下
int result;
int.TryParse(“”, out result);

image.png

📢需要注意的是 下划线_是并不是一个关键字,也能当做参数名来使用,不要混用。

2.9、列表模式[]

C#11支持的,对数组(列表)进行匹配,在中括号[]中匹配列表中的项。

  • 跳过的项可以用弃元模式_
  • 可以用数组的切片模式匹配开头、结尾的元素。
void Main()
{
int[] numbers = { 1, 2, 3, 4 };
Console.WriteLine(numbers is [_, 2, 3, ..]); // True
Console.WriteLine(numbers is [0 or 1, <= 2, >= 3]); // False
}

03、模式匹配应用

上面的各种模式匹配主要就用在 is 运算符switch 语句switch 表达式 中。

image.png

3.1、is运算符

is 运算符 本来主要是用来检测类型兼容性的,加上模式匹配就能玩出各种花样了,极大简化了让各种检查类的代码。

object value = 12;
if (value is int && value is not null) //is类型检测+逻辑模式
{
Console.WriteLine(value);
}
if (value is int a && a > 6) //+申明模式
{
Console.WriteLine(a);
}
if (value is int age and > 10 and < 14) //关系模式
{
Console.WriteLine(age);
}
var user = new { Name = “sam”, Age = 12 };
if (user is { Name: _, Age: > 10 }) //属性模式
{
Console.WriteLine(user.Name);
}
int[] arr = new int[] { 1, 2, 3 };
if (arr is [> 0, ..]) //列表模式:第一个元素>0
{
Console.WriteLine(arr);
}
var dt = new Tuple<string, int>(“sam”, 100);
if (dt is (_, > 60) d) //位置模式+申明模式(好像没什么用)
{
Console.WriteLine(d.Item1);
}

3.2、switch..case语句

switch..case 语句 是很多语言中都有的基本多条件分支语句,传统的 case 只能用于匹配常量,多用于枚举。

  • case不能穿透,一个case 执行完后必须break结束,或者return返回(退出方法),可以多个case匹配执行一组逻辑代码。
  • 传统的case就是常量模式,而现代的case可以结合上面多种模式使用,非常强大。
  • when,自由附加更多条件。
int age = 22;
string sex = “Male”;
switch (age)
{
case 1:
case 2:
Console.WriteLine(“婴儿”);
break;
case <= 3:
Console.WriteLine(“幼儿”);
break;
case > 10 and < 16:
Console.WriteLine(“青少年”);
break;
case > 18 when sex == “Male”:
Console.WriteLine(“成年男性”);
break;
case int:
break;
}

3.3、switch表达式

C#8switch有了新的语法 —— switch 表达式 ,可以看做是switch..case语句的一个变种,使用比较类似。switch表达式是一个赋值(输出)语句。

  • =>左侧为模式(返回一个bool),如果模式匹配(true)则返回右侧的值,最后一个弃元模式匹配其他情况,同default效果。
int type = 6;
var message = type switch
{
<= 1 => “success”,
2 => “warning”,
3 => “error”,
> 3 and < 10 => “other error”,
_ => “unkonwn error”,
};

可以用when来进行更多的判断,when后面的表达式就很自由了,只要返回boo即可。

object type = 6;
var message = type switch
{
int i when i<6 => “ok”,
string s when s==“null”=>“Null”,
string s when !string.IsNullOrEmpty(s)=>“string value”,
_=>“unknown value”
};
Console.WriteLine(message);

支持多个变量的组合模式:用括号()包含多个变量

string gender = “male”;
int age = 10;
string type = (gender,age) switch{
(“male”,>18)=>“VIP”,
(not “male”,>26 and <35)=>“VVIP”,
_=>“”,
};

参考资料


©️版权申明:版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处!原文编辑地址-语雀

使用c#强大的表达式树实现对象的深克隆 - a1010 - 博客园

mikel阅读(314)

来源: 使用c#强大的表达式树实现对象的深克隆 – a1010 – 博客园

一、表达式树的基本概念

表达式树是一个以树状结构表示的表达式,其中每个节点都代表表达式的一部分。例如,一个算术表达式 a + b 可以被表示为一个树,其中根节点是加法运算符,它的两个子节点分别是 a 和 b。在 LINQ(语言集成查询)中,表达式树使得能够将 C# 中的查询转换成其他形式的查询,比如 SQL 查询。这样,同样的查询逻辑可以用于不同类型的数据源,如数据库、XML 文件等。由于表达式树可以在运行时创建和修改,同样的它们非常适合需要根据运行时数据动态生成或改变代码逻辑的场景。这对于需要重复执行的逻辑(比如本文提到的深克隆)是非常有用的,因为它们可以被优化和缓存,从而提高效率。

二、创建和使用表达式树

C# 中,我们可以通过 System.Linq.Expressions 命名空间中的类来创建和操作表达式树。以下是一个创建简单表达式树的示例:

复制代码
        // 创建一个表达式树表示 a + b
        ParameterExpression a = Expression.Parameter(typeof(int), "a");
        ParameterExpression b = Expression.Parameter(typeof(int), "b");
        BinaryExpression body = Expression.Add(a, b);

        // 编译表达式树为可执行代码
        var add = Expression.Lambda<Func<int, int, int>>(body, a, b).Compile();

        // 使用表达式
        Console.WriteLine(add(1, 2));  // 输出 3
复制代码

当我们定义了一个类型后,我们可以通过一个匿名委托进行值拷贝来实现深克隆:

复制代码
//自定义类型
public class TestDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}
//匿名委托
Func<TestDto, TestDto> deepCopy = x => new TestDto()
{
    Id = x.Id,
    Name = x.Name
};
//使用它
var a =new TestDto(){//赋值};
var b = deepCopy(a);//实现深克隆
复制代码

那么想要自动化的创建这一匿名委托就会用到表达式树,通过自动化的方式来实现匿名委托的自动化创建,这样就可以实现复杂的自动化表达式创建从而不必依赖反射、序列化/反序列化等等比较消耗性能的方式来实现。核心的业务逻辑部分如下:首先我们需要知道表达式树通过反射来遍历对象的属性,来实现x = old.x这样的赋值操作。而对于不同的属性比如数组、字典、值类型、自定义类、字符串,其赋值方案是不同的,简单的值类型和字符串我们可以直接通过=赋值,因为这两者的赋值都是“深”克隆。也就是赋值后的变量修改不会影响原始变量。而复杂的字典、数组、对象如果使用=赋值,则只会得到对象的引用,所以针对不同的情况需要不同的处理。

首先我们需要定义一个接口ICloneHandler,针对不同情况使用继承该接口的处理类来处理:

interface ICloneHandler
{
    bool CanHandle(Type type);//是否可以处理当前类型
    Expression CreateCloneExpression(Expression original);//生成针对当前类型的表达式树
}

接着我们定义一个扩展类和扩展函数,用于处理深拷贝:

复制代码
public static class DeepCloneExtension
{
    //创建一个线程安全的缓存字典,复用表达式树
    private static readonly ConcurrentDictionary<Type, Delegate> cloneDelegateCache = new ConcurrentDictionary<Type, Delegate>();
    //定义所有可处理的类型,通过策略模式实现了可扩展
    private static readonly List<ICloneHandler> handlers = new List<ICloneHandler>
    {
       //在此处添加自定义的类型处理器
    };
    /// <summary>
    /// 深克隆函数
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="original"></param>
    /// <returns></returns>
    public static T DeepClone<T>(this T original)
    {
        if (original == null)
            return default;
        // 获取或创建克隆表达式
        var cloneFunc = (Func<T, T>)cloneDelegateCache.GetOrAdd(typeof(T), t => CreateCloneExpression<T>().Compile());
        //调用表达式,返回结果
        return cloneFunc(original);
    }
    /// <summary>
    /// 构建表达式树的主体逻辑
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    private static Expression<Func<T, T>> CreateCloneExpression<T>()
    {
        //反射获取类型
        var type = typeof(T);
        // 创建一个类型为T的参数表达式 'x'
        var parameterExpression = Expression.Parameter(type, "x");
        // 创建一个成员绑定列表,用于稍后存放属性绑定
        var bindings = new List<MemberBinding>();
        // 遍历类型T的所有属性,选择可读写的属性
        foreach (var property in type.GetProperties().Where(prop => prop.CanRead && prop.CanWrite))
        {
            // 获取原始属性值的表达式
            var originalValue = Expression.Property(parameterExpression, property);
            // 初始化一个表达式用于存放可能处理过的属性值
            Expression valueExpression = null;
            // 标记是否已经处理过此属性
            bool handled = false;
            // 遍历所有处理器,查找可以处理当前属性类型的处理器
            foreach (var handler in handlers)
            {
                // 如果找到合适的处理器,使用它来创建克隆表达式
                if (handler.CanHandle(property.PropertyType))
                {
                    valueExpression = handler.CreateCloneExpression(originalValue);
                    handled = true;
                    break;
                }
            }
            // 如果没有找到处理器,则使用原始属性值
            if (!handled)
            {
                valueExpression = originalValue;
            }
            // 创建属性的绑定
            var binding = Expression.Bind(property, valueExpression);
            // 将绑定添加到绑定列表中
            bindings.Add(binding);
        }
        // 使用所有的属性绑定来初始化一个新的T类型的对象
        var memberInitExpression = Expression.MemberInit(Expression.New(type), bindings);
        // 创建并返回一个表达式树,它表示从输入参数 'x' 到新对象的转换
        return Expression.Lambda<Func<T, T>>(memberInitExpression, parameterExpression);
    }
}
复制代码

接下来我们就可以添加一些常见的类型处理器:

数组处理:

复制代码
class ArrayCloneHandler : ICloneHandler
{
    Type elementType;
    public bool CanHandle(Type type)
    {
        //数组类型要特殊处理获取其内部类型
        this.elementType = type.GetElementType();
        return type.IsArray;
    }

    public Expression CreateCloneExpression(Expression original)
    {
        //值类型或字符串,通过值类型数组赋值
        if (elementType.IsValueType || elementType == typeof(string))
        {
            return Expression.Call(GetType().GetMethod(nameof(DuplicateArray), BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(elementType), original);
        }
        //否则使用引用类型赋值
        else
        {
            var arrayCloneMethod = GetType().GetMethod(nameof(CloneArray), BindingFlags.NonPublic | BindingFlags.Static).MakeGenericMethod(elementType);
            return Expression.Call(arrayCloneMethod, original);
        }
    }
    //引用类型数组赋值
    static T[] CloneArray<T>(T[] originalArray) where T : class, new()
    {
        if (originalArray == null)
            return null;

        var length = originalArray.Length;
        var clonedArray = new T[length];
        for (int i = 0; i < length; i++)
        {
            clonedArray[i] = DeepClone(originalArray[i]);//调用该类型的深克隆表达式
        }
        return clonedArray;
    }
    //值类型数组赋值
    static T[] DuplicateArray<T>(T[] originalArray)
    {
        if (originalArray == null)
            return null;

        T[] clonedArray = new T[originalArray.Length];
        Array.Copy(originalArray, clonedArray, originalArray.Length);
        return clonedArray;
    }
}
复制代码

自定义类型处理(其实就是调用该类型的深克隆):

复制代码
class ClassCloneHandler : ICloneHandler
{
    Type elementType;
    public bool CanHandle(Type type)
    {
        this.elementType = type;
        return type.IsClass && type != typeof(string);
    }

    public Expression CreateCloneExpression(Expression original)
    {
        var deepCloneMethod = typeof(DeepCloneExtension).GetMethod(nameof(DeepClone), BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType);
        return Expression.Call(deepCloneMethod, original);
    }
}
复制代码

接着我们就可以在之前的DeepCloneExtension中添加这些handles

复制代码
private static readonly List<ICloneHandler> handlers = new List<ICloneHandler>
{
    new ArrayCloneHandler(),//数组
    new DictionaryCloneHandler(),//字典
    new ClassCloneHandler()//类
    ...
};
复制代码

最后我们可以通过简单的进行调用就可以实现深克隆了

var a = new TestDto() { Id = 1, Name = "小明", Child = new TestDto() { Id = 2, Name = "小红" }, Record = new Dictionary<string, int>() { { "1年级", 1 }, { "2年级", 2 } }, Scores = [100, 95] };
var b = a.DeepClone();

总之,C# 的表达式树提供了一个强大的机制,可以将代码以数据结构的形式表示出来,使得代码可以在运行时进行检查、修改或执行。这为动态查询生成、代码优化和动态编程提供了很多可能性。

.NET有哪些好用的定时任务调度框架 - 追逐时光者 - 博客园

mikel阅读(283)

来源: .NET有哪些好用的定时任务调度框架 – 追逐时光者 – 博客园

前言

定时任务调度的相关业务在日常工作开发中是一个十分常见的需求,经常有小伙伴们在技术群提问:有什么好用的定时任务调度框架推荐的?今天大姚给大家分享5个.NET开源、简单、易用、免费的任务调度框架,帮助大家在做定时任务调度框架技术选型的时候有一个参考。

以下开源任务调度收录地址:https://github.com/YSGStudyHards/DotNetGuide/blob/main/docs/DotNet/DotNetProjectPicks.md

Quartz.Net

一款功能齐全的任务调度系统,从小型应用到大型企业级系统都能适用。功能齐全体现在触发器的多样性上面,即支持简单的定时器,也支持Cron表达式;即能执行重复的作业任务,也支持指定例外的日历;任务也可以是多样性的,只要继承IJob接口即可。

Quartz.NET是一个功能齐全的开源作业调度系统,可用于从最小的应用程序到大规模企业系统。

Quartz.NetUI

Quartz.NetUI是一个基于.NET Core + Quartz.NET + Vue + IView开箱即用的定时任务UI(不依赖数据库,只需在界面做简单配置)。

Hangfire

Hangfire 是一个非常简单易用的库,可以在 .NET 应用程序中执行后台的、延迟的和定期的任务。它支持 CPU 密集型、I/O 密集型、长时间运行和短时间运行的任务。无需使用 Windows 服务或任务计划程序。同时,Hangfire 可以与 Redis、SQL Server、SQL Azure 和 MSMQ 集成。

Hangfire.HttpJob

Hangfire.HttpJob是一个基于Hangfire开发的一个组件、一个调度器(调度服务),这个调度器启动后你可以在管理面板上添加作业(让你通过web请求的方式去调度你的作业)。

FreeScheduler

FreeScheduler 是利用 IdleBus 实现的轻量化定时任务调度,支持临时的延时任务和重复循环任务(可持久化),可按秒,每天/每周/每月固定时间,自定义间隔执行,支持 .NET Core 2.1+、.NET Framework 4.0+ 运行环境。

DotNetGuide技术社区交流群

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
  • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

【OpenVINO™】基于 C# 和 OpenVINO™ 部署 Blazeface 模型实现人脸检测 - 椒颜皮皮虾 - 博客园

mikel阅读(290)

来源: 【OpenVINO™】基于 C# 和 OpenVINO™ 部署 Blazeface 模型实现人脸检测 – 椒颜皮皮虾 – 博客园

 前言

OpenVINO™ C# API 是一个 OpenVINO™ 的 .Net wrapper,应用最新的 OpenVINO™ 库开发,通过 OpenVINO™ C API 实现 .Net 对 OpenVINO™ Runtime 调用,使用习惯与 OpenVINO™ C++ API 一致。OpenVINO™ C# API 由于是基于 OpenVINO™ 开发,所支持的平台与 OpenVINO™ 完全一致,具体信息可以参考 OpenVINO™。通过使用 OpenVINO™ C# API,可以在 .NET、.NET Framework等框架下使用 C# 语言实现深度学习模型在指定平台推理加速。

OpenVINO™ C# API 项目链接为:

https://github.com/guojin-yan/OpenVINO-CSharp-API.git

项目源码链接为:

https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples.git

1. 简介

Blazeface模型是Google推出的一款专为移动GPU推理量身定制的轻量级且性能卓越的人脸检测器,BlazeFace 在旗舰移动设备上以200-1000 + FPS的速度运行。 在本文中,我们将使用OpenVINO™ C# API 部署 Blazeface 实现人脸检测。

2. 项目环境与依赖

该项目中所需依赖已经支持通过NuGet Package进行安装,在该项目中,需要安装以下NuGet Package:

  • OpenVINO C# API NuGet Package:
OpenVINO.CSharp.API
OpenVINO.runtime.win
OpenVINO.CSharp.API.Extensions
  • OpenCvSharp NuGet Package:
OpenCvSharp4
OpenCvSharp4.Extensions
OpenCvSharp4.runtime.win

3. 项目输出

项目使用的是控制台输出,运行后输出如下所示:

<00:00:00> Sending http request to https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Model/blazeface_1000e.tar.
<00:00:01> Http Response Accquired.
<00:00:01> Total download length is 0.47 Mb.
<00:00:01> Download Started.
<00:00:01> File created.
<00:00:01> Downloading: [■■■■■■■■■■] 100% <00:00:01 0.24 Mb/s> 0.47 Mb/0.47 Mb downloaded.
<00:00:01> File Downloaded, saved in E:\GitSpace\OpenVINO-CSharp-API-Samples\model_samples\face_detection\blazeface_opencvsharp\bin\Release\net6.0\model\blazeface_1000e.tar.
<00:00:00> Sending http request to https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Image/face1.jpg.
<00:00:01> Http Response Accquired.
<00:00:01> Total download length is 0.14 Mb.
<00:00:01> Download Started.
<00:00:01> File created.
<00:00:01> Downloading: [■■■■■■■■■■] 100% <00:00:01 0.08 Mb/s> 0.14 Mb/0.14 Mb downloaded.
<00:00:01> File Downloaded, saved in E:\GitSpace\OpenVINO-CSharp-API-Samples\model_samples\face_detection\blazeface_opencvsharp\bin\Release\net6.0\model\face1.jpg.
[ INFO ] ---- OpenVINO INFO----
[ INFO ] Description : OpenVINO Runtime
[ INFO ] Build number: 2024.0.0-14509-34caeefd078-releases/2024/0
[ INFO ] Predict model files: ./model/blazeface_1000e.xml
[ INFO ] Predict image  files: ./model/face1.jpg
[ INFO ] Inference device: CPU
[ INFO ] Start RT-DETR model inference.
[ INFO ] 1. Initialize OpenVINO Runtime Core success, time spend: 3.2045ms.
[ INFO ] 2. Read inference model success, time spend: 46.1753ms.
[ INFO ] Inference Model
[ INFO ]   Model name: Model0
[ INFO ]   Input:
[ INFO ]      name: scale_factor
[ INFO ]      type: float
[ INFO ]      shape: Shape : {1,2}
[ INFO ]      name: image
[ INFO ]      type: float
[ INFO ]      shape: Shape : {1,3,640,640}
[ INFO ]      name: im_shape
[ INFO ]      type: float
[ INFO ]      shape: Shape : {1,2}
[ INFO ]   Output:
[ INFO ]      name: multiclass_nms3_0.tmp_0
[ INFO ]      type: float
[ INFO ]      shape: Shape : {750,6}
[ INFO ]      name: multiclass_nms3_0.tmp_2
[ INFO ]      type: int32_t
[ INFO ]      shape: Shape : {1}
[ INFO ] 3. Loading a model to the device success, time spend:213.1551ms.
[ INFO ] 4. Create an infer request success, time spend:0.4506ms.
[ INFO ] 5. Process input images success, time spend:74.6076ms.
[ INFO ] 6. Set up input data success, time spend:1.7392ms.
[ INFO ] 7. Do inference synchronously success, time spend:21.3498ms.
[ INFO ] 8. Get infer result data success, time spend:1.1302ms.
[ INFO ] 9. Process reault  success, time spend:0.4035ms.
[ INFO ] The result save to E:\GitSpace\OpenVINO-CSharp-API-Samples\model_samples\face_detection\blazeface_opencvsharp\bin\Release\net6.0\model\face1_result.jpg

图像预测结果如下图所示:

image-20240505195134045

4. 代码展示

以下为嘛中所使用的命名空间代码:

using OpenCvSharp.Dnn;
using OpenCvSharp;
using OpenVinoSharp;
using OpenVinoSharp.Extensions;
using OpenVinoSharp.Extensions.utility;
using System.Runtime.InteropServices;
using OpenVinoSharp.preprocess;
using OpenVinoSharp.Extensions.result;
using OpenVinoSharp.Extensions.process;
using System;
using System.Reflection.Metadata;

namespace blazeface_opencvsharp
{
    internal class Program
    {    
    	....
    }
}

下面为定义的模型预测代码:

static void face_detection(string model_path, string image_path, string device)
{
    // -------- Step 1. Initialize OpenVINO Runtime Core --------
    Core core = new Core();
    // -------- Step 2. Read inference model --------
    Model model = core.read_model(model_path);
    Dictionary<string, PartialShape> pairs = new Dictionary<string, PartialShape>();
    pairs.Add("scale_factor", new PartialShape(new Shape(1, 2)));
    pairs.Add("im_shape", new PartialShape(new Shape(1, 2)));
    pairs.Add("image", new PartialShape(new Shape(1, 3, 640, 640)));
    model.reshape(pairs);
    OvExtensions.printf_model_info(model);
    // -------- Step 3. Loading a model to the device --------
    CompiledModel compiled_model = core.compile_model(model, device);

    // -------- Step 4. Create an infer request --------
    InferRequest infer_request = compiled_model.create_infer_request();

    // -------- Step 5. Process input images --------

    Mat image = new Mat(image_path); // Read image by opencvsharp
    Mat mat = new Mat();
    Cv2.Resize(image, mat, new Size(640, 640));
    mat = Normalize.run(mat, new float[] { 123f, 117f, 104f }, new float[] { 1 / 127.502231f, 1 / 127.502231f, 1 / 127.502231f },
        false);
    float[] input_data = Permute.run(mat);

    // -------- Step 6. Set up input data --------
    Tensor input_tensor_data = infer_request.get_tensor("image");
    //input_tensor_data.set_shape(new Shape(1, 3, image.Cols, image.Rows));
    input_tensor_data.set_data<float>(input_data);
    Tensor input_tensor_shape = infer_request.get_tensor("im_shape");
    input_tensor_shape.set_shape(new Shape(1, 2));
    input_tensor_shape.set_data<float>(new float[] { 640, 640 });
    Tensor input_tensor_factor = infer_request.get_tensor("scale_factor");
    input_tensor_factor.set_shape(new Shape(1, 2));
    input_tensor_factor.set_data<float>(new float[] { ((float)640.0f / image.Rows), ((float)640.0 / image.Cols) });

    // -------- Step 7. Do inference synchronously --------
    infer_request.infer();

    // -------- Step 8. Get infer result data --------
    Tensor output_tensor = infer_request.get_output_tensor(0);
    Shape output_shape = output_tensor.get_shape();
    int output_length = (int)output_tensor.get_size();
    float[] result_data = output_tensor.get_data<float>(output_length);
    Tensor output_tensor1 = infer_request.get_output_tensor(1);
    int output_length1 = (int)output_tensor1.get_size();
    int[] result_len = output_tensor1.get_data<int>(output_length1);

    // -------- Step 9. Process reault  --------
    List<Rect> position_boxes = new List<Rect>();
    List<float> confidences = new List<float>();
    // Preprocessing output results
    for (int i = 0; i < result_len[0]; i++)
    {
        double confidence = result_data[6 * i + 1];
        if (confidence > 0.5)
        {
            float tlx = result_data[6 * i + 2];
            float tly = result_data[6 * i + 3];
            float brx = result_data[6 * i + 4];
            float bry = result_data[6 * i + 5];
            Rect box = new Rect((int)tlx, (int)tly, (int)(brx - tlx), (int)(bry - tly));
            position_boxes.Add(box);
            confidences.Add((float)confidence);
        }
    }
    for (int i = 0; i < position_boxes.Count; i++)
    {
        int index = i;
        Cv2.Rectangle(image, position_boxes[index], new Scalar(255, 0, 0), 1, LineTypes.Link8);
        Cv2.PutText(image, confidences[index].ToString("0.00"),
            new OpenCvSharp.Point(position_boxes[index].TopLeft.X, position_boxes[index].TopLeft.Y - 5),
            HersheyFonts.HersheySimplex, 0.4, new Scalar(255, 0, 0), 1);
    }
    string output_path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(image_path)),
        Path.GetFileNameWithoutExtension(image_path) + "_result.jpg");
    Cv2.ImWrite(output_path, image);
    Slog.INFO("The result save to " + output_path);
    Cv2.ImShow("Result", image);
    Cv2.WaitKey(0);
}

下面为程序运行的主函数代码,该代码会下载转换好的预测模型,并调用预测方法进行预测:

static void Main(string[] args)
{
    string model_path = "";
    string image_path = "";
    string device = "CPU";
    if (args.Length == 0)
    {
        if (!Directory.Exists("./model"))
        {
            Directory.CreateDirectory("./model");
        }
        if (!File.Exists("./model/blazeface_1000e.xml")
            && !File.Exists("./model/blazeface_1000e.bin"))
        {
            if (!File.Exists("./model/blazeface_1000e.tar"))
            {
                _ = Download.download_file_async("https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Model/blazeface_1000e.tar",
                    "./model/blazeface_1000e.tar").Result;
            }
            Download.unzip("./model/blazeface_1000e.tar", "./model/");
        }

        if (!File.Exists("./model/face1.jpg"))
        {
            _ = Download.download_file_async("https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Image/face1.jpg",
                "./model/face1.jpg").Result;
        }
        model_path = "./model/blazeface_1000e.xml";
        image_path = "./model/face1.jpg";
    }
    else if (args.Length >= 2)
    {
        model_path = args[0];
        image_path = args[1];
        device = args[2];
    }
    else
    {
        Console.WriteLine("Please enter the correct command parameters, for example:");
        Console.WriteLine("> 1. dotnet run");
        Console.WriteLine("> 2. dotnet run <model path> <image path> <device name>");
    }
    // -------- Get OpenVINO runtime version --------

    OpenVinoSharp.Version version = Ov.get_openvino_version();

    Slog.INFO("---- OpenVINO INFO----");
    Slog.INFO("Description : " + version.description);
    Slog.INFO("Build number: " + version.buildNumber);

    Slog.INFO("Predict model files: " + model_path);
    Slog.INFO("Predict image  files: " + image_path);
    Slog.INFO("Inference device: " + device);
    Slog.INFO("Start RT-DETR model inference.");

    face_detection(model_path, image_path, device);

}

5. 总结

在该项目中,我们结合之前开发的 OpenVINO™ C# API 项目部署 Blazeface 模型,成功实现了人脸检测。

  • 项目完整代码链接为:
https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/blob/master/model_samples/face_detection/blazeface_opencvsharp/Program.cs
  • 为了方便EmguCV用户使用需求,同时开发了EmguCV版本,项目链接为:
https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/blob/master/model_samples/face_detection/blazeface_emgucv/Program.cs

最后如果各位开发者在使用中有任何问题,欢迎大家与我联系。

C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys目录占用大量空间 - Microsoft Community

mikel阅读(352)

来源: C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys目录占用大量空间 – Microsoft Community

根据文档 MachineKeys folder fills up quickly (microsoft.com):

MachineKeys 文件夹存储了由 IIS 使用的证书密钥。

MachineKeys 目录占用空间的原因主要有四个:

1. 权限问题,阻止操作系统从该文件夹中删除文件。您可以参考相关文档检查所需的权限设置。 MachineKeys 文件夹的默认权限 – Windows Server | Microsoft Learn

2. 代码相关的问题。应用程序在使用完X.509证书后未能将其删除。

3. 安全软件正在执行SSL检查,并防止这些文件被删除。

4. 企业级CA(证书颁发机构)可能无法响应请求,从而导致证书密钥文件未能及时清理。

永久解决方案是修正权限设置或修复代码,以便自动清理该文件夹中的密钥。但如果永久性解决方案需要较长时间,您可能需要一个临时的方法来清除旧文件。

以管理员身份打开命令提示符并运行以下命令以,删除 MachineKeys 文件夹中超过 90 天的文件:

ForFiles /p "C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys" /s /d -90 /c "cmd /c del @file /F /A:S"

直接删除该目录下的文件可能导致SSL/TLS证书绑定失效,或者中断依赖于这些加密密钥的其他服务。

在考虑删除之前,应首先识别哪些密钥已不再使用。所以,在没有正确识别和管理证书的情况下,通常**不建议**随意删除该目录下的文件。

jquery addClass方法失效问题_addclass('checked')失效-CSDN博客

mikel阅读(328)

来源: juqery addClass方法失效问题_addclass(‘checked’)失效-CSDN博客

使用JQuery的addClass方法后,样式已经成功添加,但还是没有效果,是因为新添加的样式的优先级比起原先的样式低所致。
例如,原先样式如下
.test div{
width: 100px;
height: 100px;
background: black;
}
改变的样式如下:
.change{
background: white;
}
像这种原先样式带有父级的,对.test容器里的div直接使用addClass(“change”)语句是没效果的,因为change样式优先级低于原先的样式,可以采用如下方法:
将改变的样式写法改为:
.test .change{
background: white;
}
或者改为:
.change{
background: white!important;
}
这时对.test容器里的div使用addClass(“change”)语句就有效了
————————————————
                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/wz13759497175/article/details/79302417

超越GPT-3.5!Llama3个人电脑本地部署教程

mikel阅读(347)

来源: 超越GPT-3.5!Llama3个人电脑本地部署教程

4月18日,Meta在官方博客官宣了Llama3,标志着人工智能领域迈向了一个重要的飞跃。经过笔者的个人体验,Llama3 8B效果已经超越GPT-3.5,最为重要的是,Llama3是开源的,我们可以自己部署!

本文和大家分享一下如何在个人电脑上部署Llama3,拥有你自己的GPT-3.5+!

很多读者担心本地部署时个人电脑的硬件配置不够,实际上这种担心是多余的,笔者使用的是MacBook M2 Pro (2023款), 主要硬件配置如下:

  • 10核CPU
  • 16G内存

部署步骤大致如下:

  • 安装Ollama
  • 下载Llama3
  • 安装Node.js
  • 部署WebUI

安装Ollama

Ollama可以简单理解为客户端,实现和大模型的交互,读者可以前往https://ollama.com/download,根据操作系统类型下载对应的客户端,比如笔者下载的是macOS的。

WX20240420-085342@2x

下载之后打开,直接点击Next以及Install安装ollama到命令行。安装完成后界面上会提示ollama run llama2,不需要执行这条命令,因为我们要安装llama3

image-20240420085557726

下载Llama3

打开新的终端/命令行窗口,执行以下命令:

ollama run llama3

程序会自动下载Llama3的模型文件,默认是8B,也就80亿参数版本,个人电脑完全可以运行。

成功下载模型后会进入交互界面,我们可以直接在终端进行提问,比如笔者问的Who are you?,Llama3几乎是秒回答。

➜  Projects ollama run llama3
>>> who are you?
I'm LLaMA, a large language model trained by a team of researcher at Meta 
AI. I'm here to chat with you and answer any questions you may have.

I've been trained on a massive dataset of text from the internet and can 
generate human-like responses to a wide range of topics and questions. My 
training data includes but is not limited to:

* Web pages
* Books
* Articles
* Research papers
* Conversations

I'm constantly learning and improving my responses based on the 
conversations I have with users like you.

So, what's on your mind? Do you have a question or topic you'd like to 
discuss?

安装Node.js

支持Ollama的WebUI非常多,笔者体验过热度第一的那个WebUI(https://github.com/open-webui/open-webui),需要Docker或者Kubernetes部署,有点麻烦,而且镜像也差不多1G。

本文推荐使用ollama-webui-lite(https://github.com/ollama-webui/ollama-webui-lite),非常轻量级,只需要依赖Node.js。

小伙伴可以前往(https://nodejs.org/en/download)根据自己的操作系统和CPU芯片类型下载对应的Node.js并进行安装。

image-20240420090338877

设置国内NPM镜像

官方的NPM源国内访问有点慢,笔者推荐国内用户使用腾讯NPM源(https://mirrors.cloud.tencent.com/npm/),之前笔者使用的是淘宝源,但是今天看淘宝源(https://registry.npm.taobao.org/)的证书已经过期89天也没人维护。

打开终端执行以下命令设置NPM使用腾讯源:

npm config set registry http://mirrors.cloud.tencent.com/npm/

部署WebUI

打开终端,执行以下命令部署WebUI:

git clone https://github.com/ollama-webui/ollama-webui-lite.git
cd ollama-webui-lite
npm install
npm run dev

提示如下,WebUI已经在本地3000端口进行监听:

> ollama-webui-lite@0.0.1 dev
> vite dev --host --port 3000



  VITE v4.5.2  ready in 765 ms

  ➜  Local:   http://localhost:3000/

打开浏览器访问http://localhost:3000,可以看到如下图所示界面。默认情况下是没有选择模型的,需要点击截图所示箭头处选择模型。

image-20240420091143684

笔者给模型提了一个编写一个Golang Echo Server的例子,大概5秒就开始打印结果,速度非常不错。

image-20240420091325732

部署遇到问题的小伙伴可以关注公众号进群交流。

一个开源轻量级的C#代码格式化工具(支持VS和VS Code) - 追逐时光者 - 博客园

mikel阅读(513)

来源: 一个开源轻量级的C#代码格式化工具(支持VS和VS Code) – 追逐时光者 – 博客园

前言

C#代码格式化工具除了ReSharper和CodeMaid,还有一款由.NET开源、免费(MIT License)、轻量级的C#语言代码格式化工具:CSharpier。

工具介绍

CSharpier是一款开源、免费、轻量级的C#语言代码格式化工具。它使用Roslyn来解析你的代码,并根据其自身的规则重新格式化代码。

工具支持IDE

Visual Studio(2019和2022)、Visual Studio Code、Rider等。

工具源代码

Visual Studio 2022中安装

打开管理拓展 -> 搜索CSharpier点击下载。

C#代码格式化效果

格式化之前

    internal class Program
    {
        static void Main(string[] args)
        {
            var userNameList = new List<string> { "小明",   "小袁", 
                
                "大姚", 
                
                
                "追逐时光者" };
        }

        public class ClassName
        {
            public void CallMethod()
            {
                GetUserInfoList("1234567890","abcdefghijklmnopqrstuvwxyz","ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                );
            }
        }

        public static string GetUserInfoList(string user1,
            string user2,
            
            string user3)
        {
            return "ok";
        }
    }

格式化之后

    internal class Program
    {
        static void Main(string[] args)
        {
            var userNameList = new List<string> { "小明""小袁""大姚""追逐时光者" };
        }

        public class ClassName
        {
            public void CallMethod()
            {
                GetUserInfoList(
                    "1234567890",
                    "abcdefghijklmnopqrstuvwxyz",
                    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
                );
            }
        }

        public static string GetUserInfoList(string user1, string user2, string user3)
        {
            return "ok";
        }
    }

项目源码地址

更多项目实用功能和特性欢迎前往项目开源地址查看👀,别忘了给项目一个Star支持💖。

优秀项目和框架精选

该项目已收录到C#/.NET/.NET Core优秀项目和框架精选中,关注优秀项目和框架精选能让你及时了解C#、.NET和.NET Core领域的最新动态和最佳实践,提高开发工作效率和质量。坑已挖,欢迎大家踊跃提交PR推荐或自荐(让优秀的项目和框架不被埋没🤞)。

DotNetGuide技术社区交流群

  • DotNetGuide技术社区是一个面向.NET开发者的开源技术社区,旨在为开发者们提供全面的C#/.NET/.NET Core相关学习资料、技术分享和咨询、项目框架推荐、求职和招聘资讯、以及解决问题的平台。
  • 在DotNetGuide技术社区中,开发者们可以分享自己的技术文章、项目经验、学习心得、遇到的疑难技术问题以及解决方案,并且还有机会结识志同道合的开发者。
  • 我们致力于构建一个积极向上、和谐友善的.NET技术交流平台。无论您是初学者还是有丰富经验的开发者,我们都希望能为您提供更多的价值和成长机会。

php防sql注入过滤代码 - 搬砖小伙子 - 博客园

mikel阅读(333)

来源: php防sql注入过滤代码 – 搬砖小伙子 – 博客园

防止SQL注入的函数,过滤掉那些非法的字符,提高SQL安全性,同时也可以过滤XSS的攻击。
function filter($str)
{
    if (empty($str)) return false;
    $str = htmlspecialchars($str);
    $str = str_replace( '/', "", $str);
    $str = str_replace( '"', "", $str);
    $str = str_replace( '(', "", $str);
    $str = str_replace( ')', "", $str);
    $str = str_replace( 'CR', "", $str);
    $str = str_replace( 'ASCII', "", $str);
    $str = str_replace( 'ASCII 0x0d', "", $str);
    $str = str_replace( 'LF', "", $str);
    $str = str_replace( 'ASCII 0x0a', "", $str);
    $str = str_replace( ',', "", $str);
    $str = str_replace( '%', "", $str);
    $str = str_replace( ';', "", $str);
    $str = str_replace( 'eval', "", $str);
    $str = str_replace( 'open', "", $str);
    $str = str_replace( 'sysopen', "", $str);
    $str = str_replace( 'system', "", $str);
    $str = str_replace( '$', "", $str);
    $str = str_replace( "'", "", $str);
    $str = str_replace( "'", "", $str);
    $str = str_replace( 'ASCII 0x08', "", $str);
    $str = str_replace( '"', "", $str);
    $str = str_replace( '"', "", $str);
    $str = str_replace("", "", $str);
    $str = str_replace("&gt", "", $str);
    $str = str_replace("&lt", "", $str);
    $str = str_replace("<SCRIPT>", "", $str);
    $str = str_replace("</SCRIPT>", "", $str);
    $str = str_replace("<script>", "", $str);
    $str = str_replace("</script>", "", $str);
    $str = str_replace("select","",$str);
    $str = str_replace("join","",$str);
    $str = str_replace("union","",$str);
    $str = str_replace("where","",$str);
    $str = str_replace("insert","",$str);
    $str = str_replace("delete","",$str);
    $str = str_replace("update","",$str);
    $str = str_replace("like","",$str);
    $str = str_replace("drop","",$str);
    $str = str_replace("DROP","",$str);
    $str = str_replace("create","",$str);
    $str = str_replace("modify","",$str);
    $str = str_replace("rename","",$str);
    $str = str_replace("alter","",$str);
    $str = str_replace("cas","",$str);
    $str = str_replace("&","",$str);
    $str = str_replace(">","",$str);
    $str = str_replace("<","",$str);
    $str = str_replace(" ",chr(32),$str);
    $str = str_replace(" ",chr(9),$str);
    $str = str_replace("    ",chr(9),$str);
    $str = str_replace("&",chr(34),$str);
    $str = str_replace("'",chr(39),$str);
    $str = str_replace("<br />",chr(13),$str);
    $str = str_replace("''","'",$str);
    $str = str_replace("css","'",$str);
    $str = str_replace("CSS","'",$str);
    $str = str_replace("<!--","",$str);
    $str = str_replace("convert","",$str);
    $str = str_replace("md5","",$str);
    $str = str_replace("passwd","",$str);
    $str = str_replace("password","",$str);
    $str = str_replace("../","",$str);
    $str = str_replace("./","",$str);
    $str = str_replace("Array","",$str);
    $str = str_replace("or 1='1'","",$str);
    $str = str_replace(";set|set&set;","",$str);
    $str = str_replace("`set|set&set`","",$str);
    $str = str_replace("--","",$str);
    $str = str_replace("OR","",$str);
    $str = str_replace('"',"",$str);
    $str = str_replace("*","",$str);
    $str = str_replace("-","",$str);
    $str = str_replace("+","",$str);
    $str = str_replace("/","",$str);
    $str = str_replace("=","",$str);
    $str = str_replace("'/","",$str);
    $str = str_replace("-- ","",$str);
    $str = str_replace(" -- ","",$str);
    $str = str_replace(" --","",$str);
    $str = str_replace("(","",$str);
    $str = str_replace(")","",$str);
    $str = str_replace("{","",$str);
    $str = str_replace("}","",$str);
    $str = str_replace("-1","",$str);
    $str = str_replace("1","",$str);
    $str = str_replace(".","",$str);
    $str = str_replace("response","",$str);
    $str = str_replace("write","",$str);
    $str = str_replace("|","",$str);
    $str = str_replace("`","",$str);
    $str = str_replace(";","",$str);
    $str = str_replace("etc","",$str);
    $str = str_replace("root","",$str);
    $str = str_replace("//","",$str);
    $str = str_replace("!=","",$str);
    $str = str_replace("$","",$str);
    $str = str_replace("&","",$str);
    $str = str_replace("&&","",$str);
    $str = str_replace("==","",$str);
    $str = str_replace("#","",$str);
    $str = str_replace("@","",$str);
    $str = str_replace("mailto:","",$str);
    $str = str_replace("CHAR","",$str);
    $str = str_replace("char","",$str);
    return $str;
}
 
 
更加简便的防止sql注入的方法(推荐使用这个):
 
 if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开    
 {    
    $post = addslashes($name); // magic_quotes_gpc没有打开的时候把数据过滤    
 }    
 
 $name = str_replace("_", "\_", $name); // 把 '_'过滤掉  
   
 $name = str_replace("%", "\%", $name); // 把' % '过滤掉    
 
 $name = nl2br($name); // 回车转换    
 
 $name= htmlspecialchars($name); // html标记转换   
     
 return $name;

 

 

PHP防XSS 防SQL注入的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
 * 过滤参数
 * @param string $str 接受的参数
 * @return string
 */
static public function filterWords($str)
{
    $farr = array(
            "/<(\\/?)(script|i?frame|style|html|body|title|link|meta|object|\\?|\\%)([^>]*?)>/isU",
            "/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU",
            "/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dump/is"
    );
    $str = preg_replace($farr,'',$str);
    return $str;
}
  
/**
 * 过滤接受的参数或者数组,如$_GET,$_POST
 * @param array|string $arr 接受的参数或者数组
 * @return array|string
 */
static public function filterArr($arr)
{
    if(is_array($arr)){
        foreach($arr as $k => $v){
            $arr[$k] = self::filterWords($v);
        }
    }else{
        $arr = self::filterWords($v);
    }
    return $arr;
}

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
在防止被注入攻击时,常会用到两个函数:htmlspecialchars()和addslashes() 、trim()函数。这两个函数都是对特殊字符进行转义。
1)addslashes()作用及使用
addslashes()通常用于防止sql注入,它可对通过get,post和cookie传递过来的参数的单引号和双引号已经null前加“\”进行转义
如:如变量$str=$_POST["str"];的值为:bb' or 1='1。通过addslashes()函数过滤后会变为:bb\' or 1=\'1;
2)htmlspecialchars()作用及使用
htmlspecialchars()也是对字符进行转义,与addslashes()不同的是htmlspecialchars()是将特殊字符用引用实体替换。
如<script>alert('xss')</script>通过htmlspecialchars()过滤后为<script>alert('xss')</script&gt
3)addslashes()与htmlspecialchars()的区别
除了两个函数的转义方式不同外,它们的使用也不同。
addslashes()通过用于防止sql语句注入,在执行sql语句前对通过get、post和cookie传递来的参数中的单引号,双引号,\ 和null进行转义。
但sql执行成功后,插入到数据库中的数据是不带有转义字符\的。这是如果插入到数据库中的是一些js脚本,当这些脚本被读取出来时还是会被执行。
这是我们可对读取出来的数据使用htmlspecialchars()进行过滤,避免执行被注入的脚本。