博客 (73)

官方 Demo

WeUI:https://weui.io/

weui.js:https://weui.io/weui.js/


开发文档

WeUI:https://github.com/Tencent/weui/wiki

weui.js:https://github.com/Tencent/weui.js/blob/master/docs/README.md

WeUI for 小程序:https://github.com/Tencent/weui-wxss


引入

① <head /> 中加入:

<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=0" />

② 引用样式:(请更改地址中的版本号,参开发文档

<link href="https://res.wx.qq.com/t/wx_fed/weui-source/res/2.5.16/weui.min.css" rel="stylesheet" />

③ (可选)引用脚本:(请将下方链接中的版本号替换为最新)

<script src="https://res.wx.qq.com/t/wx_fed/weui.js/res/1.2.17/weui.min.js"></script>


经验

  • 搜索框的 <form /> 中不加 action 则键盘中显示灰色“换行”键,加入 action 则键盘中显示蓝色“搜索”键

xoyozo 8 年前
7,089

官方教程:Getting started with ASP.NET Core MVC and Entity Framework Core using Visual Studio


第一课:入门


Entity Framework Core NuGet 软件包


安装数据库提供程序(以 SQL Server 为例):其它数据库提供程序

Install-Package Microsoft.EntityFrameworkCore.SqlServer

该软件包依赖 Microsoft.EntityFrameworkCore 和 Microsoft.EntityFrameworkCore.Relational


新建数据模型


教程

课程注册 - 学生数据模型图

文件夹 Models 存放实体类


默认以 ID 或 类名ID 为主键列,并且是标识(即自动递增),以下代码可以取消标识,允许自定义 ID 值

[DatabaseGenerated(DatabaseGeneratedOption.None)]


导航属性:对于数据库来说就是外键,对一定义为实体类,对多定义为 ICollection<T>


字段类型可以是枚举 enum

创建数据库上下文

教程

在 Data 文件夹中创建一个名为 SchoolContext.cs 的类,继承于 DbContext

使用依赖注入注册上下文

教程


修改 Startup.cs 的 ConfigureServices 方法

在 appsettings.json 中配置数据库连接字符串

添加代码以使用测试数据初始化数据库

教程

在 Data 文件夹中创建一个名为 DbInitializer.cs 的类

修改 Startup.cs 的 Configure 方法

新建一个控制器和视图

在 Controllers 文件夹上右键,添加

MVC 依赖项选择 Minimal Dependencies 即可

会自动安装 NuGet 包:Microsoft.EntityFrameworkCore.Design 和 Microsoft.EntityFrameworkCore.SqlServer.Design

公约

表名优先来自 DbSet 属性名,其次是类名

实体属性名将映射为列名

实体属性名 ID 或 类名ID 将默认被设为主键

如果属性被命名,它将当作外键(例如,导航属性 Student 对应的实体 Student 的主键是 ID,所以 StudentID 是外键);


公约可以被覆盖,例如,可以指定表名,设置列名,并将任何属性设置为主键或外键。

异步代码

教程


第二课:新建、读取、更新和删除操作(CRUD)

自定义详细信息页面

Include() // 加载导航属性

ThenInclude() // 加载导航属性的导航属性

AsNoTracking() // 使该实体在当前上下文生命周期中不更新

SingleOrDefaultAsync() // 异步检索单个实体

路由数据

<a asp-action="Edit" asp-route-id="@item.ID">Edit</a>
<a asp-action="Edit" asp-route-studentID="@item.ID">Edit</a>

生成为

<a href="/Students/Edit/6">Edit</a>
<a href="/Students/Edit?studentID=6">Edit</a>

改进“新建页面”

在 HttpPost 的 Create 方法中,因为 ID 是自动递增的,所以可以从 Bind 中删除

[ValidateAntiForgeryToken] 搭配 if (ModelState.IsValid),用于实现验证,防止 CSRF 攻击

改进“删除页面”

在 HttpGet 的 Delete 方法中增加参数用于传递报错内容

在 HttpPost 的 Delete 方法中删除失败则 RedirectToAction 到 Delete 页面并带上报错参数

用”初始化和附加“的方法实现删除

Student studentToDelete = new Student() { ID = id };
_context.Entry(studentToDelete).State = EntityState.Deleted;

实例化要删除的实体(仅指定主键值),并将状态设置为 Deleted,即可在 SaveChanges 时实现删除,从而避免了删除必须先读取的情况。

处理交易

当 SaveChanges 时,EF 自动确保所有更改都成功或都失败,如果首先完成一些更改,然后发生错误,那么这些更改将自动回滚。

无追踪查询

什么情况下适用 AsNoTracking 方法:

在上下文中不需要更新任何实体,并且不需要加载导航属性(若需要导航属性,可以预先 Include 或稍后单独查询)

检索大量数据时,仅一小部分将被更新(稍后单独查询)

当前检索的实体需要在稍后以不同的目的附加(_context.Entry(*).State)


第三课:排序,过滤,分布和分组

添加列排序链接到学生索引页

教程

将“搜索框”添加到“学生索引”页面

教程

将分页功能添加到“学生索引”页面

教程

PaginatedList 类的使用

创建一个显示学生统计信息的关于页面

创建视图模型:在 Models 文件夹中创建一个 SchoolViewModels 文件夹,添加一个类文件 EnrollmentDateGroup.cs

修改 HomeController 添加上下文

使用 group by 进行分组查询


第四课:迁移


用于迁移的 NuGet 软件包

要使用迁移,可以使用包管理器控制台(PMC)或命令行界面(CLI)。教程

CLI 的另一种打开方式:在项目上右键 - 在文件资源管理器中打开文件夹,在地址栏上键入 cmd 回车


删除数据库的 CLI 命令

dotnet ef database drop

创建初始迁移

dotnet ef migrations add InitialCreate


创建数据库的代码位于 Migrations 文件夹中,Up 方法用于创建,Down 方法用于回滚

这时只生成了创建数据库的代码,并没有真正的创建数据库


多次创建的迁移会按时间戳的次序展示在 Migrations 文件夹中,数据库中记录了最后一次迁移的版本

检查数据模型快照

迁移会在 Migrations/SchoolContextModelSnapshot.cs 中创建当前数据库模式的快照,因此 EF Core 不必与数据库进行交互以创建迁移。

要删除最后一次迁移,执行:

dotnet ef migrations remove

将迁移应用于数据库

dotnet ef database update

执行完成会创建数据库结构,但表中的初始数据将在第一次运行时被添加


上次应用迁移之后创建的一个或多个新迁移,将在当前应用迁移时按顺序全部执行。


第五课:创建复杂的数据模型

实体图

通过使用属性自定义数据模型

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

DataType 用于指定比数据库固有类型更具体的数据类型,上例指定为日期,而不是日期和时间

DateType 支持:Date, Time, PhoneNumber, Currency, EmailAddress 等等

DateType 支持传达数据的语义到 HTML5

DisplayFormat 用于指定格式

ApplyFormatInEditMode 指定是否当值显示在文本框中进行编辑时也应用此格式


[StringLength(50)]
[StringLength(50, ErrorMessage = "First name cannot be longer than 50 characters.")]
[RegularExpression(@"^[A-Z]+[a-zA-Z''-'\s]*$")]

StringLength 设置数据库中最大长度,并为客户端和服务端提供验证

StringLength 可以指定最小长度,但该值对数据库没有影响

StringLength 不会阻止用户输入空格,可以使用 RegularExpression 来限制

缩短最大长度会导致迁移时发出警告,为了保证顺利迁移,请先更改数据或重新选择合适的最大长度


[Column("FirstName")]
public string FirstMidName { get; set; }

上例将属性 FirstMidName 映射到数据库列名 FirstName

如何更改数据库中表的列名


[Required]

必需属性,不能为空的类型将自动处理必填字段,无需重复指定。


[Display(Name = "Last Name")]

显示属性,指定用于显示的名称


计算属性,只有一个 get 访问器,不会在数据库中生成列,例如:

public string FullName
{        
    get
    {
        return LastName + ", " + FirstMidName;
    }
}


可以将多个属性放在一行中:

[DataType(DataType.Date),Display(Name = "Hire Date"),DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]


在一对一的关系中,副表的主键名称不以副表实体 classnameID 命名,而以主表实体 classnameID 命名时,用 Key 属性来指定主键:

[Key]

或者需要以除 classnameID 或 ID 外的其它属性为主键,那么可以用 Key 


[Range(0, 5)]

指定数值范围


当有相关实体的导航属性时,EF 不要求在数据模型中添加外键属性。详情见教程


[DatabaseGenerated(DatabaseGeneratedOption.None)]

主键值由用户提供,而不是由数据库生成。


[Column(TypeName = "money")]
public decimal Budget { get; set; }

通常不需要列映射,此例将 decimal 类型的属性 Budget 映射为 money 类型的字段 Budget。


部门可能有负责人也可能没有,负责人必定是教师。因此 InstructorID 属性为教师实体的外键,并且可空,导航属性是被命名为 Administrator 的 Instructor 实体。

public int? InstructorID { get; set; }
public Instructor Administrator { get; set; }


通常,EF 允许对不可空的外键进行级联删除以久多对多关系。

例如,如果将 Department.InstructorID 属性定义为不可空,则 EF 将配置级联删除规则,以在删除部门时删除教师。如果我们想保留教师,但业务逻辑要求该 InstructorID 属性确实不可为空,则必须使用以下语句来禁用关系中的级联删除

modelBuilder.Entity<Department>()
   .HasOne(d => d.Administrator)
   .WithMany()
   .OnDelete(DeleteBehavior.Restrict)

补充,现在设计业务逻辑时会尽量避免删除操作,而使用禁用来代替,以在数据库中永久保留记录。


[DisplayFormat(NullDisplayText = "No grade")]

NullDisplayText 指定当值为 null 时的显示内容

联合主键

在多对多关系(教师到课程)的连接表(CourseAssignment)中,两个外键都不可为空,并且一同唯一标识表的每一行,因此不需要单独的主键,将 InstructorID 和 CourseID 作为一个联合主键。

定义联合主键不能通过使用属性来完成,唯一方法是使用 Fluent API,修改 Data/SchoolContext.cs 的 OnModelCreating 方法:

modelBuilder.Entity<CourseAssignment>().ToTable("CourseAssignment");
modelBuilder.Entity<CourseAssignment>()
    .HasKey(c => new { c.CourseID, c.InstructorID });

Fluent API 替代属性

protected override void OnModelCreating(ModelBuilder modelBuilder){
    modelBuilder.Entity<Blog>()
        .Property(b => b.Url)
        .IsRequired();
}

在本教程中,您只使用 Fluent API 进行数据库映射,而不能使用属性。您还可以使用 Fluent API 来指定可以使用属性执行的大多数格式化、验证和映射规则。一些属性(如 MinimumLength)不能应用 Fluent API,因为它不会更改数据库模式,它只适用于客户端和服务端验证。

一些开发人员喜欢专门使用 Fluent API,以保持实体类“干净”。当然可以混合使用属性和 Fluent API,但推荐只选择一种方式。如果混合使用,那么 Fluent API 会覆盖属性。

添加迁移

dotnet ef migrations add ComplexDataModel

如果在此时尝试运行命令 database update(不要这样做),您将收到以下错误:

ALTER TABLE语句与FOREIGN KEY约束“FK_dbo.Course_dbo.Department_DepartmentID”冲突。冲突发生在数据库“ContosoUniversity”,表“dbo.Department”,“DepartmentID”列。

这是因为在课程 Course 表增加了一个 DepartmentID 外键,而且是不可空的,又由于课程表中已经存在数据,所以无法 AddColumn。

我们可以创建一个临时部门,然后将它的 DepartmentID 值赋给 Course.DepartmentID 作为默认值。

打开 _ComplexDataModel.cs 文件,注释将 DepartmentID 添加到课程表的代码行,注释之,并在创建 Department 表的代码之后添加创建默认部门和添加 DepartmentID 的代码,详见教程


第六课:读取相关数据

预先加载、显式加载和延时加载

教程

  • 预先加载:当实体被读取时,相关数据随之被检索。即在单个连接查询中读取所有所需数据。通过 Include 和 ThenInclude 方法实现。

  • 显式加载:当实体首次读取时,不检索相关数据。如果需要再检索相关数据。显式加载会导致多次数据库查询。

  • 延时加载:当实体首次读取时,不检索相关数据。在首次尝试访问导航属性时,将自动检索该导航属性所需的数据。

* 从定义上看“显示加载”和“延时加载”比较类似,详细区别会在学完本课后有具体的了解。

创建一个显示部门名称的课程页面

教程

在课程列表中,每个课程都显示部门名称,因此使用预先加载。

在控制器中使用 Include 和 AsNoTracking

在视图中使用 @Html.DisplayFor(modelItem => item.Department.Name)

创建一个显示课程和报名的教师页面

教程

为教师页面创建一个视图模型 InstructorIndexData.cs

在控制器中多次使用 Include 和 ThenInclude 来预先加载相关数据

第一个 Include 加载办公室(一对零或一)

第二个 Include 加载课程(多对多)和报名课程的学生(多对多)

第三个 Include 加载课程(多对多)和课程所在部门(多对一)

本例中“课程的学生”和“课程的部门”是各自级联 ThenInclude 加载的,不能合并到同一个 Include 的课程中,因为 ThenInclude 不能读取多个分支的导航属性,每个分支都必须使用 Include 从教师实体调用。

在视图中给选择的教师添加 class 样式类

显式加载

教程

去掉 Include 和 AsNoTracking,然后在需要的时候附加相关的实体(上下文.Entry())来实现显式加载,以减少首次读取实体时的数据量。

await 上下文.Entry(单个实体).Collection(x=>x.导航属性).LoadAsync(); // 一对多

await 上下文.Entry(单个实体).Reference(x=>x.导航属性).LoadAsync(); // 一对一


第七课:更新相关数据

课程必须与部门关联,在新建和编辑课程时提供部门的下拉列表。

ViewBag.DepartmentID = new SelectList(departmentsQuery.AsNoTracking(), "DepartmentID", "Name", selectedDepartment);
<select asp-for="DepartmentID" class="form-control" asp-items="ViewBag.DepartmentID">
    <option value="">-- Select Department --</option>
</select>

SelectList 为下拉列表创建一个集合,允许指定默认选中项,并传递到 ViewBag。


将 .AsNoTracking() 添加到详细信息和删除方法


“一对零或一”关系:(本例是教师和办公室分配,抑或是文章和正文、学生和档案)

删除教师的办公室分配时,如果原先具有值,则删除办公室分配;

输入教师的办公室分配时,如果原先为空,则创建一个办公室分配;

更改教师的办公室分配时,更改现在有办公室分配值。

如何处理:

在 HttpGet 的 Edit 方法中,Include 办公室实体,并 AsNoTracking

在 HttpPost 的 Edit 方法中,移除除 id 以外的参数(为了不与 HttpGet 的 Edit 冲突,改名为 EditPost,并 ActionName("Edit"))

if (await TryUpdateModelAsync<Instructor>(
     instructorToUpdate,
     "",
     i => i.FirstMidName, i => i.LastName, i => i.HireDate, i => i.OfficeAssignment))

使用模型绑定器的值更新检索到的教师实体。TryUpdateModel 支持更新实体的导航属性。

我们可以直接设置实体的导航属性为 null,以便相关的行将被删除。


第八课:处理并发冲突

悲观并发,即锁定,性能差。

乐观并发:

[Timestamp]
public byte[] RowVersion { get; set; }

添加一个 timestamp 类型的 RowVersion 字段

详见教程


第九课:继承

教程


第十课:进阶专题

调用“返回实体”的查询

为了防止 SQL 注入,使用参数化查询:

public async Task<IActionResult> Details(int? id)
{
    if (id == null)
    {
        return NotFound();
    }
    
    string query = "SELECT * FROM Department WHERE DepartmentID = {0}";
    
    var department = await _context.Departments
        .FromSql(query, id)
        .Include(d => d.Administrator)
        .AsNoTracking()
        .SingleOrDefaultAsync();
        
    if (department == null)
    {
        return NotFound();
    }
        
    
    return View(department);
}

调用“返回其他类型”的查询

编写 SQL,而非 LINQ:

public async Task<ActionResult> About()
{
    List<EnrollmentDateGroup> groups = new List<EnrollmentDateGroup>();
    var conn = _context.Database.GetDbConnection();
    try
    {
        await conn.OpenAsync();
        using (var command = conn.CreateCommand())
        {
            string query = "SELECT EnrollmentDate, COUNT(*) AS StudentCount "
                + "FROM Person "
                + "WHERE Discriminator = 'Student' "
                + "GROUP BY EnrollmentDate";
            command.CommandText = query;
            DbDataReader reader = await command.ExecuteReaderAsync();

            if (reader.HasRows)
            {
                while (await reader.ReadAsync())
                {
                    var row = new EnrollmentDateGroup { EnrollmentDate = reader.GetDateTime(0), StudentCount = reader.GetInt32(1) };
                    groups.Add(row);
                }
            }
            reader.Dispose();
        }
    }
    finally
    {
        conn.Close();
    }
    return View(groups);
}

调用“更新”查询(批量更新)

使用参数化查询批量更新数据,返回受影响行数:

ViewData["RowsAffected"] = 
    await _context.Database.ExecuteSqlCommandAsync(
        "UPDATE Course SET Credits = Credits * {0}",
        parameters: multiplier);

检查发送到数据库的 SQL

有时,可以看到发送到数据库的实际 SQL 查询很有帮助。

第一步:设置一个断点

第二步:调试模式运行程序

第三步:在“输出”窗口可以看到 SQL 查询语句

自动变化检测

EF 通过将实体的当前值与原始值进行比较来确定实体如何更改。

一些方法会导致自动更改检测:

DbContext.SaveChages

DbContext.Entry

ChangeTracker.Entries

如果您正在跟踪大量实体,并且您在循环中多次调用上述方法之一,则可以通过临时关闭 AutoDetectChangesEnabled 属性,能显著提升性能。

_context.ChangeTracker.AutoDetectChangesEnabled = false;

从现有数据库反向工程

完整教程

常见错误

问:ContosoUniversity.dll 由另一个进程使用

答:在 IIS Express 中停止站点。

问:迁移在 Up 和 Down 方法中没有代码

原因:在运行migrations add命令时有未保存的更改

答:运行migrations remove命令,保存代码更改并重新运行migrations add命令。




xoyozo 8 年前
5,328

本文不定时更新!


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 就是罪魁祸首。


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)等。


xoyozo 8 年前
8,177

最近要做个简单的类似 CNZZ 和百度统计的统计器,不可避免地遇到 JS 文件异步加载 和 给 JS 文件传参 的问题。

参考了 CNZZ 的代码以后,在 Chrome 的控制台发现以下警告:

A Parser-blocking, cross-origin script, http://s4.cnzz.com/stat.php?***, is invoked via document.write. This may be blocked by the browser if the device has poor network connectivity. See https://www.chromestatus.com/feature/5718547946799104 for more details.

Paul Kinlan 给出了解释,是因为使用了 document.write() 的方式输出了 <script src="***" /> HTML DOM,建议改成 document.appendChild() 或 parentNode.insertBefore(),最好的例子就是 Google Analytics

<!-- Google Analytics -->
<script>(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<!-- End Google Analytics -->

上述 JavaScript 跟踪代码段可以确保该脚本在所有浏览器中加载和异步执行。

加了一些注释,便于理解,官方英文版

(function (i, s, o, g, r, a, m) {
  i['GoogleAnalyticsObject'] = r;
  // console.log(window['GoogleAnalyticsObject']) // 'ga'
  // console.log(i[r]) // undefined
  i[r] = i[r] || function () { // i[r] 就是 window['ga'],定义了一个函数
    (i[r].q = i[r].q || []).push(arguments) // 往 ga.q 这个数组中增加一项
  },
  i[r].l = 1 * new Date(); // 时间戳,写法等同于 new Date().getTime()
  // console.log(i[r]) // window['ga'] 就是上面那个 function
  a = s.createElement(o), // 创建一个 script 元素
  m = s.getElementsByTagName(o)[0]; // 文档中的第一个脚本(文档中肯定至少已有一个脚本了)
  a.async = 1; // 异步加载
  a.defer = 1; // 兼容旧浏览器(我自己加的)
  a.src = g;
  m.parentNode.insertBefore(a, m) // 将 a 脚本插入到 m 脚本之前
})(window, document, 'script', 'http://***/***.js', 'ga');
// i s o g r
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');

过程是:

创建了一个 <script> 元素,并异步加载 http://***/***.js;初始化了一个全局函数 ga;在 ga() 命令队列中添加了两条命令。

现在我们可以在这个外部 js 中使用 ga.q 这个对象中的数据了,示例:

;(function () {
  console.log(ga.q);
})(window);

简单补充下,async 是 HTML5 属性,使支持异步加载 JS 文件;defer 只支持 IE,作用类似。

测试异步只需要将 js 文件换成服务端页面,并人为设置 sleep 时间即可,阻塞式调用的话会在加载 js 时暂停后续页面的渲染。

xoyozo 8 年前
6,760

收录了一些个人觉得不错的网页开发插件。

由于插件更新频繁,本页如有错误请指正,也欢迎告知更多功能强大、使用方便的插件。

插件简介备注
框架
jQuery最流行的 JS 框架

下载中文文档英文整合文档中文整合文档浏览器支持来自 css88 的文档

官方建议 IE 6-8 使用 1.12.4

Angular中文版
AngularJS (version 1.x)
一套框架,多种平台同时适用手机与桌面MVC 架构,使得开发现代的单一页面应用程序(SPAs:Single Page Applications)变得更加容易
Vue.js是一套用于构建用户界面的渐进式框架。
Bootstrap中文版简洁、直观、强悍的前端开发框架英文文档v3中文文档v2中文文档视频教程主题和模板
jQuery UI为 jQuery 提供更丰富的功能示例:DatepickerColor AnimationShake Effect
功能
jQuery File UploadjQuery 文件上传英文文档
jQuery Cookie读取、写入和删除 cookie浏览器支持文档
json2.jsjson 操作库已弃用,旧 IE 用 jQuery 的 parseJSON,HTML 5 用 JSON.parse
Lightbox

老牌图片浏览插件

推荐使用更强大的 Viewer.js

 
Swiper中文版最现代的移动触摸滑块(Most Modern Mobile Touch Slider)英文文档中文文档,旧浏览器支持版本:2.x.xSwiper 2 英文文档中文文档
jquery-cropper图片裁剪
FastClick用于消除手机浏览器上触摸事件触发之间的 300 毫秒延迟用法不应用的场景
PACE页面加载进度条文档,IE8+
toastrjQuery 通知文档
Autosize一款小巧的,可自动调整 textarea 高度的独立脚本IE9+
X-editable允许您在页面上创建可编辑元素文档Demo
select2一款提供搜索过滤、自定义样式的下拉框插件
jQuery Tags Input标签输入框
用法
Viewer.js图片浏览插件

GitHub(viewerjs)GitHub(jquery-viewer)

jquery-viewer 是 viewerjs 的 jQuery 插件,即在 jQuery 环境中要同时引用这两个脚本。

PDF.jsA general-purpose, web standards-based platform for parsing and rendering PDFs.
编辑器
UEditor百度在线编辑器GitHub 下载文档ASP.NET 部署教程
日期时间
bootstrap-datepickerBootstrap 日期选择器Online Demo
DateTimePicker日期时间选择 
MultiDatesPicker多日期选择 
FullCalendar日历日程事件工作表IE 9+, jQuery 2.0.0+
TimeTo计时、倒计时 
图表
D3.jsD3.js 是基于数据驱动文档工作方式的一款 JavaScript 函数库,主要用于网页作图、生成互动图形,是最流行的可视化库之一。
Highcharts中文版兼容 IE6+、完美支持移动端、图表类型丰富、方便快捷的 HTML5 交互性图表库文档
ECharts百度图表控件 
AntV来自蚂蚁金服的专业、简单、无限可能的可视化解决方案
G2 - 专业易用的可视化类库
G2-mobile - 移动端高性能可视化类库
G6 - 关系图可视化类库
流程图, 关系图, 可视化规范, 地图, 河流图, 力导图, 网络图, UML图, 业务流程图, 时序图
SyntaxHighlighter功能齐全的代码语法高亮插件(JS) 
动态排名数据可视化

将历史数据排名转化为动态柱状图图表

开源代码,非插件,修改使用

GitHub视频教程EV录屏网页示例视频效果
图标
Font Awesome完美的图标字体IE 8+v3.2.1 支持 IE 7进阶用法(定宽/边框/动画/旋转/叠加)
Glyphicons图标字体作为 Bootstrap 组件
Iconfont阿里巴巴矢量图标库用户可以自定义下载多种格式的 icon,也可将图标转换为字体,便于前端工程师自由调整与调用
UI 框架
WeUI同微信原生视觉体验一致的基础样式库DemoWiki
Apple UI Design Resources苹果用户界面设计资源 
xoyozo 8 年前
9,834

程序设计规范:


  • 【推荐】上传的文件直接保存到文件存储服务(如阿里云 OSS),这样即使被上传了后门 shell,对网站服务器也不会有影响。

  • 否则必须通过文件头来确定文件类型,检查文件十六进制的文件头和文件尾是否合法,并检查文件流中是否包含 php、evel 等字符。

  • 不可直接使用客户端文件名来保存文件,特别是后缀名/扩展名。应生成随机文件名,并通过检验文件头来确定文件类型。必须由程序指定保存目录。

  • 使用 OSS 的应直接上传,不要在 ECS 上临时存放或备份。如必须存放的,应按上述规范操作。


服务器安全设置


CentOS + nginx + PHP:

  • 全站文件取消属性中的“执行”权限(chmod),因为这个“执行”与运行 PHP 无关。而需要上传文件的“目录”需要“执行”权限,原因是需要往该目录创建文件。

  • 仅需要写入的目录或文件设置“写入”权限。如上传图片目录、ThinkPHP 的 Runtime 目录。

  • 凡可写目录或文件均不允许运行 PHP / PY 等 除需要被直接访问的 PHP / PY 文件,其它动态文件均不允许被访问到,在 nginx 的配置文件中添加项,参:https://xoyozo.net/Blog/Details/nginx-location-if,若全站使用统一的入口文件访问,那么设置仅该文件允许运行 PHP 即可。通过 IO 方式被其它文件包含的文件,无需运行 PHP 权限。(“deny all”对 include 起作用,但对 IO 不起作用,因此 Runtime 目录可以继续为 ThinkPHP 提供缓存服务。)这一步非常有用。

  • 使用与 nginx 网站用户不同的用户来部署网站文件,如宝塔面板 PHP 使用 www 用户,那么就使用 root 或其它新用户来上传文件,否则将导致全站目录和文件可写。有条件的建议不同网站使用不同的用户,可防止一个网站被入侵后导致其它网站文件或磁盘上的其它文件被泄露的风险(2022年10月2日从宝塔官方社区获悉,宝塔面板暂不支持使用非 www 用户创建并运行网站)。


Windows Server + IIS + ASP.NET:

  • 配置每个磁盘的安全属性,拒绝“IIS_IUSRS”这个用户组的所有权限。只要设置驱动器即可,子文件夹和文件会自动继承。若运行 .NET Framework 项目,需要设置 C:\Windows\Microsoft.NET\Framework\v*.*.*****\Temporary ASP.NET Files\ 目录可修改写入权限,.NET Core 项目不需要此设置。

  • 为每个网站创建一个新用户,仅隶属于“IIS_IUSRS”。网站根目录安全属性添加该用户,权限选择“读取”。(已测取消“读取与执行”不影响 PHP,“列出文件夹内容”视业务需求开启,建议关闭)。仅需要上传文件的目录或文件设置“修改”、“写入”权限。(修改对应修改文件,写入对应上传文件)

  • IIS 网站中设置“物理路径凭据”以及应用程序池的“标识”。

  • IIS 中设置写入目录的“处理程序映射”无脚本

xoyozo 9 年前
4,873

各位站长好:

 

根据苹果相关通知,从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技术部


M
转自 MAGAPP产品部 8 年前
5,801

知其然,才能使其安——王震

 

常见的攻击手法

SQL 注入

文件上传

弱口令

Nday 攻击

XSS

社会工程学

等等……

 

被黑原因总结

不知道 不及时 不在意
不知道自用系统安全动态 不及时更新系统安全补丁 不在意个人信息安全
不知道常见黑客攻击手段 不及时修复漏洞 不在意用户数据安全
不知道该如何修复 不及时排查被黑系统 不在意各种安全软件提示、提醒
不知道今后该如何防御   不在意细节

 

那些年,醉人的“三字经”

网站渗透娱乐版 针对企业的实战版

进谷歌 找注入

没注入 就旁注

没旁注 用0day

没0day 猜目录

没目录 就嗅探

爆账户 找后台

传小马 放大马

拿权限 挂页面

放暗链 清数据

搞企业 先扫描

默认密 都知道

社工库 找一找

邮箱号 先列好

九头蛇 跑一跑

搞不定 放大招

发邮件 凭伪造

没邮箱 搞网站

二级域 皆可爆

老漏洞 没修好

新漏洞 刷一票

干研发 Git 找

原代码 全都要

CDN 可以跳

防火墙 可以撬

堡垒机 可以绕

云防护 可以秒

是企业 没有哪家搞不了

 

攻击手法统计

Nday攻击:45%

漏洞攻击:35%

其他攻击:15%

0day攻击:5%

 

一些箴言

80%的安全问题都是已知的安全问题,但是能抵御已知安全问题的网站只有20%

弱口令虽然看起来很弱,但是忽视弱口令只会让你的网站变得更弱

没有百分之百的安全,你所做的一切不是为了让自己无坚不摧,只是让自己不再弱不禁风

80%的系统安全问题都是可以通过升级补丁来解决,但是能做到这点的人只有20%

SQL注入存在十几年了,依然是主流攻击手段,可见安全比的不是谁更先进,而是谁更细心

不要得罪你的开发人员,这就跟你吃饭不要得罪服务员一样,你不知道他下一秒会不会在你的菜里吐口水

 

还有一句

永远不要觉得你安装的安全防护软件真的可以保护你的安全

 

服务器安全注意事项

不安装不必要的软件

排查所有系统弱口令

关闭不常用的端口

控制目录权限

不在服务器上下载、打开非官方提供软件

不在服务器上打开他人发来的网页链接

 

如何排查暗链?

利用查看网站的源代码来检查黑链

使用站长工具“网站死链检测”功能来检查黑链

用 FTP 查看网站文件的修改时间来检查黑链

接入 webscan.360.cn 检测

 

后门排查

Windows 下,D 盾、安全狗、主机卫士

Linux 下,Seay 一句话扫描脚本、主机卫士 Linux 版

用 FTP 查看网站文件的修改时间来排查恶意后门

接入 webscan.360.cn 等在线检测

 

安全类书籍推荐

《Web 安全深度剖析》——张炳帅 著

《白帽子讲 Web 安全》——吴瀚清 著

《Web 前端黑客技术揭秘》——钟晨呜(余弦)著

《黑客攻防技术宝典 Web 实战篇》——国外某黑客 著

 

联系方式

官网:www.flsec.com

xoyozo 8 年前
4,148

海鲜大部分是冷冻包装产品,小部分是散装称重产品,与超市类似,应选择“商超版”,除了钱箱、扫描枪,还应接电子秤。

  • 触摸屏

    不用记键盘快捷键,商品少的话直接点选,连扫码、输码、搜索都省了

  • 好用的收银软件

    见下方表格

  • 称重一体

    散装商品方便取重

  • Windows 7 及以上版本 或 安卓 操作系统

    安心连网,用于支付宝/微信收款,方便连锁店共享数据。选择 Windows 的话建议选到 win10,因为 win7 将在 2020 年停止支持;新的收银机基本用的安卓,可能因为各种成本低吧,不过听说安卓收银机会卡顿,类似于安卓手机的操作感,核心数和内存跟PC也不是一个概念。

  • 固态硬盘

    Windows 建议选固态,开机快;安卓是闪存

  • 销售过程中任何时间使用会员卡,而不是必须先扫会员卡,再扫商品

  • 标签打印机,支持打印价格签(不干胶热敏纸条码),称重商品需要贴上即时生成的条码

  • 支持扫描枪或扫码器扫描客户手机上的支付宝、微信(动态)付款码,以规避客户使用支付成功的截图来欺骗。需要一些配置,提现扣手续费。

  • 支持拼音简码销售


选购步骤 先选择适合自己的收银软件,再选择配置和外观,当然要考虑外接设备的兼容性(电子秤同步称重、软件开钱箱、是否需要标签打印机或后厨打印机、扫描枪是否需要支持支付宝微信 等等)。

注:标签打印机不同于小票打印机,前者用于打印临时标签,可以包含名称、价格、重量、条码等信息,贴于散装称重商品,需选购;后者打印小票给顾客提供购买商品的明细,一般收银机自带。


附:几大收银软件功能对比(从商超的角度分析)注:部分功能可能因配置不同而不同,具体应咨询客服。


二维火来钱快美团收银
版本

餐饮版

商超版

奶茶版:适用连锁店

基础版:适用餐饮

零售版:适用超市

专业版:适用连锁餐厅

操作系统安卓安卓安卓
适配触摸屏
扫描商品条码、支付二维码
对接外卖平台美团外卖、饿了么、百度外卖美团外卖、饿了么
美团外卖
手机下单免费微店、客户自助点餐
收银机点餐、顾客扫码点餐、服务员点餐
收银方式聚合支付、支付宝、微信、现金现金、支付宝、微信、银联、优惠券组合付款现金、支付宝、微信、优惠券、会员、记账
会员功能会员等级、积分、折扣、微信公众号营销会员等级、充值、积分、折扣、俏销短信、报表短信、储值、积分
支持手机火掌柜App

来钱快App 收银助手

美团管理APP
报表
自制条码(接标签打印机)
商超版、奶茶版支持
盘点库存手机操作电脑端
对接电子秤商超版支持
连锁店管理专业版支持
其它特点

排队叫号;

自主微信公众号粉丝运营;

小程序点餐

免费微信店铺,推广公众号

提高美团和大众点评店铺人气;

排队软件;

一店多收银台;

售价


买收银机赠(零售 488 元),免费升级,连锁版每用户 599 元零售版和基础版免费(买收银机赠),专业版收费
相关链接

官方网站:http://www.2dfire.com/


来钱快:

http://www.lqksyj.com/

杭州萨宝科技:

http://www.91laiqian.cn/

软件和驱动:

http://www.sabove.com/

官方网站:

http://shouyin.meituan.com/

视频教程:

http://shouyin.meituan.com/productGuide


我的评价界面拟物还不错,具体没有深究公司没有美团有名,但是入行比美团早,产品成熟,创新力强可能更适合于奶茶店类型,对打包、外卖完美适用,有机会试用的话可以给出更客观的评价

本文资料整理于 2018 年 7 月


舟山海鲜捕鱼人品牌诚招代理,电话:13646674565(微信同号)

xoyozo 8 年前
4,527

推荐:参考此文:如何升级 ASP.NET 项目 MySql.Data 和 Connector/NET 至 8.0.x

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

这是 MySQL 官方提供的,用来帮助 .NET 开发者使用 LINQ 来方便操作 MySQL 数据库的解决方案。

我们所需要的软件全部被封装在 MySQL Installer 套件当中,非常方便。

下载后选择“Custom”自定义选择需要安装的产品和功能:

  • MySQL Server - 在本机安装 MySQL 数据库,如果我们直接连接远程数据库则不需要安装

  • MySQL for Visual Studio - 是一款 Visual Studio 插件,用于连接和管理 MySQL 数据库

  • Connector/NET - ADO.NET 托管提供程序


使用也非常方便:

  1. 在“服务资源管理器”中添加连接,更改数据源为“MySQL”。(如果没有该项,重启计算机试试;仍然没有,重新运行 MySQL Installer,选择“Modify ...”,勾选对应 VS 版本的“Visual Studio Integration”和“Entity Framework Designer Integration”)

  2. 项目中“添加新项”,在“数据”中选择“ADO.NET 实体数据模型”,即 Entity Framework,而非“LINQ to SQL 类”,根据需要选择表、视图和存储过程


Windows Server 服务器上安装 MySQL Server 过程中(或安装完成后再次运行 MySQL Installer)可配置端口(同时配置防火墙)。

建议勾选安装 MySQL Workbench 来管理 MySQL 数据库。

新建用户时,主机填“%”即该用户允许远程连接。


如果报以下错误:

不支持直接到存储查询(DbSet、DbQuery、DbSqlQuery)的数据绑定。应使用数据填充 DbSet (例如通过对 DbSet 调用 Load),然后绑定到本地数据。对于 WPF,绑定到 DbSet.Local。对于 WinForms,绑定到 DbSet.Local.ToBindingList()。

记得在绑定时加一个 .ToList() 即可。


如果发布后报以下错误:

找不到请求的 .Net Framework Data Provider。可能没有安装。

那么在服务器上安装 Connector/NET 即可。


如果在 VS 中连接此 EF 时如果遇到:

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

指定的架构无效。错误 0152: 未找到具有固定名称“MySql.Data.MySqlClient”的 ADO.NET 提供程序的实体框架提供程序。请确保在应用程序配置文件的“entityFramework”节中注册了该提供程序。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260882。

那么,只需在 NuGet 中搜索并重新安装 MySql.Data.Entity ,重新生成项目。如果仍然提示,请检查 Connector/NET 是否有更新。 

6.10.4 版本相关的问题参:MySQL Connector/Net 6.10.4 不支持 VS

xoyozo 9 年前
5,679