上厕所的时候看到的一个超级赞的东东#1

上厕所是一个特别的场景,有时候总会遇到有趣的事情,所以开了这个系列记载。

当然了,因为上厕所一篇时间较短,所以每一篇都是短篇。

今天分享的是在一家日企的厕所看到的一个流程图,第一次看到这个介绍,我被惊讶到了。

作为一个自称BPM(业务流程管理)专家的我,直呼汗颜,茅塞顿开!

我觉得这个流程写得有几个亮点:

1、工具配图
2、位置配图
3、错误和正确的参考图
4、简洁精炼的文字介绍

给我最大的其它的是,把工具用ABC的英文来命名,对位置用123数字命名。这其实对于我们常规的流程梳理,两个维度就可以用英文、数字来清晰地区分。如果还有多个维度,还可以使用中文的甲乙丙丁或者中文的壹贰叁肆。这个做法简直太妙了!

Infor ERP LN有用的Session:ttstpdeldeflt Remove User Defaults

在使用Infor ERP LN的过程中,由于网络中断或者不稳定经常会出现用户打开某个Session的时候报错,信息类似如下:

Fatal error : value DsNheight=-280 out of range

那么这时候,用户怎么也打不开想要使用的Session了,这时候就需要用到这个有用的Session:Remove User Defaults.

输入用户的账号,选择相应的公司,然后输入对应的Session Code,点击Remove即可。

宝塔LNMP环境WordPress二级目录伪静态的设置

我这个站的WordPress位于主域名下的/shanghai/下面,原来国外主机用的Apache,现在这个是Nginx主机,所以伪静态的规则要重新改下。

宝塔可以很方便生成WordPress的顶级目录下的伪静态代码,但对于二级目录就的自己写了。

代码如下,把其中的/shanghai/改为你的目录即可。

location /
{
	 try_files $uri $uri/ /index.php?$args;
}

rewrite /wp-admin$ $scheme://$host$uri/ permanent;

location /shanghai/ {
index index.html index.php;
if (-f $request_filename/index.html){
rewrite (.*) $1/index.html break;
}
if (-f $request_filename/index.php){
rewrite (.*) $1/index.php;
}
if (!-f $request_filename){
rewrite (.*) /shanghai/index.php;
}
}

国内主机请关闭WordPress自动更新

如果你部署在国内,你就知道升级的时候会不断地遇到升级失败,然后整站就不能访问了。

原因及重要性不必多说,那就说说关闭的方法吧:配置wp-config.php文件

全局配置文件wp-config.php位于wordpress程序根目录下的,在文件最后加入如下代码:

/** 关闭WordPress自动更新升级 */
define('AUTOMATIC_UPDATER_DISABLED', true);

经历了WordPress被种木马,回到国内(上海)主机

11月17日,Tony微信告诉我博客不能访问了,我一看被植入了js木马。

回想了一下11月4日还写博客来的,当时没有什么问题的。

赶紧问服务商有没有备份,最近的备份是哪天的?得到的答复是只保留最近3天的备份,找到最早的是11月14日的,可惜那时候已经被黑了。数据库和程序都被动了。

看了一下本地的备份,最近的是3月份的,也就是说半年多的博客要丢了。

头大,但工作挺忙,也顾不上了。

第一个念头就是,搬回阿里云,只要有付费的每日备份。

碰到青云有个双十一的活动,就随手买了个Linux的上海主机。正好也需要备案,就没急着捣鼓。等到了周末暂时利用新主机上的MySQL数据,看了一下被植木马的数据库,发现规律就是每篇文章都在结尾加入了一串javascript代码,同时站点的home和site的配置项都被改为木马的网址。

于是心里一喜,果断的写了REPLACE替换,清除了木马。

此时有了信心,拿起我的BeyondCompare文件比较利器,对WordPress程序与原版程序作了对比,发现不少上传的php文件,还有无后缀的木马文件。同时发现了被修改的程序文件,就这样逐渐的把程序的木马也清理了。

此时备案还在进行中,就在原来的国外主机上进行了程序和数据库的覆盖,当然了本地也保存了备份。

果然,网站正常了。欣喜的告诉小伙伴们,大家非常期待我分享如何清除木马的。

我还是比较谦虚的,希望等几天看看,是否还有未清理的木马,不然分享就是给自己丢人。

果不其然,替换后的第二天,程序又被植入了木马。

干净对虚拟机下的其他站点目录都进行了清理,还删除了几个漏网之鱼。

这下基本上放心了,此时备案也快完成了。

于是在新主机上玩BT宝塔,对服务器安全、网站目录、端口放行、SSL证书、WordPress二级目录下的伪静态等全部研究了一遍。

昨天,改了DNS,指向到了新主机。

老主机的数据全部删除了,希望在新主机上,在宝塔的协助下,能够安全不被黑。

这篇作为流水账,下次分享详细的木马清理过程,还有WordPress文件目录安全设置和伪静态的相关内容。

.NET程序连接Oracle一次执行多行SQL的注意事项

以前写的基于MSSQL数据库的.NET程序,不用担心SQL语句中的;或者换行符。但是因为要基于Infor LN的Oracle数据库进行开发,就碰到了;分号和换行的报错,同时一次执行UPDATE的多条更新语句时,也会报错。

Oracle.ManagedDataAccess.Client.OracleException:ORA-00911: invalid character

单行SQL如果有换行时,加了;就报上面的错,多行执行的时候,会报下面这种错误

Oracle.ManagedDataAccess.Client.OracleException:ORA-06550: line 1, column 1:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:

   ; <an identifier> <a double-quoted delimited-identifier>
The symbol ";" was substituted for "end-of-file" to continue.

虽然从网上能搜索到ExecuteNonQuery执行Oracle多条SQL的时候需要用到以下结构

BEGIN
SQL1;
SQL2;
SQL3;
END;

但是并没有人提到一定要确保整个SQL是一行,必须没有换行!

BEGIN
 UPDATE BAANDB.TWHINH225301 A
 SET A.T$WVID = -999
,A.T$ASGN = 1
,A.T$PKID = 'Troy'
,A.T$STLO = 'EMS'
 WHERE A.T$RUNN = 'CN432789'
 AND A.T$PICM = 1
 AND A.T$ASGN = 2
 AND A.T$PCKD = 2;
UPDATE BAANDB.TWHINH225301 A
 SET A.T$WVID = -999
,A.T$ASGN = 1
,A.T$PKID = 'Troy'
,A.T$STLO = 'EMS'
 WHERE A.T$RUNN = 'CN432785'
 AND A.T$PICM = 6
 AND A.T$ASGN = 2
 AND A.T$PCKD = 2;
END;

因为写日志看SQL方便,用了AppendLine,那么下面的代码中,需要手动替换下换行符:Replace(Environment.NewLine, ” “),如果还不放心,可以用Replace(“r\n”, ” “).Replace(‘\n’, ‘ ‘).Replace(‘\r’, ‘ ‘) 批量将各种换行符替换为空格。

            var result = 1;
            var sb = new StringBuilder();
            sb.AppendLine("BEGIN");
            foreach (var entity in list)
            {
                sb.AppendLine("UPDATE BAANDB.TWHINH225" + companyId + " A");
                sb.AppendLine("SET A.T$WVID = -999");
                sb.AppendLine(",A.T$ASGN = 1");
                if (!string.IsNullOrEmpty(entity.Picker))
                {
                    entity.Picker = dbHelper.SqlSafe(entity.Picker);
                    sb.AppendLine(",A.T$PKID = '" + entity.Picker + "'");
                }
                if (!string.IsNullOrEmpty(entity.StagingLocation))
                {
                    entity.StagingLocation = dbHelper.SqlSafe(entity.StagingLocation);
                    sb.AppendLine(",A.T$STLO = '" + entity.StagingLocation + "'");
                }
                // By Line
                sb.AppendLine("WHERE A.T$OORG = " + GetOrderOrigin(entity.OrderOrigin));
                sb.AppendLine("AND A.T$ORNO = '" + entity.OrderNumber + "'");
                sb.AppendLine("AND A.T$OSET = " + entity.OrderSet);
                sb.AppendLine("AND A.T$PONO = " + entity.Line);
                sb.AppendLine("AND A.T$SEQN = " + entity.SequenceNumber);
                sb.AppendLine("AND A.T$SERN = " + entity.Advice);
                // Check Assign Status
                sb.AppendLine("AND A.T$ASGN = 2");
                sb.AppendLine("AND A.T$PCKD = 2;");
            }
            sb.AppendLine("END;");
            try
            {
                ExecuteNonQuery(sb.ToString().Replace(Environment.NewLine, " "));
            }
            catch (Exception e)
            {
                LogUtil.WriteException(e);
                result = 0;
            }

            return result;

因为这个问题,还从大石头的新生命微信群发了红包求助,意外收获了结识了一个挺不错的开发者王振(王Bank)和他写的DbHelper:https://gitee.com/wangbank/BankDbHelper

.NET程序中如何解决Google Chrome浏览器iframe禁止跨域的SameSite的Cookie设置

这个问题是我们总部的一个外部应用,给到我们的客户每家一个iframe的嵌套页面,通过计算handshake的动态值,实现免登录的。这其中用到了Cookie和服务器端的Form认证。

伴随着谷歌浏览器(80版本之后对cookie的校验更加严格,SameSite属性默认值由None变为Lax)的升级,iframe中的Cookie跨域被默认禁用了,除非SameSite为None并Secure属性为True(强制SSL启用HTTPS访问)

经过印度第三方外包公司45天的调查处理,仍未解决。

经过远程会议,了解了现在团队已经做过的尝试,大的方向没错,目前未能解决的问题是

无法将2个Cookie的SameSite写成None

.ASPXAUTH
ASP.NET_SessionId

一开始我以为改用最原始的HTTPCookie的方式写就行了,但是这两个Cookie就是无法赋值。微软官网建议的在Web.config和Global.asax设置也没用。

好在透过Google看到有人提到用URL Rewrite工具,果然有效。

最终解决方案,用URL重写工具,在system.webServer节点写入Outbound规则如下:

    <rewrite>
      <outboundRules>
        <rule name="AddSameSiteCookieFlag">
          <match serverVariable="RESPONSE_Set-Cookie" pattern="^(.*)(ASP.NET|ASPXAUTH|SessionId)(=.*)$" />
          <action type="Rewrite" value="{R:0};SameSite=None" />
        </rule>
      </outboundRules>
    </rewrite>

而原有的<forms />认证信息中,必须加入requireSSL=”true”,总共涉及9行代码。

最终印度第三方外包公司的同事高高兴兴的去部署到服务器了。

BPM一夜之间都成了低代码开发平台

月初中国软件网的记者赵满满筹备一篇BPM的文章,微信联系到我问几个问题,让我重新去关注了一下当下国产BPM的一些现状。

最大的发现是:一夜之间,你去国内的BPM厂商的官网去看,每家都增加了低代码平台的宣传口号。

我搜集整理了一下,比方第一家易正的新口号:Low-Code,流程快速开发平台

奥哲的新口号:低代码开发平台云产品与方案提供商

炎黄盈动的新口号:全球领先的低代码和BPM PaaS服务商

没想到这两年低代码平台的崛起对周边产品的影响这么大,很多时候一个概念出来的时候,边界很难限定,影响也很难预估。

最后附上中国软件网的《低代码、中台化、AI化并发,BPM会成为大赢家?》文章链接。

跟老板学管理#3:没办法解决的先放一放

曾经就几个问题求证老板,确认他是否知道?

老板说:其实很多问题,我知道了,但没有好的解决方案,只能先放一放。

我想这里的问题不仅指事情,也包括人。

很多时候,一个人在一个位置上不合适,在没有好的后备方案的情况下,就先留着。

当有解决办法的时候,放下的还能拿起来。

拿得起,放得下。

说起来容易,生活和工作都需要知行合一。

上海美食打卡:浦东周浦黄大哥羊肉

今天约了高中同学、饭搭子的表弟一起吃早饭,慕名前往周浦的黄大哥羊肉,怕去的晚吃不到,6点钟爬起来去排队。

开车过去30分钟,7点钟不到就到了,但店附近没有停车场,在距离500多米的一个广场停车场停好车,路上看到另一家叫长脚羊肉的店,排队得有30米以上。

拐过路口,找到了黄大哥羊肉店,看起来很简陋,但是排队的人依然很多。

老板一家直接提供服务,很亲民。

老板陪一些本地的老人边吃边聊,喝点小酒。

老板的女儿收钱,估计是太太切肉。

整个流程是先买羊肉和羊杂,然后可以打包带走,多数堂吃顺道点上面条(干和汤两种)和羊肉汤、羊杂汤。

点好以后,我就到院子里找了个位置,不对,应该是等了个位置。

还有些人直接在街上,找个凉阴处,摆张桌子就吃起来。

我点肉没经验,切出来肥肉居多。但吃起来还不算太腻。

特别是羊皮,以前我很反感崇明红烧羊肉还带皮的操作,因为从小就是喝羊肉汤不习惯,可能我们县的没品牌,但菏泽的单县羊肉汤还是有有一定品牌的。现在吃起来带羊皮沾点酱料还是很美味的。

如果比起来以前吃苏州臧书羊肉面,还是臧书羊肉的面好吃。

比起昨天在奉贤庄行的李记羊肉,黄大哥这里只有一种做法,李记就是一个大饭店,黄大哥目前还是小店。

但现在用户为王的时代,谁能低估一个以传统产品为核心的美食品牌呢,谁能低估一个小品牌的潜能呢。

你问我为啥开始美食打卡,写这些流水账的文字。

我想说

以前觉得挣钱不重要

现在才知道

星辰和大海都需要门票

而诗和远方的路费

也都很贵

远了去不了,那先从近处去探索吧