Web
Web

小说更新

gh_11d136296ec9_258.jpg

查询完小说,点击更新。有红色徽章的代表有更新。

PHP 角色权限控制

所有的web都是通过资源、css、描述语句、js等展现的一个页面、按钮、链接等等,而这些页面、按钮、链接、只有通过触发才可以进行激活,所以可以看待为是一个面向对象的程序、这个按钮底部实现的逻辑可以是后端、前端来实现、如何控制前端、后端逻辑需要控制模型。常用的控制权限有两种模型可以用:RBAC、AUTH。前者在百度百科上有完整的模型概念,后者是没有的。我也在网络上搜索了一下AUTH,看到有人博客写AUTH2.0,我觉得如果你不理解概念,那就不要去写。容易误导一些没有概念的人,然后这些人又很有理的说给下一个人,久而久之错误的概念会像瘟疫一样散播。搜索AUTH除了看到OAUTH2.0,其余的没有看到。而AUTH和OAUTH2.0是两种完全不同的东西,如果你想了解OAUTH2.0,可以查看rfc6749

概念

RBAC:用于角色权限访问控制,基于判断节点。

AUTH:用于角色权限访问控制,基于规则判断节点。

它们的粒度是一致的,不同的是对节点的判断方式。

例子

例如:有一个类(class)类里有一个函数(function)。现在要限制用户A能够访问到function。建表如下

用户表

idnamenum
1用户A20
节点表

idnode

2class/function
关联表

iduser_idnode_idnode_rule
112num>10

RBAC 判断:首先获取用户A的id为1,然后查找关联表user_id为1的node_id,最后通过node_id来获取到node,获取到的node就是用户A能够访问的节点。有些节点你没有写进节点表,那就代表是公共的,可以随意使用的,所以判断的时候要判断当前节点是否在节点表里,如果不在,就没有必要判断节点了。

AUTH判断:首先获取用户A的num,然后查找关联表node_rule的规则,发现如果num>10则可以获取到node_id为2。最后通过node_id去获取节点表。一样的要判断公共的节点。

上述描述少了一个角色组和角色的分类描述,这些都无关紧要。

如何实现前端控制

MVC结构如果你了解过这种结构的实现方式的话,每一个V层的实现都是需要一个模板引擎的,就像smarty。更重要的是PHP支持HTML混编。要怎么实现一个自己的模板引擎 ?下面其实是一个正常的html。

<!DOCTYPE html>
    <html>
        <head>
            <title></title>
        </head>
        <body>
            {$echo}
        </body>
    </html>

在body节点有一个很特殊的“代码”{$echo},为什么有的模板标签非要有花括号,或者中括号,或者其它的开始结束标签,实际只有一个目的,方便正则替换。原理:读取html文件,php正则提取所有的模板标签,替换模板标签里的语句,或者变量。这也就是为什么有缓存这个模板概念,因为替换完以后是需要输出或者保存后再输出的。有了上述的概念以后,那么前端控制就比较容易了,TP或者微擎都支持自定义模板标签函数,完全可以自己定义一个函数,函数里读取用户的ID,然后获取当前的URL,通过判断当前的URL与你的节点库里的URL进行对比返回一个布尔值来确定是否展示,或者是否可触发即可。

php微信推送

PushScript

源码:https://github.com/iwonmo/pushscript

下载:PushScript.jar.zip

使 用

将文件下载并解压会的到一个PushScript.jar的文件,上传到服务器。在文件同目录下新建一个http文件。

data/PushScript.jar

data/http '是TXT文件,不过没有后缀。

http文件里面填写你的回调地址。

运行

nohup java -jar PushScript.jar &

PHP

socket_connect($socket,'127.0.0.1', 1992);
socket_write($socket, "用户OPEN或者其他文本数据|过期时间");

当达到过期时间后,会自动回调你填写的接口

如下图

WechatIMG3.jpeg

Linux安装java

JDK:https://pan.baidu.com/s/148iyCSr2VYO4divsIHKVUw 提取码: ue5c 

工具:WinSCP

使用WinSCP在usr/local新建一个java文件夹例如:/usr/local/java/,然后将JDK包上传解压。

打开/etc/profile文件最底部输入如下内容

JAVA_HOME=/usr/local/java/jdk1.8.0_211
JRE_HOME=/usr/local/java/jdk1.8.0_211/jre
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
export JAVA_HOME JRE_HOME PATH CLASSPATH

执行一下命令 source /etc/profile 免重启使配置生效。

软链接添加方法

ln -s /usr/local/java/jdk1.8.0_211 /bin/java /usr/bin/java


微信小程序未授权与授权后关联问题的解决

微信小程序有一个授权登录,在你没有授权的时候,一般会限制访问,实际完全可以避免这种情况。观看了一些app或者应用的处理上发现了一些规律。都存在一个唯一的临时用户。

这个临时用户是体现给前端展示的,一般是一个随机名字,或者一组规律的字串。这有一个好处,当你微信小程序授权以后可以拿到这一个临时的字符串,然后与你的授权信息去做匹配。app的道理等同。


微信小程序的相关文档

屏幕快照 2019-05-18 下午11.25.53.png

清理策略里有写,只有在代码包被清理的时候本地缓存才会清理。也就是说,除去代码清理以外,你完全可以使用这几个函数来做本地的临时用户存储。

__autoload 内部实现原理

__autoload  

官方:尝试加载未定义的类。我的理解是在New 对象的时候,会将对象名传递。

<?php
function __autoload($class_name) { 
    echo '加载的类名:'.$class_name;
} 

@$a = new iwonmo(); 
@$a = new iwonmo1();

运行结果输出:加载的类名:iwonmo

当New的类不存在时,可以通过这个函数进行include/require。

不过注意官方的警告:This feature has been DEPRECATED as of PHP 7.2.0. Relying on this feature is highly discouraged. 在7.2.0以后的版本被弃用

SPL

SPL的全称是:Standard PHP Library (PHP标准库),版本:PHP 5 >= 5.1.0, PHP 7,这个库是做什么用的,在官网也有解释,只不过需要看英文版,因为中文版的介绍实际是不全的,不单单是这个解释。所以看PHP的文档尽量看英文版的。

The Standard PHP Library (SPL) is a collection of interfaces and classes that are meant to solve common problems.

No external libraries are needed to build this extension and it is available and compiled by default in PHP 5.0.0.

SPL provides a set of standard datastructure, a set of iterators to traverse over objects, a set of interfaces, a set of standard Exceptions, a number of classes to work with files and it provides a set of functions like spl_autoload_register()


大致的意思是SPL是一个解决常见问题接口或者的集合。然后里面提供了一组叫做SPL的函数。另外(英文里不包含):SPL函数也取代了__autoload。

spl_autoload_register的官方解释里有这么一句话:如果在你的程序中已经实现了__autoload()函数,它必须显式注册(explicitly registered )到__autoload()队列中。因为 spl_autoload_register()函数会将Zend Engine中的__autoload()函数取代为spl_autoload()或spl_autoload_call()。

对于这组函数可以翻阅PHP的源代码(php_spl.c):

int spl_autoload(const char *class_name, const char * lc_name, int class_name_len, const char * file_extension TSRMLS_DC) /* {{{ */
{
    char *class_file;
    int class_file_len;
    int dummy = 1;
    zend_file_handle file_handle;
    zend_op_array *new_op_array;
    zval *result = NULL;

    class_file_len = spprintf(&class_file, 0, "%s%s", lc_name, file_extension);

    if (zend_stream_open(class_file, &file_handle TSRMLS_CC) == SUCCESS) {
        if (!file_handle.opened_path) {
            file_handle.opened_path = estrndup(class_file, class_file_len);
        }
        if (zend_hash_add(&EG(included_files), file_handle.opened_path, strlen(file_handle.opened_path)+1, (void *)&dummy, sizeof(int), NULL)==SUCCESS) {
            new_op_array = zend_compile_file(&file_handle, ZEND_REQUIRE TSRMLS_CC);
            zend_destroy_file_handle(&file_handle TSRMLS_CC);
        } else {
            new_op_array = NULL;
            zend_file_handle_dtor(&file_handle);
        }
        if (new_op_array) {
            EG(return_value_ptr_ptr) = &result;
            EG(active_op_array) = new_op_array;
    
            zend_execute(new_op_array TSRMLS_CC);
    
            destroy_op_array(new_op_array TSRMLS_CC);
            efree(new_op_array);
            if (!EG(exception)) {
                if (EG(return_value_ptr_ptr)) {
                    zval_ptr_dtor(EG(return_value_ptr_ptr));
                }
            }

            efree(class_file);
            return zend_hash_exists(EG(class_table), (char*)lc_name, class_name_len+1);
        }
    }
    efree(class_file);
    return 0;
} /* }}} */

大致就是找到这个文件,然后编译成OP代码,然后执行,释放。实际这个过程也是__autoload的过程。这里有一个地方是会将对象名转换为小写,不知道这段代码的意义。不过明白大致意思就可以。file_extension由于被宏定义,所以这里它是一个上下文。


个人理解,如有错误还望指出。