小陆同学

python 中文名:蟒蛇,设计者:Guido van Rossum

导航

portal--内实现免密登陆其他系统的方案

 
  首先说一下需求,我们有2套前后端的项目要做集成,其中一套使用开源系统scui作为portal,另外一套A项目以iframe的形式加到portal菜单里去。并且想要实现从portal跳转A项目时候是免密的,无需再次登陆。
  这时候了解到vue的localstorage存的信息在同一个域名,同一个端口的情况下,可以共享localstorage,只需要将2个系统的localstorage的key存成一致的,且value形态是一致的。
  我们的方式是:借助caddy启动portal前+后端,caddy端口40080;用caddy再将A项目的前+后端启动,caddy端口50080。这时再配置nginx,用nginx的1个端口代理这两个caddy的端口,通过nginx的location来分别分发到40080和50080。
  这样做的好处是:2个系统可以使用各自的端口单独使用,也可以通过portal免密到A项目。可独立可共存。
然后在代码的层面作出修改,为什么需要修改代码?举例,2个系统的登陆接口可能都是/api/auth/login,那么用nginx的这个端口去访问的话,可能会转发错误。所以需要给A项目增加一级url,比如:/aos/api/auth/login。通过这样的方式实现了2个系统的嵌套使用。

项目部署

# 
安装caddy:(mac:brew install caddy)
或者下载https://caddyserver.com/download
caddy是go语言的,免安装,linux里都能拷贝过去就用。

 

-----------nginx的配置--------------------

 
server {
    listen 80 default_server;
    server_name localhost 10.10.10.10;
 
    location / {
        proxy_pass http://127.0.0.1:40080;
    }
    location /aos/{
    proxy_pass http://127.0.0.1:50080;
    }
}

 

portal部署

--------portal项目配置bin/Caddyfile------

{
    admin off
}
:40080 {
handle /api/* {
    reverse_proxy /api/* 127.0.0.1:8000
}
handle {
    root * /mnt/it-ops-portal-platform/web
    file_server
    try_files {path} /index.html
}
log {
    output file bin/logs/httpd.log
}
}

 

----------restart.sh-------------

#!/bin/bash
source /etc/profile
programpath=/mnt/portal
cd ${programpath}; pwd
# web & vue
ps aux | grep ${programpath}/bin/caddy | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 1
${programpath}/bin/caddy start --config ${programpath}/bin/Caddyfile
# api
ps aux | grep ${programpath}/manage.py | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 1
nohup python3 ${programpath}/manage.py run >/dev/null 2>&1 &

 

A项目部署

-----------A项目bin/Caddyfile----------

{
admin off
}
:50080 {
handle /aos/api/* {
    reverse_proxy /aos/api/* 127.0.0.1:5000
}
handle {
    root * /mnt/it-ops-product-center-platform/web
    encode gzip    # 前端静态文件压缩gzip后,需要做配置才能访问到压缩后的文件
    file_server
    try_files {path} /index.html
}
log {
    output file bin/logs/httpd.log
}
}

 

---------A项目restart.sh-------

#!/bin/bash
source /etc/profile
programpath=/mnt/A
cd ${programpath}; pwd
# web & vue
ps aux | grep ${programpath}/bin/caddy | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 1
${programpath}/bin/caddy start --config ${programpath}/bin/Caddyfile
# task
ps aux | grep "celery -A app.main.service.celerytask.celery worker -l info --workdir ${programpath}" | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 1
nohup celery -A app.main.service.celerytask.celery worker -l info --workdir ${programpath} >/dev/null 2>&1 &
# api
ps aux | grep ${programpath}/manage.py | grep -v grep | awk '{print $2}' | xargs kill -9
sleep 1
nohup python3 ${programpath}/manage.py run >/dev/null 2>&1 &

 

上代码:

vue将所有请求加上一级url

-------router/index.js-----

export default new Router({
mode: 'history',
# 要添加的路由
base: '/aos/',
routes: [

 

------config/index.js------

module.exports = {
    # 要添加的路由
    publicPath: '/aos/',
    build: {
        env: require('./prod.env'),
        index: path.resolve(__dirname, '../dist/index.html'),
        assetsRoot: path.resolve(__dirname, '../dist'),
        # 静态资源路径,通过npm run build之后,原先dist目录下的static目录前会增加一层目录:dist/aos/static… dist/index.html
        assetsSubDirectory: 'aos/static',
        assetsPublicPath: '/',
        productionSourceMap: true,  # 这里改为了false,不生成map文件
        productionGzip: false,  # 这里后来改了true,将前端静态文件压缩,可以有效的减少vue页面首次加载的白屏时间,参考:https://blog.csdn.net/weixin_44668908/article/details/109157082
        productionGzipExtensions: ['js', 'css'],
        bundleAnalyzerReport: process.env.npm_config_report
},
    dev: {
        env: require('./dev.env'),
        port: 8082,
        autoOpenBrowser: true,
        # 静态资源路径
        assetsSubDirectory: 'aos/static',
        assetsPublicPath: '/',
        proxyTable: {
        },
        cssSourceMap: false,
}                                

 

flask socketio官方文档

https://flask-socketio.readthedocs.io/en/latest/api.html?highlight=path#flask_socketio.SocketIO
flask 怎么接收这个请求呢?
没改路由之前是OK的,但是改的过程中发现:可能报跨域问题,404问题,等等,然后才发现,flask_socket也自带path属性,前后端的path值保持一致即可

------------manage.py-------------

 
from flask_socketio import SocketIO,send,emit
app = create_app(os.getenv('BOILERPLATE_ENV') or 'dev')
# flask http请求的base_url
app.register_blueprint(blueprint,url_prefix='/aos')
CORS(app, resources=r'/*')
CORS(app,supports_credentials=True)
# path为socket.io的路由
socketio = SocketIO(app,cors_allowed_origins='*',path='/aos/api/socket/')
# jenkins应用构建
@socketio.on('jenkins_build')
def jenkins_build_start(message,sid):
    message = json.loads(urllib.parse.unquote(message))
    message['action'] = 'can_deploy_app'
    response = jenkins_job_build(message)
    if response.get('code')==200:
        thread = socketio.start_background_task(target=background_thread_get_build_info,kwargs=response,sid=sid)
    else:
        socketio.emit('jenkins_build_console', {'text': response},room=sid,broadcast=True)
# 定时获取jenkins构建日志
def background_thread_get_build_info(sid,**kwargs):
    while True:
        check_args = kwargs.get('kwargs').get('msg')
        tail_output,status = check_app_build_consolelog(check_args)
        if tail_output:
          tail_output = tail_output+'<br/>加载中…'
          socketio.emit('jenkins_build_console', {'text': {'code':200,'msg':tail_output}},room=sid, broadcast=True)
          print("status",status)
          if status :
              tail_output = tail_output + '<br/>任务完成!'
              socketio.emit('jenkins_build_console', {'text': {'code': 200, 'msg': tail_output}},room=sid,broadcast=True)
              build_result = {}
              build_result['log_detail'] = tail_output
              build_result['status'] = status
              build_result['app_name'] = check_args.get('app_name')
              build_result['job_id'] = check_args.get('job_id')
              build_result['app_id'] = check_args.get('app_id')
              task = save_jenkins_build_job_log(build_result)
              task = save_jenkins_build_job_log.delay(build_result)
              back_up_build_production_backage.delay(check_args)
            break
    socketio.sleep(5)
@socketio.on('connect', namespace='/aos')
def test_connect():
    print('=====socketio====')
    socketio.emit('my response', {'data': 'Connected'})
@socketio.on('disconnect', namespace='/aos')
def test_disconnect():
    print('Client disconnected'

 

 

Socket io的默认路由改成指定前缀的url

----------config/urls.js----------

export default {
    // api请求地址
    // API_URL: 'http://127.0.0.1:5000/aos',
    // // socketio请求地址
    // SOCKET_URL: 'http://127.0.0.1:5000'
    API_URL: 'http://1.1.1.1:50080/aos',
    SOCKET_URL: 'http://1.1.1.1:50080'
}

 

-----------main.js---------

socketio对象可以加的一些属性:https://blog.csdn.net/ZYS10000/article/details/122737466
import URLS from '../config/urls'
import VueSocketio from 'vue-socket.io'
// vue-socket.io 2.1.1旧版本引用方式
// Vue.use(VueSocketio,URLS.API_URL,store);
// URLS.SOCKET_URL = http://127.0.0.1:5000
// 如下配置需要将版本升级:npm install vue-socket.io@3.0.7。否则旧版本+新写法会报错:Uncaught TypeError: Vue2.default is not a constructor
Vue.use(new VueSocketio({
  debug:true,
  //# 不自动链接,指定页面的指定场景再链接
  autoConnect: false,
  connection:URLS.SOCKET_URL,
  vuex:{
    store,
  },
  options:{
    //# 通过path属性可以将socketio原来默认的url中/socket.io/部分替换成path变量
    path:'/aos/api/socket/'
  }
}))

 

 
---------vue指定页面-------
 
created() {
// this.$socket.connect();
// this.$socket.open();
  this.handleClick()
},
sockets:{
  // 接收应用构建日志
  jenkins_build_console: function(val){
  if (val['text']['code']!=200){
    alert(val['text']['msg'])
  }else{
    document.getElementById('app_build_logs').innerHTML=val['text']['msg']
    // 监听滚动事件
    document.querySelector(".box").addEventListener('scroll',this.scrolling)
    this.scrollToBottom();
    }
  },
},
methods: {
 
  // 执行构建
  execute_built() {
  // 发布分支和回滚版本必选
  if (!this.form.branch){
    alert('请选择发布分支')
    return false
  }
  # 开启socket io
  this.$socket.open();
  var params = {
    app_id: this.app_id,
    branch: this.form.branch,
    username: JSON.parse(localStorage.getItem('username'))
  }
  document.getElementById('app_build_logs').innerHTML=''
  console.log(this.$socket.id)
  this.$socket.emit('jenkins_build',encodeURI(JSON.stringify(params)),this.$socket.id);
 
  document.getElementById('app_build_logs').innerHTML='加载中...'
},

 

遇到的问题:

nginx 托管aos的静态文件后,通过portal访问,console了错误的日志:NET::ERR_CONTENT_LENGTH_MISMATCH 200 (OK)
百度的原因都是权限问题,
给我的nginx授权后,没有效果:sudo chmod -R 777 /usr/local/etc/nginx/*
 
最后,哈哈哈哈,竟然:sudo nginx,成功了,显然还是权限的问题,只不过授权错了
 
参考文档:https://www.freesion.com/article/4209772219/

posted on 2022-05-27 17:56  小陆同学  阅读(446)  评论(0编辑  收藏  举报