django+vue前后端分离项目部署
后端用的drf,使用的是uwsgi+nginx
进入服务器项目文件目录下,我的django项目放在了“/usr/myProjects/”目录下了。在manage.py同级目录下创建uwsgi.ini文件,配置如下:
测试效果命令:
如果访问:xxx.xxx.xxx.xx:8000 成功, 则uwsgi.ini配置成功
我的nginx.conf所在位置是“/etc/nginx/nginx.conf”
配置文件如下:
1、第一行
主要就是给nginx加权限,vue部署后使用history路由时会去掉地址后面的‘#’号,打包部署后不加权限会有bug。
2、如配置所示,有两个Server,分别部署了前端服务,和后端服务,值得注意的是两个Server用的是同一个服务器,监听的端口不同。
3、vue部署需要注意的是反向代理地址:
以及后面的端口问题
4、后端的Server需要注意location中的uwsgi_pass 后面的端口号要和uwsgi.ini中配的相同,否则监听不到
5、后端跨域问题。如果遇到跨域需要自己网上找配置,我的没遇到,可能是因为我在django的settings中配置了跨域。
6、django-suit后台管理样式崩了,需要改,但是api可以正常访问,这个有空再说
7、我开始后台监听的是8008端口,vue前端监听的是80端口,这样前端显示好看。然而问题出现了,虽然后台api可以正常访问,vue的本地开发环境也能正常运行且文字、图片资源均显示正常,但是前端vue打包线上部署后,文字信息显示正常,图片信息缺失8008端口,导致显示不出来。为图方便我选择了前端监听8008端口,后端监听80,部署后显示正常。原因不太清楚///////有空再说吧。
8、不要问我为啥都前后端分离了还部署到一个服务器上?穷,而且只是测试,没必要
9、此文仅适合入门
关于django后台admin(suit)缺失的修改(参考:django中文网: )
在环境中进入项目目录,需要收集css样式,在终端输入命令:
接下来你就回发现static文件中包含了css文件,此时再打开网站,样式显示正常
uWSGI 通过 xxx.ini 启动后会在相同目录下生成一个 xxx.pid 的文件,里面只有一行内容是 uWSGI 的主进程的进程号。
关于uwsgi,进入同届目录下
教训
获取不到环境,那就指定环境
另外:记得重启uwsgi,重启Nginx,实在不行就先把监听的端口kill掉再重启
暴力删端口:fuser -k 80/tcp
netstat -aptn命令行,查看所有开启的端口号
netstat -ntlp | grep 80 查看具体的端口是否使用
ps -ef | grep uwsgi 查看是否有uwsgi端口存在
Vue项目前后端分离下的前端鉴权方案
# Vue项目前后端分离下的前端鉴权方案
### 技术栈
前端Vue全家桶,后台.net。
### 需求分析
1. 前端路由鉴权,屏蔽地址栏入侵
2. 路由数据由后台管理,前端只按固定规则异步加载路由
3. 权限控制精确到每一个按钮
4. 自动更新token
5. 同一个浏览器只能登录一个账号
### 前端方案
对于需求1、2、3,采用异步加载路由方案
1. 首先编写vue全局路由守卫
2. 排除登录路由和无需鉴权路由
3. 登录后请求拉取用户菜单数据
4. 在vuex里处理菜单和路由匹配数据
5. 将在vuex里处理好的路由数据通过`addRoutes`异步推入路由
```
router.beforeEach((to, from, next) = {
// 判断当前用户是否已拉取权限菜单
if (store.state.sidebar.userRouter.length === 0) {
// 无菜单时拉取
getMenuRouter()
.then(res = {
let _menu = res.data.Data.ColumnDataList || [];
// if (res.data.Data.ColumnDataList.length 0) {
// 整理菜单路由数据
store.commit("setMenuRouter", _menu);
// 推入权限路由列表
router.addRoutes(store.state.sidebar.userRouter);
next({...to, replace: true });
// }
})
.catch(err = {
// console.log(err);
// Message.error("服务器连接失败");
});
} else {
//当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的菜单会自动进入404页面
if (to.path == "/login") {
next({
name: "index"
});
} else {
next();
}
}
} else {
// 无登录状态时重定向至登录 或可进入无需登录状态路径
if (to.path == "/login" || to.meta.auth === 0) {
next();
} else {
next({
path: "/login"
});
}
}
});
```
##### 注意
我这里无需鉴权的路由直接写在router文件夹下的index.js,通过路由元信息meta携带指定标识
```
{
path: "/err-404",
name: "err404",
meta: {
authentication: false
},
component: resolve = require(["../views/error/404.vue"], resolve)
},
```
上面说到路由是根据后台返回菜单数据根据一定规则生成,因此一些不是菜单,又需要登录状态的路由,我写在router文件夹下的router.js里,在上面步骤4里处理后台返回菜单数据时,和处理好的菜单路由数据合并一同通过`addRoutes`推入。
这样做会有一定的被地址栏入侵的风险,但是笔者这里大多是不太重要的路由,如果你要求咳咳,可以定一份字典来和后台接口配合精确加载每一个路由。
```
// 加入企业
{
path: "/join-company",
name: "join-company",
component: resolve = require([`@/views/index/join-company.vue`], resolve)
},
```
在vuex中将分配的菜单数据转化为前端可用的路由数据,我是这样做的:
管理系统在新增菜单时需要填写一个页面地址字段`Url`,前端得到后台菜单数据后根据`Url`字段来匹配路由加载的文件路径,每个菜单一个文件夹的好处是:你可以在这里拆分js、css和此菜单私有组件等
```
menu.forEach(item = {
let routerItem = {
path: item.Url,
name: item.Id,
meta: {
auth: item.Children,
}, // 路由元信息 定义路由时即可携带的参数,可用来管理每个路由的按钮操作权限
component: resolve =
require([`@/views${item.Url}/index.vue`], resolve) // 路由映射真实视图路径
};
routerBox.push(routerItem);
});
```
关于如何精确控制每一个按钮我是这样做的,将按钮编码放在路由元信息里,在当前路由下匹配来控制页面上的按钮是否创建。
菜单数据返回的都是多级结构,每个菜单下的子集就是当前菜单下的按钮权限码数组,我把每个菜单下的按钮放在此菜单的路由元信息`meta.auth`中。这样作的好处是:按钮权限校验只需匹配每个菜单路由元信息下的数据,这样校验池长度通常不会超过5个。
```
created() {
this.owner = this.$route.meta.auth.map(item = item.Code);
}
methods: {
matchingOwner(auth) {
return this.owner.some(item = item === auth);
}
}
```
需求4自动更新token,就是简单的时间判断,并在请求头添加字段来通知后台更新token并在头部返回,前端接受到带token的请求就直接更新token
```
// 在axios的请求拦截器中
let token = getSession(auth_code);
if (token) config.headers.auth = token;
if (tokenIsExpire(token)) {
// 判断是否需要刷新jwt
config.headers.refreshtoken = true;
}
// 在axios的响应拦截器中
if (res.headers.auth) {
setSession(auth_code, res.headers.auth);
}
```
对于需求5的处理比较麻烦,要跨tab页只能通过`cookie`或`local`,笔者这里不允许使用`cookie`因此采用的`localstorage`。通过打开的新页面读取`localstorage`内的`token`数据来同步多个页面的账号信息。`token`使用的`jwt`并前端md5加密。
这里需要注意一点是页面切换要立即同步账号信息。
经过需求5改造后的全局路由守卫是这样的:
```
function _AUTH_() {
// 切换窗口时校验账号是否发生变化
window.addEventListener("visibilitychange", function() {
let Local_auth = getLocal(auth_code, true);
let Session_auth = getSession(auth_code);
if (document.hidden == false Local_auth Local_auth != Session_auth) {
setSession(auth_code, Local_auth, true);
router.go(0)
}
})
router.beforeEach((to, from, next) = {
// 判断当前用户是否已拉取权限菜单
if (store.state.sidebar.userRouter.length === 0) {
// 无菜单时拉取
getMenuRouter()
.then(res = {
let _menu = res.data.Data.ColumnDataList || [];
// if (res.data.Data.ColumnDataList.length 0) {
// 整理菜单路由数据
store.commit("setMenuRouter", _menu);
// 推入权限路由列表
router.addRoutes(store.state.sidebar.userRouter);
next({...to, replace: true });
// }
})
.catch(err = {
// console.log(err);
// Message.error("服务器连接失败");
});
} else {
//当有用户权限的时候,说明所有可访问路由已生成 如访问没权限的菜单会自动进入404页面
if (to.path == "/login") {
next({
name: "index"
});
} else {
next();
}
}
} else {
// 无登录状态时重定向至登录 或可进入无需登录状态路径
if (to.path == "/login" || to.meta.auth === 0) {
next();
} else {
next({
path: "/login"
});
}
}
});
}
```
经过需求5改造后的axios的请求拦截器是这样的,因为ie无法使用`visibilitychange`,并且尝试百度其他属性无效,因此在请求发出前做了粗暴处理:
```
if (ie浏览器) {
setLocal('_ie', Math.random())
let Local_auth = getLocal(auth_code, true);
let Session_auth = getSession(auth_code);
if (Local_auth Local_auth != Session_auth) {
setSession(auth_code, Local_auth, true);
router.go(0)
return false
}
}
```
这里有一个小问题需要注意:因为用的`local`因此首次打开浏览器可能会有登录已过期的提示,这里相信大家都能找到适合自己的处理方案
### 结语
经过这些简单又好用的处理,一个基本满足需求的前后端分离前端鉴权方案就诞生啦
(一)基于 vue-element-admin 前端与后端框架搭建
通过 src/settings.js 进行全局配置:
get-page-title.js 在 src/permission.js 中被引用
修改 package.json
执行命令启动
中间件是一个函数,请求和响应周期中被顺序调用
写一个中间函数
调用中间件注意事项:
应用如何响应请求的一种规则
响应 / 路径的 get 请求
响应 / 路径的 post 请求
规则主要分两部分
通过自定义异常处理中间件处理请求中产生的异常
使用时需要注意两点:
浏览器输入
安装 boom 依赖,最大的好处是可以快速的帮我们生成一些异常信息
app.js
创建 router 文件夹,创建 router/index.js
创建 router/user.js
创建 router 文件夹,创建 router/constant.js
启动,访问根路径
这里指定的路由的前缀 /user 所有访问路径前要加 /user
访问
访问一个不存在的路径
自定义路由异常处理中间件
注意两点:
访问一个不存在的路径时,会返回一个 json 的结果,方便前端做出处理
前端使用vue后端使用tp5的前后端分离的项目如何在宝塔上部署,请大佬指点一下,第一次接触?
前端工程师是互联网时代软件产品研发中不可缺少的一种专业研发角色。从狭义上讲,前端工程师使用 HTML、CSS、JavaScript 等专业技能和工具将产品UI设计稿实现成网站产品,涵盖用户PC端、移动端网页,处理视觉和交互问题。从广义上来讲,所有用户终端产品与视觉和交互有关的部分,都是前端工程师的专业领域。[1]
中文名
前端开发工程师
所属学科
计算机科学与技术
核心技术
HTML、CSS、JavaScript、jQuery
主流框架
React.js、Vue.js、Angularjs
快速
导航
发展方向
词条来源
前端是一个相对比较新的行业,互联网发展早期(1995年~2005年)是没有专业的前端工程师的。随着互联网的发展,大约从2005年开始,正式的前端工程师角色被行业认可,到了2010年,互联网开始全面进入移动时代,前端工程师的地位越来越重要,前端领域的技术发展也越来越快,各种新的思想、设计模式、工具和平台都快速发展,对前端工程师的技能要求也越来越高。[1]
发展方向
专家方向
经过几年的技术积累,大量的项目历练,很自然地就朝着专家的方向过渡了。技术人普遍具有的一个特征就是不喜欢管一些乱七八糟的事,更愿意钻研感兴趣的技术,解决一些技术难题。走专家路线可能是大多数技术人的选择。
前端vue+后台管理系统怎么上线?
想要将前端Vue + 后台管理系统上线,需要以下步骤:
将前端Vue程序打包为静态文件,使用npm或yarn运行命令: npm run build或yarn build。
在你的服务器上,可以使用FTP或SCP等工具将静态文件上传到服务器。
配置服务器以在Web服务器(例如Apache或Nginx)上提供静态文件。
将后台管理系统部署到服务器上(例如Node.js),并确保其在需要时访问Vue的静态文件。
配置Web服务器以将所有HTTP请求转发到服务器上运行的后台管理系统。
配置Web服务器以使用SSL证书(如Let’s Encrypt)启用HTTPS加密连接(推荐)。
通过这些步骤,您可以将Vue +后台管理系统部署到生产环境中并运行。
前端vue与后端Thinkphp在服务器的部署
vue在服务端部署时,我们都知道通过npm run build 指令打包好的dist文件,通过http指定是可以直接浏览的,Thinkphp通过域名指向index.php文件才可以浏览。要使前端正常调用后端数据,有两种方法:1、前端跨域调用后端数据,2、前端打包文件部署在后端的服务器文件夹下(同域)。
web服务器: apache
一、跨域
在服务器配置站点:
在路径/home/www/ 下创建test项目文件夹,用来放项目文件。
找到httpd-vhosts.conf文件配置站点
前端站点:
ServerName test.test.com
DocumentRoot "/home/www/test/dist"
DirectoryIndex index.html
后端站点:
ServerName test.testphp.com
DocumentRoot "/home/www/test/php"
DirectoryIndex index.php
将前端打包好的dist文件放在/home/www/test/ 文件夹下,运行可浏览,当路径改变时,刷新会出现404错误。此时dist文件下创建一个.htaccess文件,当路径不存在时,路径指向能解决此问题。
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
在/home/www/test文件夹下创建项目根目录php文件夹,将thinkphp文件放在php下。TP5的入口文件在public文件下,在这将public下的入口文件index.php挪到php文件夹下(个人习惯将入口文件放在项目根目录), 后端绑定Index模块。
前端调用后端接口,存在跨域,跨域解决方法有好几种,在这我将在后端php做配置,解决跨域问题,在公用控制器设置跨域配置:
class Common extends Controller
{
public $param;
// 设置跨域访问
public function _initialize()
{
parent::_initialize();
isset($_SERVER['HTTP_ORIGIN']) ? header('Access-Control-Allow-Origin: '.$_SERVER['HTTP_ORIGIN']) : '';
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
header("Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, authKey, sessionId");
$param = Request::instance()-param();
$this-param = $param;
}
}
前端调用登录接口: this.axios.post('', {user: '', password: ''})。
(可在webpack.base.conf.js文件下可定义接口:)
二、同域
后端配置同上,公共配置器中的header配置注释。将前端的dist文件下的所有文件(包含.htaccess),放在php文件夹下。将后端index控制器的index方法的路径重定向php下的index.html文件:
namespace app\index\controller;
use think\Controller;
class Index extends Controller
{
public function index() {
$this-redirect('/index.html');
}
}
前端调用登录接口: this.axios.post('/index.php/base/login', {user: '', password: ''})
转自: