美文网首页
nginx增加自定义账号鉴权

nginx增加自定义账号鉴权

作者: 言午日尧耳总 | 来源:发表于2021-09-28 22:46 被阅读0次

    nginx增加自定义账号鉴权

    使用nginx反向代理实现

    当一个站点内部程序是个黑盒(无法修改里面的请求逻辑),如何增加自己的账号系统鉴权

    实现逻辑

    • 使用nginx的反向代理功能
    • 自定义账号系统增加两个接口,一个页面(为避免路径冲突,增加了"/xuxiaocong",根据自己需求修改)
      • 账号接口:POST "/xuxiaocong/login",接收用户名和密码,输入正确则生成token
      • 鉴权接口:GET "/xuxiaocong/auth",读取cookie中的token,验证其有效性,有效返回200状态码,无效返回401状态码
      • 登录页面:GET "/xuxiaocong/login",登录页面,填写用户名和密码,将token写入cookie

    效果

    • 用户访问站点
    • 触发/auth鉴权,token无效时,跳转自定义登录页面
    • 登录成功后刷新页面,进入源站点
    • 当token失效时,会重新弹出登录页面
    • 如果源站点也有自己的账号,则需要输入两个账号密码,双重认证

    demo目录结构

    • root # 根目录
      • static # 静态文件(flask框架)
        • xuxiaocong
          • axios.min.js
          • axios.min.map
      • templates # 页面(flask框架)
        • login.html # 登录页面
      • main.py
      • requirements.txt

    nginx配置

    • 代理时增加鉴权(验证cookie)
    • 无权限时跳转ATP的login页面
    • 验证成功后cookie记录token,跳转回原页面
    • 由于原页面可能会有路径冲突,将路径命名为"/xuxiaocong"这样比较拗口的路径
    • 实际项目路径中可增加guid等方式降低重复可能
    • 所有符合设置的路径都需要鉴权(调用/xuxiaocong/auth接口),一定注意接口的高性能
    server {
        listen       80;
        listen  [::]:80;
        server_name  localhost;
    
        location / {                                        # 这里做演示,所有请求都需要鉴权,实际项目注意过滤条件
            proxy_pass http://www.damengsanqian.com/;       # 代理需要鉴权的站点
            proxy_set_header X-Original-URI $request_uri;
            auth_request /xuxiaocong/auth;                  # 鉴权接口
            error_page 401 /xuxiaocong/login;               # 401跳转登录页面
        }
    
        # 路径代理
        location /xuxiaocong {
            proxy_pass http://localhost:5000/xuxiaocong;
            auth_request off;                               # 该路径禁用鉴权
        }
    
        # 静态文件路径代理(flask框架限制)
        location /static/xuxiaocong {
            proxy_pass http://localhost:5000/static/xuxiaocong;
            auth_request off;                               # 该路径禁用鉴权
        }
    
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /usr/share/nginx/html;
        }
    }
    

    代码(Python)

    开头所说的两个接口一个页面,用其他语言实现

    • /requirements.txt
    flask
    
    • /main.py
    import json
    from flask import Flask, request, make_response, render_template
    
    app = Flask(__name__)
    
    # 登录,GET获取页面,POST验证账号密码并返回token
    @app.route('/xuxiaocong/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'GET':
            resp = make_response(render_template('login.html'), 200)
            return resp
        else:
            # 获取post数据
            data = json.loads(request.get_data())
            username = data.get('username')
            password = data.get('password')
            if username == '1' and password == '1':
                return '7cp4VkZ3Nju1AOjy', 200
            else:
                return '账号或密码错误', 400
    
    # 鉴权
    @app.route('/xuxiaocong/auth')
    def auth():
        token = request.cookies.get('xuxiaocong_token')
        # 模拟校验token
        # time.sleep(1)
        if token == '7cp4VkZ3Nju1AOjy':
            return '200', 200
        else:
            return '无token或token失效', 401
    
    
    • /templates/login.html
    <!DOCTYPE html>
    <html>
    
    <head>
        <title>Login</title>
        <script src="{{ url_for('static',filename='xuxiaocong/axios.min.js') }}"></script>
    </head>
    
    <body>
        <h1>使用LCP/ATP账号登录</h1>
        <p>这里是测试</p>
        <p>账号:1</p>
        <p>密码:1</p>
        账号:<input type="text" name="username" id="username" />
        <br />
        密码:<input type="password" name="password" id="password" />
        <br />
        <input type="button" onclick="token()" value="登录" />
        <script>
            function token() {
                const username = document.getElementById("username").value
                const password = document.getElementById("password").value
                axios.post('/xuxiaocong/login', { username, password })
                    .then(function (response) {
                        //设置cookie
                        setCookie('xuxiaocong_token', response.data)
                        location.reload()
                    })
                    .catch(function (error) {
                        alert(`发生错误:${error.response.data}`)
                    })
    
            }
            function setCookie(name, value) {
                const Days = 30;
                const exp = new Date();
                exp.setTime(exp.getTime() + Days * 24 * 60 * 60 * 1000);
                document.cookie = name + "=" + escape(value) + ";expires=" + exp.toGMTString();
            }
        </script>
    </body>
    
    </html>
    

    项目

    pip --default-timeout=200 install -r requirements.txt
    
    set FLASK_APP=main
    set FLASK_ENV=development
    flask run -p 5000
    # 如果nginx使用docker时,需要使用localhost无法访问宿主机
    # 使用ip启动程序
    # nginx配置也需要使用ip
    flask run -h 本机ip -p 5000
    

    docker nginx

    内容 地址
    网站 http://localhost:8881
    基本配置 /etc/nginx/nginx.conf
    站点配置 /etc/nginx/conf.d/default.conf

    常用命令

    nginx -s reload
    vi /etc/nginx/conf.d/default.conf
    
    rm -rf /etc/nginx/conf.d/default.conf
    echo "" > /etc/nginx/conf.d/default.conf
    

    相关文章

      网友评论

          本文标题:nginx增加自定义账号鉴权

          本文链接:https://www.haomeiwen.com/subject/dukdnltx.html