- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
在
PHP笔记-用户登录&权限拦截说明
这篇博文中设置Cookie时用的是数据库的用户id。这样有问题,用户可以随意改动ID,从而获取不同的用户权限。
这里我们更新下,增加点安全性。构造safe包
内容如下:
CookieAndSession.php
<?php
namespace safe;
class CookieAndSession{
public $cookie;
public $userId;
public $browser;
public $os;
public $timeToLive;
}
CookieTool.php
<?php
namespace safe;
class CookieTool{
protected function generateKey(): string{
$length = 32;
$retKey = "";
for ($i = 0; $i < $length; $i++)
{
$retKey .= chr(mt_rand(33, 126));
}
return $retKey;
}
protected function getIPAddress(): string{
$ipaddress = "";
if (isset($_SERVER['HTTP_CLIENT_IP']))
$ipaddress = $_SERVER['HTTP_CLIENT_IP'];
else if(isset($_SERVER['HTTP_X_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_X_FORWARDED']))
$ipaddress = $_SERVER['HTTP_X_FORWARDED'];
else if(isset($_SERVER['HTTP_FORWARDED_FOR']))
$ipaddress = $_SERVER['HTTP_FORWARDED_FOR'];
else if(isset($_SERVER['HTTP_FORWARDED']))
$ipaddress = $_SERVER['HTTP_FORWARDED'];
else if(isset($_SERVER['REMOTE_ADDR']))
$ipaddress = $_SERVER['REMOTE_ADDR'];
else
$ipaddress = 'UNKNOWN';
return $ipaddress;
}
protected function getBrowser($agent): string{
$browserAgent = "";
if(strstr($agent, 'MSIE')) {
$browserAgent="Internet Explorer";
}
else if(strstr($agent, 'Opera')) {
$browserAgent="Opera";
}
else if(strstr($agent, 'Firefox')) {
$browserAgent="Firefox";
}
else if(strstr($agent, 'Chrome')) {
$browserAgent = "Chrome";
}
else if(strstr($agent, 'Safari')) {
$browserAgent = "Safari";
}
else{
$browserAgent = "unknown";
}
return $browserAgent;
}
protected function getPlatform($agent): string{
$agent = strtolower($agent);
$platform = "";
if(strstr($agent, 'win')) {
$platform="windows";
}
else if(strstr($agent, 'linux')) {
$platform = "linux";
}
else{
$platform = "unknown";
}
return $platform;
}
protected function getMacAddress(): string{
$MAC = exec('getmac');
print_r($MAC);
$MAC = strtok($MAC, ' ');
return $MAC;
}
public function printCookieArray(){
global $cookieAndSessionArray;
print_r($cookieAndSessionArray);
}
public function setCookieByUserId($userId){
$userToken = $this->generateKey();
$browserAgent = $this->getBrowser($_SERVER['HTTP_USER_AGENT']);
$platform = $this->getPlatform($_SERVER['HTTP_USER_AGENT']);
$cookieAndSession = new CookieAndSession();
$cookieAndSession->cookie = $userToken;
$cookieAndSession->userId = $userId;
$cookieAndSession->browser = $browserAgent;
$cookieAndSession->os = $platform;
$cookieAndSession->timeToLive = 24 * 60 * 60;
@session_start();
$_SESSION["user"] = serialize($cookieAndSession);
setcookie('userToken',$userToken ,time() + 1 * 24 * 3600);
}
}
因为这里我用的是自定义MVC框架,在每次加载的时候,会调用如下start函数:
public static function start(){
self::setPath();
self::setConfig();
self::setSafe();
self::setUrl();
self::setAutoLoad();
self::setDispatch();
}
其中setSafe()就是新加的,作用是加载对应的php文件
private static function setSafe(){
$files = self::getAllFile(SAFE_PATH);
foreach($files as $file){
if(file_exists($file)){
include $file;
}
}
}
其中getAllfile是获取当前目录下的所有文件,如下:
private static function getAllFile($dir): array{
$retArray = array();
if(!is_dir($dir))
return $retArray;
$files = scandir($dir);
foreach ($files as $file){
$tmpFile = $dir . "/" . $file;
if(!is_dir($tmpFile)){
array_push($retArray, $dir . "/" . $file);
}
}
return $retArray;
}
其中SAFE_PATH如下:
ROOT_PATH在index.php中定义的,如下:
index.php
<?php
define("ROOT_PATH", str_replace("\\", "/", dirname(__DIR__)) . "/");
include ROOT_PATH . "core/App.php";
\core\App::start();
当用户点击登录后:
其userToken就为随机数了
后台登录校验是这样的:
public function check(){
$useName = trim($_POST["userName"]);
$password = trim($_POST["password"]);
$captcha = trim($_POST["captcha"]);
......
......
......
$cookieTool = new CookieTool();
$cookieTool->setCookieByUserId($user['user_id']);
$this->success("登录成功", '', 'dashboard', "index");
}
权限拦截如下:
public function __construct(){
include VENDOR_PATH . "smarty/Smarty.class.php";
$this->smarty = new \Smarty();
$this->smarty->template_dir = APP_PATH . P . "/view/";
$this->smarty->compile_dir = RESOURCES_PATH . "views";
if(strtolower(C) != "privilege"){
if(isset($_COOKIE['userToken'])){
@session_start();
$obj = unserialize($_SESSION["user"]);
if(strcmp($_COOKIE['userToken'], $obj->cookie) != 0){
$this->error("未登录,请先登录", "user", "privilege", "login");
}
$userModel = new UserModel();
$user = $userModel->getById((int)$obj->userId);
if($user){
return;
}
}
$this->error("未登录,请先登录", "user", "privilege", "login");
}
}
我正在尝试使用增强的 for 循环遍历 Iterable,但我无法确定何时处理最后一个值。 public void apply(Tuple key,
我正在使用以下代码在 Sheet2 的 A:H 范围内查找和替换 Sheet1 中存在的单词列表(ColA 用于 FIND 单词,ColB 用于 REPLACE 单词)。它执行这项工作,但非常缓慢。可
我正在使用 Hibernate (JPA2) hibernate.hbm2ddl.auto=update用于测试和 hibernate.hbm2ddl.auto=validate用于生产。 我想要做的
基本问题: 为什么我只能用 Scala 编写: println(10) 为什么我不需要写: Console println(10) 后续问题: 如何引入一个新方法“foo”,它像“println”一样
我正在尝试将 Maven 项目迁移到 Bazel,但在 Datanucleus 增强方面遇到了麻烦。 后 jar -file 已构建,Datanucleus 会查看其中的内部并执行一些字节码操作以增强
正在使用 css3 转换进行漂亮的导航。为此还编写了一些 javascript。 但不幸的是它看起来有点凌乱。你们能给我一些优化 javascript 代码的技巧吗? 笔--> http://code
我想将自定义任务绑定(bind)到默认构建器发布周期中。我想在项目编译、打包、标记和部署之后但在增加版本号并提交之前运行此代码。 我将如何融入发布周期的这一部分? 最佳答案 不幸的是,release
我使用ElasticSearch 6.6。我的应用程序通过从不同数据源提取数据来构建ES索引。搜索未指定数据源。它只是建立一个类似的查询: GET employerdata/_search { "
我正在使用此代码将“k1 = v1; k2 = v2; k3 = v3; kn = vn”字符串解析为映射。 qi::phrase_parse( begin,end,
我正在试图弄清楚作业的一部分,但我已经把头撞在墙上有一段时间了。我正在尝试将 DNA 序列转录为 RNA 序列。然而,我收到了 ArrayOutOfBoundsException。我不熟悉使用增强的
我需要对基于 python Google App Engine 的应用程序的警告进行分类。我从 GAE stackdriver 下载日志。我认为 GAE Stackdriver 错误报告位于 http
我有一个 django charField,通过 is_valid() 方法进行检查。用户应该在此字段中输入有效的逻辑表达式,因此我编写了一个解析方法,如果表达式不正确,该方法会引发异常。 如何增强
我编写了以下控制台应用程序,要求用户输入一天。 我需要一些帮助才能改进,以便他们为一周中的所有日子提供正确的答案。 如果用户输入除星期一以外的任何其他日期,则输出为“今天”、“昨天”、“明天”,并在这
我在使用带有 ES6 let 关键字的模块模式(扩充)时遇到错误。 这有效。 var Example = ( Example => { Example.name = ""; retur
我只是问是否线程安全可以使用 我明确指出“doSomething()”是线程安全的。 最佳答案 线程安全取决于您正在迭代的 Collection,而不是 enhanced for 的使用。如果 Col
我有一个非常符合 this Jquery demo 的要求,这是一个简单的购物车演示。基本上,我需要对该演示进行两项改进。 我需要文本输入以及可用的“产品”。因此,当我拖放其中一种产品时,文本字段应随
我正在三个表 messages、message_recipients 和 users 上运行查询。 messages表的表结构: id int pk message_id int message te
这个问题已经有答案了: In detail, how does the 'for each' loop work in Java? (29 个回答) 已关闭 4 年前。 由于增强的 for 循环是只读
我在 css 中制作了一个很酷的鼠标悬停,当父级鼠标悬停时它会显示动画 gif。 这是我的代码:http://codepen.io/clemeeent/pen/oggzMa 问题是我将有大约 40 天
目前,当使用 Knockout foreach 绑定(bind)时,您可以使用 $index 访问当前索引。我想让其他类似的功能可用于我的内部绑定(bind) - 例如: array(让我访问正在操作
我是一名优秀的程序员,十分优秀!