1. 程式人生 > 其它 >portal--內實現免密登陸其他系統的方案

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 [email protected]。否則舊版本+新寫法會報錯: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/