• 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/
  • 相关阅读:
    HashMap 和 Hashtable 的区别
    提高利用运行(安装)内存
    MyEclipse、Hbuilder、Idea快捷键
    本地安装MySQL详细教程
    MyEclipse/Eclipse相关设置
    MyEclipse 10导入JDK1.7或1.8
    Oracle视图(和Mysq一样l)
    Oracle事务
    MySql综合知识汇总
    Mysql存储过程
  • 原文地址:https://www.cnblogs.com/lutt/p/16318621.html
Copyright © 2020-2023  润新知