已经很久没有写文章了,此次借着做这个小项目的机会,重新update自己写代码的技能;自从转岗后比较少写代码,感觉都有点生疏了;好了,话不多话,进入本次正题;我先介绍下开发这个项目的背景,因为我们公司是初创企业,公司的项目基本上都是为了辅助企业管理及运营而开发;团队也是只有三五个人的小团队,我在这个团队主要负责产品管理及需求跟进。因为运营的原因,公司同时经营了几个品牌,每个品牌针对不同的市场,所以公司虽然不大,但公司的项目却多而杂。一直以来,系统更新都是整个团队最为头痛的事情,因为品牌的差异化,导致项目的维护成本大大增加。所以我跟项目组提了一个需求就是需要一个可以管理系统更新包及自动更新的系统。因为项目组同事还有一堆任务要做,这个需求提了几周了都还没有开始落地,最后决定自己先写一个简单的出来过渡(一开始想百度一个现成的,但一直没找到有合适,也有可能关键词没用对,哈哈);

目前公司的项目基本上都是使用PHP语言开写,近期新开的一个项目采用的是vue+php的形式,所以为了方便后续的维护及扩展,这个项目我还是选择了vue+php的组合。还有一个原因就是,之前我没接触过vue,想借这个机会了解下这个前端新宠;

最后确定下来项目框架如下:

前端:Vue 2.5.2+Element UI 2.12

后端:Codeigniter 3.1.10

数据库:Mysql 5.7.0

本地开发环境:PHP 7.0.5 + Apache 2.4

OK,进入正题;我给该项目取的名称为upgrade-web,由于upgrade-web采用前后端分离,整个项目自己在搞,所以我先从后端开始搞起;

首先下载最新稳定版的CI框架,CI框架是目前PHP框架中相对干净的一个,除了框架必要的功能,什么都没有提供了。选择这个框架的原因也在于自己想重温下以前写代码的逻辑。从零开始搭项目。

CI框架的应用目录结构如下:(只罗列了我们在项目中会使用到的相关文件,框架的核心目录及文件用途,有需要的朋友自行去官网查看,本文不做过多叙述)

upgrade-idcims
|-----application           应用目录  |-----core              重写框架的核心类|-----helpers           重写框架的辅助函数  |-----libraries         自定义类库  |-----language          语言包  |-----config            应用配置  |-----config.php    应用相关的配置|-----database.php  数据库相关的配置|-----autoload.php  设置自动加载类库的配置|-----constants.php 常量配置文件  |-----routes.php    路由配置文件  |-----controllers       控制器目录   |-----models            模型目录   |-----views         视图目录  |-----cache         存放数据或模板的缓存文件  |-----errors            错误提示模板  |-----hooks         钩子,在不修改系统核心文件的基础上扩展系统功能  |-----third_party       第三方库  |-----logs          日志
|-----system                框架程序目录
|-----index.php             入口文件

在写代码之前,我们先设计下表结构;upgrade-web的需求很简单,逻辑也不复杂,所以我们需要的表结构也不复杂;按前期能预计到的需求我们先设计三张表;用户表,更新包管理表,客户端管理表;

用户表:

CREATE TABLE `ui_user` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`username` varchar(100) NOT NULL DEFAULT '' COMMENT '用户名',`password` varchar(255) NOT NULL DEFAULT '' COMMENT '密码',`nickname` varchar(20) NOT NULL DEFAULT '' COMMENT '昵称',`token` varchar(255) DEFAULT NULL COMMENT '登录token',`activate_time` int(11) DEFAULT NULL COMMENT '活动时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;INSERT INTO `ui_user` (`id`, `username`, `password`, `nickname`, `token`, `activate_time`)
VALUES(1, 'tim', 'bmB/xRUAs8t9gz1C6/gt/iZoRreGyK+Y9JXRWVr8YSLlZk5doX2mzFOeiEwKgDQWYae033Fk3betlHk9D5tVqM5HRh+GanzWz7DemvynSzyPw3wtA6IznqYF+t740j8+SHyFspKlqfYydHpwL0yh0Fy731fbXWSbtGdn2EhxI+Q=', '', '90b460c429255c2f80c9dedbdcb9ea158c37d16d', 1573612152);

更新包管理表

CREATE TABLE `ui_upgradepackage` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`package_path` text COMMENT '更新包路径',`upgrade_description` text COMMENT '更新说明',`can_upgrade` tinyint(1) DEFAULT '1' COMMENT '允许更新',`note` text COMMENT '备注',`version` double DEFAULT NULL COMMENT '版本号',`git_version` varchar(255) DEFAULT NULL COMMENT 'git 版本号',`upload_time` int(11) DEFAULT NULL COMMENT '上传时间',`filename` varchar(255) DEFAULT NULL COMMENT '文件名',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

客户端管理

CREATE TABLE `ui_clientmanager` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`client_name` varchar(255) DEFAULT NULL COMMENT '客户端名称',`client_url` varchar(255) DEFAULT NULL COMMENT '客户端地址',`current_version` double DEFAULT NULL COMMENT '当前版本',`pre_version` double DEFAULT NULL COMMENT '上一个版本',`auth_time` bigint(20) DEFAULT NULL COMMENT '授权时间',`expire_time` bigint(20) DEFAULT NULL COMMENT '到期时间',`lastupdate_time` bigint(20) DEFAULT NULL COMMENT '最后更新时间',`update_status` varchar(50) DEFAULT 'unknow' COMMENT '更新状态(更新成功/正在更新/更新失败)',`allow_server` varchar(50) DEFAULT NULL COMMENT '可管理服务器数量',`allow_line` varchar(50) DEFAULT NULL COMMENT '可管理线路数量',`note` text COMMENT '备注',`last_version` double DEFAULT NULL COMMENT '最新版本',`client_ip` varchar(25) DEFAULT NULL COMMENT '服务器IP',`auth_code` varchar(255) DEFAULT NULL COMMENT '授权code',`init_auth` tinyint(1) DEFAULT '2' COMMENT '是否初始授权 1=是2=否',`auth_code_shadow` varchar(255) DEFAULT NULL COMMENT '授权code的影子',`download_code` varchar(255) DEFAULT NULL COMMENT '下载码',`download_code_time` int(11) DEFAULT NULL COMMENT '下载码超时时间',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

好了,框架有了,表结构也有了,现在可以开始码代码了。因为是自己一个人开发,并且需求相对比较明确,故直接省去了画功能流程的步骤,直接开干了,哈哈。

做为一个标准的后台管理系统,登录功能是一定要的吧,来让我们先从一个登录功能开始吧。

哦,在些之前还有一个事要先做,CI框架作为upgrade-web的后端,为前端提供数据接口,那我们就需要做好一些接口约定规范。统一接口数据返回格式;

我们在upgrade-web ----> libraries 目录下创建一个IResponse.php文件,代码如下:

<?php/*** @Author: Tim* @Date:   2019-11-12 11:34:49*/
class IResponse {/*** [returnJson 返回json数据格式]* @Author Tim* @param  array  $data    [业务数据]* @param  string $result  [执行结果 success/faild]* @param  string $type    [结果类型 data/info/warning/error]* @param  string $message [提示信息]* @return string*/public static function returnJson($data=[], $result='success', $type='data', $message=''){$response = ['result'=>$result, 'data'=>$data, 'type'=>$type, 'message'=>$message];return $response;}/*** [responseJson 返回json数据格式]* @Author Tim* @param  array  $data    [业务数据]* @param  string $result  [执行结果 success/faild]* @param  string $type    [数据类型 data/info/redirect]* @param  string $message [提示信息]* @return string*/public static function responseJson($data=[], $result='success', $type='data', $message='') {echo json_encode(self::returnJson($data, $result, $type, $message));}
}

既然有登录功能,那自然需要有一个控制类判断用户是否登录啦。所以我们创建一个权限控制类来帮我们完成一些会话及系统权限相关的操作(这个类后面再扩展其它权限认证,目前只做会话管理及判定)。同样在 upgrade-web ----> libraries 中创建一个Auth.php 文件,代码如下

<?php/**
* 系统权限控制核心代码
*
* 系统用户民权限分配及判权操作
* @author      Tim
* @Date:   2019-11-12 11:36:23
*/
defined('BASEPATH') OR exit('No direct script access allowed');class Auth
{private $_ci;           // CI 句柄private $_islogin = false;     // 是否已登录private $_updatetokentime = 3600; // 更新token时间private $_user;         // 当前登录用户private $authorization;       // 当前活跃tokenpublic function __construct(){$this->_ci = & get_instance();  // 获取CI句柄$this->_ci->load->library('session');$this->_ci->load->model('M_user','m_user');$this->authorization = $this->_ci->input->get_request_header('Authorization');}/*** [isLogin 判断是否已登录]* @Author Tim* @return bool*/public function isLogin(){// todo: 加入用户是否已登录检测$authorization = $this->_ci->session->userdata('authorization');if(empty($authorization)) {$this->_islogin = false;} else {// 判断token 是否一致,一个会话只允许一个token存在,新token替换旧tokenif(isset($authorization['token']) && $this->authorization == $authorization['token']) {$this->_user = $authorization['user'];if(isset($this->_user['id']) && !empty($this->_user['id'])) {if((time() - $this->_user['updatetokentime']) > $this->_updatetokentime) {$this->_islogin = false;$user = $this->_ci->m_user->findById($this->_user['id']);      // 从数据库获取用户数据if(isset($user['token']) && $user['token'] == $this->_user['token']) {$token = sha1(time().rand());// 更新tokenif($this->_ci->m_user->update($user['id'], ['token'=>$token])) {$this->_user['token'] = $token;$this->_user['updatetokentime'] = time();$this->updateUserSession($token);$this->_islogin = true;}}} else {// token在有效期内$this->_islogin = true;}}} else {// 清除当前会话token$this->_ci->session->unset_userdata('Authorization');$this->_islogin = false;}}return $this->_islogin;}/*** [login 登录]* @Author Tim* @param  array $user [用户信息]* @return bool*/public function login($user){$this->_user = $user;$this->_user['activate_time'] = time();$this->_user['updatetokentime'] = time();$this->_user['token'] = sha1(time().rand());   // 更新token// 更新用户登录信息if($this->_ci->m_user->update($this->_user['id'], ['activate_time'=>$this->_user['activate_time'],'token'=>$this->_user['token']])){$this->updateUserSession($this->_user['token']);return true;}return false;}/*** [logout 登出]* @Author Tim* @return void*/public function logout(){$this->_ci->session->sess_destroy();return $this->_ci->m_user->update($this->_user['id'], ['activate_time' => time(),'token'=>'']);     // 更新退出时间}/*** [getXToken 获取当前登录token]* @Author Tim* @return string*/public function getXToken(){return $this->authorization;}/*** [getUser 获取当前用户登录信息]* @Author Tim* @return array*/public function getUser(){$authorization = $this->_ci->session->userdata('authorization');return $authorization['user'];}/*** [updateUserSession 更新用户会话信息]* @Author Tim* @param string token 登录token* @return void*/private function updateUserSession($token){$this->authorization = $token;header('Authorization: '.$token);$session_data = ['authorization' => ['token'=>$token, 'user'=>$this->_user]];$this->_ci->session->set_userdata($session_data);}
}

现在我们可以写登录的逻辑代码了。为了尽快完成该项目,所有非业务逻辑的代码都简单处理化,后面再抽时间完善。

在 upgrade-web ----> controllers 中创建Login.php

<?php
defined('BASEPATH') OR exit('No direct script access allowed');class Login extends BaseController {public function __construct(){$this->__needlogin__ = false;parent::__construct();$this->load->model('M_user',"m_user");       // 加载用户模型}public function index(){if($this->auth->isLogin()) {// 已登录IResponse::responseJson([], 'success', 'info', $this->lang->line('logined'));} else {// 未登录$username = trim($this->input->post('username'));$password = trim($this->input->post('password'));$password = $this->rsa->privEncrypt($password);log_message('error', $password);$muser = $this->m_user->verifyUser($username, $password);if(empty($muser)) {sleep(1);IResponse::responseJson([], 'faild', 'info', $this->lang->line('incorrect_account'));return;}if($this->auth->login($muser)) {IResponse::responseJson([], 'success', 'info', $this->lang->line('login_success'));} else {IResponse::responseJson([], 'faild', 'info', $this->lang->line('login_faild'));}}}/*** [logout 登出]* @Author Tim* @return void*/public function logout(){if($this->auth->logout()) {IResponse::responseJson([], 'success', 'info', $this->lang->line('logout_success'));} else {IResponse::responseJson([], 'faild', 'info', $this->lang->line('logout_faild'));}}
}

登录控制器中只包含了两个方法,登入与登出;结合权限控制类,我们可以使用postman工具测试登录功能。

今天先更新到这里,明天继续;

【第一更】WEB系统版本及自动更新管理系统相关推荐

  1. 禁止win7系统flash插件自动更新教程【系统天地】

    使用电脑浏览器观看视频的时候,总会遇到浏览器弹出adobe flash player安装的提示窗口,这个浏览器的插件可让各大视频网站都对它进行支持,一些用户不想flash插件自动更新,如何禁止设置呢? ...

  2. 【Windows】Win 10 1809 版系统彻底禁用自动更新的办法

    Win 10 1809 版系统彻底禁用自动更新的办法   Win10 升级到1809版后,多了一个"Windows Update Medic Service"服务,该服务是&quo ...

  3. 联想android系统怎么关闭自动更新,系统自动更新怎么关闭|关闭系统更新设置方法-系统城...

    2019-02-14 14:58:54 浏览量:2540 microsoft更新附带着很多其他的产品,而这些产品是用户们不需要的程序,系统经常会自动更新某些软件,非常烦人.针对这一问题,我们最好的办法 ...

  4. Windows10系统彻底禁止自动更新

    Windows10经常一段时间会自动更新,而且每次更新的时间又长,作为个人电脑,其实也不需要打什么补丁,我的电脑一直都是裸奔状态 一般的解决办法就是来到Windows更新设置 此设备上的更新安装只能临 ...

  5. Win10系统彻底关闭自动更新方法——亲测有效

    windows 系统自动更新问题解决方法 前段时间开始频繁使用电脑,注意到了这个以前不太在意的问题. 第一个方法: 禁用Windows Update服务 同时按下键盘 Win + R,打开运行窗口,输 ...

  6. vue 实现app项目版本迭代自动更新 热更新

    需求: app打开时自动检测是否是最新版本,如果不是出现弹框,点击升级 效果图: 实现步骤: 一,准备工作 声明一个bol值VersionFlag控制版本升级弹窗的开关,默认关闭 Website: 更 ...

  7. svn版本信息自动更新到源代码

    背景:在线上代码和线下代码不一致时,用这个时间先比对是很重要的,首先看时间确定是不是最新的代码,再进行问题排查是很有必要的.Subversion 的 svn:keywords 是一个非常有用的功能,可 ...

  8. win10一装MATLAB就蓝屏,安装系统之后win10自动更新就蓝屏

    谢谢回复. 如果您可以帮忙导出[事件查看器],这样可以更好的协助分析您的情况: 1. 按WINDOWS键,搜索框中输入并打开[事件查看器] 2. 展开[事件查看器],右键单击要将其存档的日志,选择[另 ...

  9. android系统签名app自动更新,【Android 进阶】Apk 使用系统签名

    刚入职的时候,固件中 app 需要在源码中编译,不是很理解,为什么不使用 IDE 编译,然后 copy 到 /system/app/*,咨询导师,得到反馈 app 需要使用系统的权限 在 Androi ...

最新文章

  1. 2020中国年度AI评选结果揭晓!领航企业、商业人物、创新产品……AI落地最佳参考就在这里...
  2. start for graduate studies career path
  3. 【随手拍解救单身男女(1)】数据分析师书豪
  4. java 年计算_java实现计算某年某月的天数
  5. STM32那点事(4)_DMA(上)
  6. 自己动手写DB数据库框架(增)
  7. J1939标准概述【小白入门】
  8. CREO:CREO软件之零件【模型】形状之拉伸、旋转、旋转混合的简介及其使用方法(图文教程)之详细攻略
  9. 斯坦福NLP名课带学详解 | CS224n 第1讲 - NLP介绍与词向量初步(NLP通关指南·完结)
  10. 扩展欧几里得算法——Python详解
  11. 问题:加入导航条后webView的UIWebBrowserView位置偏移
  12. pytorch torch.nn到底是什么?
  13. aws lambda_借助AWS Elastic Beanstalk轻松进行Spring Boot部署
  14. 【MySQL】九、数据排序(升序 order by ... asc,降序 desc),sql语句的执行顺序
  15. 能力提升的僵化、优化、固化过程
  16. 论文翻译-Scene Text Detection and Recognition: The Deep Learning Era
  17. 团队执行力(企业管理培训)
  18. 国际认可度最高的验厂:BSCI
  19. 一些生活中简单可用的技能--十分钟学会,终生受益
  20. Chrome浏览器多开

热门文章

  1. 手动搭建一个RAP2
  2. 全球首富离婚,近万亿元家产该怎么分
  3. 快速云:五分钟了解几款磁盘测试与IO查看的工具
  4. swift版左右侧滑菜单
  5. 刷脸支付给人耳目一新的场景体验
  6. 2015年斯坦福创业课程-技术驱动的闪电式扩张(Blitzscaling) 18: Airbnb
  7. 分布式认知在计算机应用系统,分布式任务分布式认知对高校计算机基础课程影响论文...
  8. 分析了一下360安全卫士的 HOOK(二)——架构与实现(zt)
  9. 痛苦煎熬的202301-07
  10. latex上编写论文转到word上