def legalize_ws(account: SsoAccount, sso: WorkspaceSso) -> requests.Session:
    """
    使用该账号认证该工作空间
    :param account:
    :param sso:
    :return: session
    """
    logger.info("{} 工作空间认证:".format(account.username, sso.ws_id))
    session = requests.Session()
    try:

        rest = session.get(sso.portal_site,
                           proxies=proxies,
                           verify=False,
                           timeout=timeout)

        session.post(rest.url,
                     data={
                         'username': account.username,
                         'password': account.password,
                         'confirm': 'yes'
                     },
                     proxies=proxies,
                     verify=False,
                     timeout=timeout)

    except Exception as e:
        raise AccountException(e)
    return session
 def wrapper(*args, **kwargs):
     if 'username' not in session:
         return redirect(url_for("web.login"))
     if not method or request.method == method:  # 不设置method或当前请求方法匹配时
         for r in policies:
             if r.value not in session['role']:
                 return redirect(url_for("web.login"))
     logger.info("{} {}".format(session.get("username"), request.url))
     return func(*args, **kwargs)
def status_clear():
    """
    刷新状态
    :return:
    """
    logger.info("job status_clear ...")
    # 工作空间状态
    Workspace.objects(Workspace.status == Workspace.STATUS_START).update(
        status=Workspace.STATUS_STOP)
def watch_hosts(portal_site):
    """
    获取url下的所有hosts,以及sso认证时所需要的一些信息
    可根据自己实际情况获取,可能会有前后端分离的情况,可以自己去解析
    本示例比较简单,只简单获取当前url中的host
    :param portal_site: 首页url
    :return: (redirect_url, system_type, hosts, portal_site)
    """
    logger.info("watch hosts: {} begin...".format(portal_site))

    hs = re.findall(r'http[s]?://([\w.:-]+).*$', portal_site)
    rest = requests.get(portal_site)
    system_type = Workspace.TYPE_SSO

    logger.info("watch hosts: {} -> {}".format(portal_site, hs))
    return rest.url, system_type, hs, portal_site
 def wrapper(*args, **kwargs):
     if 'username' not in session:
         return redirect(url_for("web.login"))
     logger.info("{} {}".format(session.get('username'), request.url))
     return func(*args, **kwargs)
def deal_with_direct(header: HeaderModel, body: BodyModel, name,
                     packet_record: PacketRecord, auth: WorkspaceAuth):
    """
    手动录入认证信息
    :param header:
    :param body:
    :param name:
    :param packet_record:
    :param auth:
    :return:
    """
    logger.info("{} deal with direct: {}".format(name, header.url))
    for auth_info in auth.auth_info:
        assert isinstance(auth_info, AuthInfo)
        if auth_info.url_pattern and not re.match(auth_info.url_pattern,
                                                  header.url):  # url_pattern
            continue
        _header = copy.copy(header)
        _body = copy.copy(body)
        try:
            if auth_info.auth_args:
                _header.update_args(auth_info.auth_args)
            if auth_info.auth_header:
                _header.update_headers(auth_info.auth_header)
            if auth_info.auth_param:
                _body.update_param(auth_info.auth_param)

            if _body.type == BodyModel.TYPE_JSON:
                raw_rest = requests_request(_header.method,
                                            _header.url,
                                            json=_body.body(),
                                            headers=_header.header)
            elif _body.type in [BodyModel.TYPE_FORM, BodyModel.TYPE_BYTE]:
                raw_rest = requests_request(_header.method,
                                            _header.url,
                                            data=_body.body(),
                                            headers=_header.header)
            else:
                raise ParserException("illegal body type {}".format(
                    _body.type))
        except Exception as e:
            logger.error("{} processing error!".format(auth_info.describe),
                         exc_info=True)

            packet_data = PacketData(banner=gen_banner(auth_info.describe,
                                                       _header.method,
                                                       _header.url, str(e)),
                                     role_describe=auth_info.describe)
            packet_data.save()
            packet_record.per_packets.append(packet_data)
        else:
            resp_body = BodyModel(raw_rest.content, charset=raw_rest.encoding)
            packet_data = PacketData(
                banner=gen_banner(auth_info.describe, _header.method,
                                  _header.url, raw_rest.text),
                role_describe=auth_info.describe,
                request=Request(url=_header.url,
                                method=_header.method,
                                header=_header.header,
                                body_content=_body.content,
                                body_type=_body.type),
                response=Response(status_code=raw_rest.status_code,
                                  header=raw_rest.headers,
                                  body_content=resp_body.content,
                                  body_type=resp_body.type))
            packet_data.save()
            packet_record.per_packets.append(packet_data)
def deal_with_sso(header: HeaderModel, body: BodyModel, name,
                  packet_record: PacketRecord, sso: WorkspaceSso,
                  ws: Workspace):
    """
    处理sso认证的系统
    :param header:
    :param body:
    :param name:
    :param packet_record:
    :param sso:
    :param ws:
    :return:
    """
    rs = redis.Redis(connection_pool=redis_pool)
    hm_key = "{}:{}".format(name, ws.id)  # session
    logger.info("{} deal with sso: {}".format(name, header.url))
    _header = header.header
    if 'Cookie' in _header.keys():
        _header.pop('Cookie')

    for account_id, describe in sso.roles.items():
        account = SsoAccount.objects(id=account_id)
        if len(account) == 0:
            logger.error("no {}->{}!".format(account_id, describe))
            continue
        account = account[0]
        assert isinstance(account, SsoAccount)
        _r = describe if describe else account.describe if account.describe else account.username

        try:
            if account.username == '-':  # 空角色
                if body.type == BodyModel.TYPE_JSON:
                    raw_rest = requests_request(header.method,
                                                header.url,
                                                json=body.body(),
                                                headers=_header)
                elif body.type in [BodyModel.TYPE_FORM, BodyModel.TYPE_BYTE]:
                    raw_rest = requests_request(header.method,
                                                header.url,
                                                json=body.body(),
                                                headers=_header)
                else:
                    raise ParserException("Illegal body type{}".format(
                        body.type))
            else:  # 正常账号
                auth_session = rs.hmget(hm_key, str(account.id))[0]
                if not auth_session:
                    session = legalize_ws(account, sso)
                    auth_session = AuthSession(session, account)

                    rs.hset(hm_key, str(account.id),
                            pickle.dumps(auth_session))
                else:
                    auth_session = pickle.loads(auth_session)

                rs.expire(hm_key, 60 * session_timeout)  # 重设超时时间

                if body.type == body.TYPE_JSON:
                    raw_rest = auth_session.request(header.method,
                                                    header.url,
                                                    json=body.body(),
                                                    headers=_header)
                elif body.type in [BodyModel.TYPE_FORM, BodyModel.TYPE_BYTE]:
                    raw_rest = auth_session.request(header.method,
                                                    header.url,
                                                    data=body.body(),
                                                    headers=_header)
                else:
                    raise ParserException('Illegal body type {}'.format(
                        body.type))
        except Exception as e:
            logger.error("{} {} processing error!".format(
                account_id, describe),
                         exc_info=True)

            if isinstance(e, AccountException):  # 账号失效
                account.status = SsoAccount.STATUS_INVALID
                account.save()
            packet_data = PacketData(banner=gen_banner(_r, header.method,
                                                       header.url, str(e)),
                                     role_describe=_r)
            packet_data.save()
            packet_record.per_packets.append(packet_data)
        else:
            resp_body = BodyModel(raw_rest.content, charset=raw_rest.encoding)
            packet_data = PacketData(
                banner=gen_banner(_r, header.method, header.url,
                                  raw_rest.text),
                role_describe=_r,
                request=Request(url=header.url,
                                method=header.method,
                                header=raw_rest.request.headers,
                                body_content=body.content,
                                body_type=body.type),
                response=Response(status_code=raw_rest.status_code,
                                  header=raw_rest.headers,
                                  body_content=resp_body.content,
                                  body_type=resp_body.type))
            packet_data.save()
            packet_record.per_packets.append(packet_data)