首页 > 其他分享 >从零开始构建报警中心:part10 接入统一登录

从零开始构建报警中心:part10 接入统一登录

时间:2023-12-21 19:31:48浏览次数:36  
标签:return 接入 part10 redis token 从零开始 user login com

前文使用flask-login实现了用户登入登出,在实际使用中过于简单,这里引入统一登录。关于统一登录可以看一下早前的这篇文档:一个简单的SSO统一登录设计

对于接入统一登录可以参考一下的时序图:


从零开始构建报警中心:part10 接入统一登录_flask

根据这个时序图,要接入已有的SSO,需要对现有系统进行一些修改:

  1. 未登录情况下,在login视图中添加从cookie或header中检测Authorization。并根据Authorization是否存在进行判断。
  1. 如果无Authorization,跳转至SSO进行登录
  2. 有Authorization,发送给SSO进行验证
  1. 已登录状态下,验证Authorization是否合法,如果不合法重新登陆。

相关代码如下

在本实例中

SSO的域名为sso.xxx.com,自身应用域名为t.xxx.com,因为在SSO中设定了cookie作用域为xxx.com。

其他代码逻辑,例如访问SSO的/attach/valid验证token,处理flask_login的next参数等均在时序图中有所描述。

使用到了redis存储flask-login中所使用的User对象,并在logout时从redis中移除该条数据,用以实现load_user返回None。


from flask import Flask, redirect, render_template, request, session, url_for
from flask_login import LoginManager, login_user, UserMixin, current_user, login_required, logout_user
import pickle
import requests
from redis import Redis

app = Flask(__name__, template_folder="templates")
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'  # 使用SQLite数据库,可以根据需要更改

db.init_app(app)  # 初始化绑定DB 与 Flask
login_manager = LoginManager(app)  # Setup a Flask-Login Manager
login_manager.login_view = "login"  # required_login 校验不通过,默认跳转

# 用戶登錄Redis配置
user_redis_con = Redis(
    host='127.0.0.1',  # 服务器地址
    port=6379,  # 服务器端口
    db=10
    )


class User(UserMixin):
    """
    flask-login 必要 User类
    """
    def __init__(self, username):
        self.username = username

    def __repr__(self):
        return self.username

    def get_id(self):
        return self.username


# 用户加载函数
# 使用redis存储User对象,如果Redis中没有,则认为未登录,返回None
@login_manager.user_loader
def load_user(id):
    """
    flask-login必要,重要的回调函数
    从redis中返回User类对象,或者None
    :param id:
    :return:
    """

    redis_id = user_redis_con.get(id)
    if redis_id is None:
        return None
    else:
        try:
            user = pickle.loads(redis_id)  # 使用 pickle.loads 方法 将 存储在redis中的序列化对象读出来,还原成User对象
            return user
        except Exception as E:
            return None


# 定义错误处理函数,捕获404错误
@app.errorhandler(404)
def page_not_found(error):
    # 重定向到根路由
    return redirect(url_for('index'))

# 定义根路由
@app.route('/')
@login_required
def index():
    user = current_user
    return '欢迎你, ' + user.username


@app.route('/login', methods=["GET", "POST"])
def login():
    """
    接入统一登录
    未登录状态的所有请求都会被重定向到此URL
    如果请求参数中没有token,则会重定向到sso进行登录操作。
        通过@login_required 撞过来的请求,会带着next参数,表明来源url。
        如果有next参数则将来源URL作为n参数挂在redirectUrl中,用以回跳到登录前页面。(中间跳到了SSO,所以这段有点复杂)
    如果请求参数中有token,则将token放入header Authorization中发送给sso进行验证会验证。
        验证token通过后,直接登录。否则返回提示。
    :return:
    """
    token = request.cookies.get('Authorization', None)\
        if request.cookies.get("Authorization", None) \
        else request.headers.get("Authorization", None)
    if token:
        print("token   " + token)
        # token 参数存在,向SSO请求验证。
        headers = {'Authorization': token}
        attach_valid_url = "http://sso.xxx.com/attach_valid"
        r = requests.get(attach_valid_url, headers=headers)  # 将token放入header  Authorization中发送给sso进行验证。
        data = r.json()
        if data["code"] == 1001:
            username = data["result"]["username"]
            user = User(username)
            # 保存用户信息
            user_dump = pickle.dumps(user)  # 使用 pickle.dumps 方法 将 User 对象序列化存储在redis中
            user_redis_con.set(username, user_dump)
            # 登录操作
            login_user(user)
            # 处理登录路由
            n = request.args.get('next')
            print(n)
            if n:
                return redirect(n)
            else:
                return redirect(url_for('index'))
        else:
            n = request.args.get('next')
            # @login_required 会自动添加一个next parma。如果有这个param 则给redirectUrl加上一个n参数,然后把n挂在上面。
            if n:
                return redirect("%s/login?redirectUrl=%s/login?next=%s" % (
                    'http://sso.xxx.com', 'http://t.xxx.com', n))
            else:
                return redirect("%s/login?redirectUrl=%s/login" % ('htto://sso.xxx.com', 'http://t.xxx.com'))
    else:
        print("无token")
        n = request.args.get('next')
        # @login_required 会自动添加一个next parma。如果有这个param 则给redirectUrl加上一个n参数,然后把n挂在上面。
        if n:
            return redirect("%s/login?redirectUrl=%s/login?next=%s" % (
                'http://sso.xxx.com', 'http://t.xxx.com', n))
        else:
            print("无next")
            return redirect("%s/login?redirectUrl=%s/login" % ('http://sso.xxx.com', 'http://t.xxx.com'))


@app.route('/logout')
@login_required
def logout():
    """
    退出登录
    执行logout_user()进行登出操作(flask-login)
    并删除redis缓存中的User类对象信息
    :return:
    """
    username = current_user.username
    # --start-- 本地系统logout
    logout_user()
    user_redis_con.delete(username)
    # --end--
    # # 重定向SSO进行logout操作
    return redirect("%s/logout" % 'http://sso.xxx.com')


if __name__ == '__main__':
    app.run(debug=True, port=80)


标签:return,接入,part10,redis,token,从零开始,user,login,com
From: https://blog.51cto.com/quietguoguo/8926510

相关文章

  • 从零开始用 Axios 请求后端接口
    对于前端同学来说,请求后端接口是一个非常通用的东西。在十几年前的时候,我们还用Ajax去请求后端接口。但在2023年的今天,很多框架都很成熟了,我们有了更加快捷的方式——Axios框架。请求框架哪家强?对于使用Vue技术栈的同学来说,其实接口请求框架就三种:vue-resource、Axios......
  • 国标GB28181安防监控LiteCVR视频平台无法接入Ehome5.0的原因排查
    随着人工智能技术的迅速发展,未来的安防视频技术将更加智能化。通过深度学习和图像识别算法,安防摄像头可以自动识别异常行为、人脸识别、车辆识别等,从而提供更智能、自动化的安全监控。用户在现场使用LiteCVR平台接入ehome5.0,显示无法接入。针对这个情况我们来好好分析一下。......
  • GB28181视频平台LiteCVR接入音频无声的原因排查
    视频监控系统逐渐向着互联互通和可视化的方向发展。随着互联网技术的发展,视频监控系统可以联网进行数据传输,实现不同监控设备之间的互联互通。同时,可视化技术的应用也使得视频监控数据可以以更加直观的方式呈现,使得人们更加容易理解和应用。GB28181视频平台LiteCVR拓展性强,视频能力......
  • 国标GB28181安防视频平台LiteCVR接入国标设备时,注册不上线的原因排查
    随着社会经济的快速发展和科技的持续进步,安防监控行业在近年来取得了显著的进步。从城市安全到家庭监控,从工厂管理系统到交通管理,安防监控系统已经深入到各个领域,为人们的生活和工作提供了强大的安全保障。有用户在使用视频监控安防平台LiteCVR时,出现了国标GB28181设备注册不上线的......
  • GeneFace接入
    一、构建环境1、安装CUDA2、安装Python库3、准备3DMM模型3.1、下载3DMMmodel在这个链接申请BFM2009model.提交申请--等待邮件获取到邮件中的跳转链接已经用户名密码下载模型压缩包BaselFaceModel.tgz,将其解压,解压后获得其中 01_MorphableModel.mat保存到 ./dee......
  • Chat接入
    一、文档https://platform.openai.com/docs/api-reference/chat二、调用curlhttps://api.openai.com/v1/chat/completions\-H"Content-Type:application/json"\-H"Authorization:Bearer$OPENAI_API_KEY"\-d'{"model":"......
  • Completions接入
    一、文档https://platform.openai.com/docs/api-reference/completions二、调用curlhttps://api.openai.com/v1/completions\-H"Content-Type:application/json"\-H"Authorization:Bearer$OPENAI_API_KEY"\-d'{"model&q......
  • day17 基于Prometheus的HPA自动伸缩 -Prometheus黑盒监控-自定义资源接入监控系统 (7.
    一、基于Prometheus的HPA自动伸缩1、背景Kubernetes集群规模大、动态变化快,而且容器化应用部署和服务治理机制的普及,传统的基础设施监控方式已经无法满足Kubernetes集群的监控需求。需要使用专门针对Kubernetes集群设计的监控工具来监控集群的状态和服务质量。Prometheus则......
  • 从零开始构建报警中心:part08 数据库链接与验证
    处理了model与schema就可以进行数据的实际操作了。flask应用可以通过flask-sqlachemy进行ORM操作。APP与数据库绑定定义flask应用,对该应用进行配置,绑定数据库链接信息,并初始化DB,相关代码如下app.py这是整个系统的入口,后续将添加登入登出(flask-login),SSO接入,蓝图,以及API接入fromfla......
  • android 接入 GreenDao 报错Unresolved reference: DaoMaster
    这是我在51CTO博客的第一篇博文。大家好,我是永远的回忆丶,混迹移动端多年的安卓开发工程师。今天我来分享一个踩坑记录,关于GreenDao接入的问题。出现场景:接入GreenDao并且使用更多插件之后,很容易产生报错Unresolvedreference:DaoMaster解决方法:plugins{id'com.android.......