def before_request(): g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid, g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) g.ip = request.headers.get('X-Real-Ip', request.remote_addr) # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url()
def before_request(): g.startTime = time.time() g.redis = create_redis_engine() g.mysql = create_mysql_engine() g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid, g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) app.logger.debug("uid: {}, sid: {}".format(g.uid, g.sid)) g.api = api g.ip = request.headers.get('X-Real-Ip', request.remote_addr) g.agent = request.headers.get("User-Agent") # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url() # 上下文扩展点之请求后(返回前) before_request_hook = plugin.get_all_cep.get("before_request_hook") for cep_func in before_request_hook(): cep_func(request=request, g=g) before_request_return = plugin.get_all_cep.get("before_request_return") for cep_func in before_request_return(): resp = cep_func(request=request, g=g) try: success = resp.is_before_request_return except: logger.warn( "Plugin returns abnormalities when before_request_return") else: if success is True: return resp
def before_request(): g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid, g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) g.ip = request.headers.get('X-Real-Ip', request.remote_addr) # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url() # 上下文扩展点之请求后(返回前) before_request_hook = plugin.get_all_cep.get("before_request_hook") for cep_func in before_request_hook(): cep_func(request=request, g=g)
def authorized(): """ Client SSO 单点登录、注销入口, 根据`Action`参数判断是`ssoLogin`还是`ssoLogout` """ Action = request.args.get("Action") if Action == "ssoLogin": # 单点登录 ticket = request.args.get("ticket") if request.method == "GET" and ticket and g.signin == False: resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_ticket"), dict(ticket=ticket, app_name=SSO["app_name"], get_userinfo=True, get_userbind=False)) logger.debug("SSO check ticket resp: {}".format(resp)) if resp and isinstance(resp, dict) and "success" in resp and "uid" in resp: if resp["success"] is True: uid = resp["uid"] sid = resp["sid"] expire = int(resp["expire"]) # 获取用户信息,若不需要,可将get_userinfo=True改为False,并注释下两行 g.userinfo = resp["userinfo"].get("data") or dict() set_userinfo(uid, g.userinfo, expire) logger.debug(g.userinfo) # 授权令牌验证通过,设置局部会话,允许登录 sessionId = set_sessionId(uid=uid, seconds=expire, sid=sid) response = make_response(redirect(get_redirect_url("front.index"))) response.set_cookie(key="sessionId", value=sessionId, max_age=expire, httponly=True, secure=False if request.url_root.split("://")[0] == "http" else True) return response elif Action == "ssoLogout": # 单点注销 ReturnUrl = request.args.get("ReturnUrl") or get_referrer_url() or url_for("front.index", _external=True) NextUrl = "{}/signOut?ReturnUrl={}".format(sso_server, ReturnUrl) app_name = request.args.get("app_name") if request.method == "GET" and NextUrl and app_name and g.signin == True and app_name == SSO["app_name"]: response = make_response(redirect(NextUrl)) response.set_cookie(key="sessionId", value="", expires=0) return response elif Action == "ssoConSync": # 数据同步:参数中必须包含大写的hmac_sha256(app_name:app_id:app_secret)的signature值 signature = request.args.get("signature") if request.method == "POST" and signature and signature == hmac_sha256("{}:{}:{}".format(SSO["app_name"], SSO["app_id"], SSO["app_secret"])).upper(): try: data = json.loads(request.form.get("data")) ct = data["CallbackType"] cd = data["CallbackData"] uid = data["uid"] token = data["token"] except Exception,e: logger.warning(e) else: logger.info("ssoConSync with uid: {} -> {}: {}".format(uid, ct, cd)) resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_sync"), dict(token=token, uid=uid)) if resp and isinstance(resp, dict) and resp.get("success") is True: # 之后根据不同类型的ct处理cd logger.debug("ssoConSync is ok") if ct == "user_profile": g.userinfo.update(cd) elif ct == "user_avatar": g.userinfo["avatar"] = cd return jsonify(msg="Synchronization completed", success=set_userinfo(uid, g.userinfo), app_name=SSO["app_name"])
def before_request(): g.startTime = time.time() g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid,g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) g.username = g.uid g.api = api g.plugins = PLUGINS g.userinfo = api.sso_get_userinfo(g.uid) # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url() logger.access.debug("sid: {}, uid: {}, userinfo: {}".format(g.sid, g.uid, g.userinfo))
def before_request(): g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid, g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) # 用户信息 g.userinfo = get_userinfo(g.uid) app.logger.debug(g.userinfo) # 客户端IP地址 g.ip = request.headers.get('X-Real-Ip', request.remote_addr) # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url()
def before_request(): g.rc = rc g.site = get_site_config() g.cfg = Attribute(g.site) g.signin, g.userinfo = default_login_auth() #: Trigger hook, you can modify flask.g hm.call("before_request") #: (Logged-on state)required field: username, is_admin g.userinfo = Attribute(change_userinfo(g.userinfo)) g.is_admin = is_true(g.userinfo.is_admin) g.next = get_redirect_url()
def before_request(): g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid, g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) g.redis = from_url(REDIS) g.site = getSystem(g.redis, sysKey)["data"] print g.uid # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url() # 上下文扩展点之请求后(返回前) before_request_hook = plugin.get_all_cep.get("before_request_hook") for cep_func in before_request_hook(): cep_func(request=request, g=g)
def before_request(): sessionId = request.cookies.get("sessionId", request.headers.get("sessionId")) g.startTime = time.time() g.redis = create_redis_engine() g.mysql = create_mysql_engine() g.signin = verify_sessionId(sessionId) g.sid, g.uid = analysis_sessionId(sessionId, "tuple") if g.signin else (None, None) logger.debug("uid: {}, sid: {}".format(g.uid, g.sid)) g.api = api g.ip = request.headers.get('X-Real-Ip', request.remote_addr) g.agent = request.headers.get("User-Agent") # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url()
def before_request(): g.startTime = time.time() g.signin = verify_sessionId(request.cookies.get("sessionId")) g.sid, g.uid = analysis_sessionId(request.cookies.get("sessionId"), "tuple") if g.signin else (None, None) g.username = g.uid g.api = api g.plugins = PLUGINS g.userinfo = api.sso_get_userinfo(g.uid) # 仅是重定向页面快捷定义 g.redirect_uri = get_redirect_url() #上下文扩展点之请求后(返回前) before_request_hook = plugin.get_all_cep.get("before_request_hook") for cep_func in before_request_hook(): cep_func(request=request, g=g) logger.access.debug("sid: {}, uid: {}, userinfo: {}".format( g.sid, g.uid, g.userinfo))
def authorized(): """ Client SSO 单点登录、注销入口, 根据`Action`参数判断是`ssoLogin`还是`ssoLogout` """ Action = request.args.get("Action") if Action == "ssoLogin": # 单点登录 ticket = request.args.get("ticket") if request.method == "GET" and ticket and g.signin == False: resp = sso_request( "{}/sso/validate".format(sso_server), dict(Action="validate_ticket"), dict(ticket=ticket, app_name=SSO["app_name"], get_userinfo=True, get_userbind=False)) logger.sys.debug("SSO check ticket resp: {}".format(resp)) if resp and isinstance( resp, dict) and "success" in resp and "uid" in resp: if resp["success"] is True: uid = resp["uid"] sid = resp["sid"] expire = int(resp["expire"]) g.userinfo = resp["userinfo"].get("data") or dict() logger.sys.debug(g.userinfo) # 授权令牌验证通过,设置局部会话,允许登录 sessionId = set_sessionId(uid=uid, seconds=expire, sid=sid) response = make_response( redirect(get_redirect_url("front.index"))) response.set_cookie( key="sessionId", value=sessionId, max_age=expire, httponly=True, secure=False if request.url_root.split("://")[0] == "http" else True) return response elif Action == "ssoLogout": # 单点注销 ReturnUrl = request.args.get("ReturnUrl") or get_referrer_url( ) or url_for("front.index", _external=True) NextUrl = "{}/signOut?ReturnUrl={}".format(sso_server, ReturnUrl) app_name = request.args.get("app_name") if request.method == "GET" and NextUrl and app_name and g.signin == True and app_name == SSO[ "app_name"]: response = make_response(redirect(NextUrl)) response.set_cookie(key="sessionId", value="", expires=0) return response elif Action == "ssoConSync": # 数据同步:参数中必须包含大写的hmac_sha256(app_name:app_id:app_secret)的signature值 # 此处可以改为要求登录,passport sessionId可以解析出所需要的sid、uid signature = request.args.get("signature") if request.method == "POST" and signature and signature == hmac_sha256( "{}:{}:{}".format(SSO["app_name"], SSO["app_id"], SSO["app_secret"])).upper(): try: data = json.loads(request.form.get("data")) ct = data["CallbackType"] cd = data["CallbackData"] uid = data["uid"] token = data["token"] except Exception, e: logger.plugin.warning(e) else: logger.plugin.info("ssoConSync with uid: {} -> {}: {}".format( uid, ct, cd)) resp = sso_request("{}/sso/validate".format(sso_server), dict(Action="validate_sync"), dict(token=token, uid=uid)) if resp and isinstance(resp, dict) and resp.get("success") is True: # 之后根据不同类型的ct处理cd logger.plugin.debug("ssoConSync is ok") if ct == "user_profile": # like {u'nick_name': u'.\u5f18\u5f08', u'gender': u'1', u'domain_name': u'taochengwei', u'birthday': u'1995-04-22', u'location': u'\u5317\u4eac \u671d\u9633', u'signature': u'\u5c81\u6708\u5982\u5200\u65a9\u5929\u9a84'} logger.plugin.debug( "sync user_profile before: {}".format(g.userinfo)) g.userinfo.update(cd) logger.plugin.debug( "sync user_profile after: {}".format(g.userinfo)) elif ct == "user_avatar": logger.plugin.debug( "sync user_avatar before: {}".format( g.userinfo["avatar"])) g.userinfo["avatar"] = cd logger.plugin.debug( "sync user_avatar after: {}".format( g.userinfo["avatar"])) return jsonify(msg="Synchronization completed", success=g.api.sso_set_userinfo( uid, g.userinfo), app_name=SSO["app_name"])
def signIn(): """ 单点登录流程 1. Client跳转到Server的登录页,携带参数sso(所需sso信息的加密串),验证并获取应用数据。 2. 未登录时,GET请求显示登录表单,输入用户名密码或第三方POST登录成功后(一处是signIn post;一处是OAuthDirectLogin post;一处是OAuthBindAccount post),创建全局会话(设置Server登录态)、授权令牌ticket,根据ticket生成sid(全局会话id)写入redis,ReturnUrl组合ticket跳转; 已登录后,检查是否有sid,没有则创建ticket,ReturnUrl组合ticket跳转。 3. 校验参数通过后,设置ReturnUrl(从数据库读取)为Client登录地址;校验未通过时ReturnUrl为系统redirect_uri。 4. Client用ticket到Server校验(通过api方式),通过redis校验cookie是否存在;存在则创建局部会话(设置Client登录态),否则登录失败。 -- sso加密规则: aes_cbc(jwt_encrypt("app_name:app_id.app_secret")) -- sso校验流程: 根据sso参数,验证是否有效,解析参数获取name、id、secret等,并用name获取到对应信息一一校验 -- 备注: 第3步,需要signIn、OAuthGuide方面路由设置 第4步,需要在插件内增加api路由 """ # 加密的sso参数值 sso = request.args.get("sso") or None sso_isOk, sso_returnUrl, sso_appName = checkGet_ssoRequest(sso) logger.debug("method: {}, sso_isOk: {}, ReturnUrl: {}".format( request.method, sso_isOk, sso_returnUrl)) if g.signin: # 已登录后流程 # 如果没有sid说明是本地登录,需要重置登录态 if sso_isOk: if g.sid: # 创建ticket,返回为真即是ticket tickets = g.api.usersso.ssoCreateTicket(sid=g.sid, agent=g.agent, ip=g.ip) if tickets: ticket, sid = tickets returnUrl = "{}&ticket={}".format(sso_returnUrl, ticket) return redirect(returnUrl) else: flash( dfr(dict(msg="Failed to create authorization ticket"))) else: sessionId, returnUrl = checkSet_ssoTicketSid( sso_isOk, sso_returnUrl, sso_appName, g.uid, get_redirect_url("front.userset")) return set_redirectLoginstate(sessionId, returnUrl) return redirect(url_for("front.userset")) else: # 未登录时流程 if request.method == 'POST': # POST请求不仅要设置登录态、还要设置全局会话 res = dict(msg=None, code=1, nextUrl=url_for('.signIn', sso=sso) if sso_isOk else url_for('.signIn')) if vaptcha.validate: auth = Authentication(g.mysql, g.redis) result = auth.signIn(account=request.form.get("account"), password=request.form.get("password")) if result["success"]: # 记录登录日志 auth.brush_loginlog(result, login_ip=g.ip, user_agent=g.agent) sessionId, returnUrl = checkSet_ssoTicketSid( sso_isOk, sso_returnUrl, sso_appName, result["uid"], get_redirect_url("front.userset")) logger.debug("signIn post returnUrl: {}".format(returnUrl)) res.update(nextUrl=returnUrl, code=0) return set_jsonifyLoginstate(sessionId, dfr(res)) #return set_redirectLoginstate(sessionId, returnUrl) else: res.update(msg=result["msg"]) else: res.update(msg="Man-machine verification failed") return jsonify(dfr(res)) #return redirect(url_for('.signIn', sso=sso)) if sso_isOk else redirect(url_for('.signIn')) else: # GET请求仅用于渲染 return render_template("auth/signIn.html", vaptcha=vaptcha.getChallenge)