new bad auth web page

merge-requests/2/head
Vladislav Klychkov 2 years ago
parent 7f01b9c66e
commit aaefa6ab2a

@ -18,9 +18,10 @@ from . import ServerBC
# объявление import # объявление import
from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response, Body from fastapi import FastAPI, Form, Request, HTTPException, Depends, Header, Response, Body
from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse from fastapi.responses import PlainTextResponse, HTMLResponse, FileResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates from fastapi.templating import Jinja2Templates
from starlette.datastructures import MutableHeaders
from pydantic import BaseModel from pydantic import BaseModel
import uvicorn import uvicorn
import io import io
@ -28,6 +29,7 @@ from starlette.responses import StreamingResponse
from typing import Union from typing import Union
from pyOpenRPA import __version__ from pyOpenRPA import __version__
import requests
import base64 import base64
import uuid import uuid
import datetime import datetime
@ -43,6 +45,8 @@ app = FastAPI(
swagger_ui_oauth2_redirect_url = "/orpa/fastapi/docs/oauth2-redirect", swagger_ui_oauth2_redirect_url = "/orpa/fastapi/docs/oauth2-redirect",
) )
def IdentifyAuthorize(inRequest:Request, inResponse:Response, def IdentifyAuthorize(inRequest:Request, inResponse:Response,
inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"), inCookiesStr: Union[str, None] = Header(default=None,alias="Cookie"),
inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")): inAuthorizationStr: Union[str, None] = Header(default="",alias="Authorization")):
@ -71,8 +75,10 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
###################################### ######################################
#Way 2 - try to logon #Way 2 - try to logon
if len(lHeaderAuthorization) == 2: if len(lHeaderAuthorization) == 2:
llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split( if "AuthExc" in lCookies:
":") raise AuthException()
else:
llHeaderAuthorizationDecodedUserPasswordList = base64.b64decode(lHeaderAuthorization[1]).decode("utf-8").split(":")
lUser = llHeaderAuthorizationDecodedUserPasswordList[0] lUser = llHeaderAuthorizationDecodedUserPasswordList[0]
lPassword = llHeaderAuthorizationDecodedUserPasswordList[1] lPassword = llHeaderAuthorizationDecodedUserPasswordList[1]
lDomain = "" lDomain = ""
@ -108,22 +114,24 @@ def IdentifyAuthorize(inRequest:Request, inResponse:Response,
mOpenRPA["Domain"] = lResult["Domain"] mOpenRPA["Domain"] = lResult["Domain"]
mOpenRPA["User"] = lResult["User"] mOpenRPA["User"] = lResult["User"]
mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False) mOpenRPA["IsSuperToken"] = __Orchestrator__.GSettingsGet().get("ServerDict", {}).get("AccessUsers", {}).get("AuthTokensDict", {}).get(mOpenRPA["AuthToken"], {}).get("FlagDoNotExpire", False)
try:inResponse.delete_cookie(key="AuthExc")
except Exception:pass
return lAuthToken return lAuthToken
#inRequest.OpenRPASetCookie = {} #inRequest.OpenRPASetCookie = {}
#New engine of server #New engine of server
#inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken #inRequest.OpenRPAResponseDict["SetCookies"]["AuthToken"] = lAuthToken
else: else:
raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (для пользователя не заявлен доступ к оркестратору pyOpenRPA. Обратитесь в техническую поддержку)", headers={}) errorMsg = "Попытка авторизации не прошла успешно (для пользователя не заявлен доступ к оркестратору pyOpenRPA. Обратитесь в техническую поддержку)"
raise ErrorException(text=errorMsg)
else: else:
raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неверная пара логин / пароль)", headers={}) errorMsg = "Попытка авторизации не прошла успешно (неверная пара логин / пароль)"
###################################### raise ErrorException(text=errorMsg)
else: else:
raise HTTPException(status_code=401, detail="Попытка авторизации не прошла успешно (неполная пара логин / пароль)", headers={ 'WWW-Authenticate':'Basic'}) raise AuthException()
else: return None # Credentials are not required - return none else: return None # Credentials are not required - return none
#network.predictor.enabled
# Перевод встроенных fastapi функций на авторизацию
lRouteList =[] lRouteList =[]
for lItem in app.router.routes: for lItem in app.router.routes:
lRouteList.append(lItem) lRouteList.append(lItem)
@ -137,6 +145,35 @@ for lItem in lRouteList:
tags=["FastAPI"] tags=["FastAPI"]
) )
class ErrorException(Exception):
def __init__(self, text :str, name: str="AuthExc"):
self.name = name
self.text = text
class AuthException(Exception):
def __init__(self, name: str="AuthTryWindowCreate"):
self.name = name
templates = Jinja2Templates(directory=CrossOS.PathJoinList(CrossOS.PathSplitList(__file__)[:-2] + ["Resources","Web","orpa"]))
# Обработчик ошибки авторизации (вывод информации о причинах неудачной авторизации)
@app.exception_handler(ErrorException)
async def unicorn_exception_handler(request: Request, exc:ErrorException):
response = templates.TemplateResponse(status_code=401,name="badAuth.xhtml", context={"request":request, "errorMsg":exc.text, "title":"ОРКЕСТРАТОР PYOPENRPA", "subtitle":"ПАНЕЛЬ УПРАВЛЕНИЯ", "version":__version__})
response.set_cookie(key=exc.name,value="True")
return response
# Обработчик попытки авторизации (отвечает за вызов окна для ввода пары логин / пароль)
@app.exception_handler(AuthException)
async def unicorn_exception_handler_2(request: Request, exc: AuthException):
response = HTMLResponse(status_code=401, headers={'Content-type':'text/html; charset=utf-8', 'WWW-Authenticate':'Basic'})
try:response.delete_cookie(key="AuthExc")
except Exception:pass
return response
from . import ServerSettings from . import ServerSettings

@ -498,7 +498,7 @@ def SettingsUpdate():
#} #}
#Orchestrator basic dependencies # Index page in server.py because of special settings #Orchestrator basic dependencies # Index page in server.py because of special settings
{"Method":"GET", "URL": gSettingsDict["ServerDict"]["URLIndexStr"],"MatchType": "EqualNoParam", "ResponseDefRequestGlobal": pyOpenRPA_Index}, {"Method":"GET", "URL": gSettingsDict["ServerDict"]["URLIndexStr"],"MatchType": "EqualNoParam", "ResponseDefRequestGlobal": pyOpenRPA_Index},
{"Method":"GET", "URL": "/metadata.json", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources\\Web\\orpa\\metadata.json")), "ResponseContentType": "application/json"}, {"Method":"GET", "URL": "/metadata.json", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources\\Web\\orpa\\metadata.json")), "ResponseContentType": "application/json","UACBool":False,},
#{"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"}, #{"Method":"GET", "URL": "/Index.js", "MatchType": "EqualCase", "ResponseFilePath": os.path.join(lOrchestratorFolder, "Web\\Index.js"), "ResponseContentType": "text/javascript"},
{"Method":"GET", "URL": "/orpa/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources")),"UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/orpa/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, CrossOS.PathStr("..\\Resources")),"UACBool":False, "UseCacheBool": True},
{"Method":"GET", "URL": "/orpa/client/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, "Web"),"UACBool":False, "UseCacheBool": True}, {"Method":"GET", "URL": "/orpa/client/resources/", "MatchType": "BeginWith", "ResponseFolderPath": os.path.join(lOrchestratorFolder, "Web"),"UACBool":False, "UseCacheBool": True},

@ -0,0 +1,101 @@
<!DOCTYPE html>
<html lang="en" >
<head>
<!-- Yandex.Metrika counter -->
<script async="" src="https://mc.yandex.ru/metrika/tag.js"></script>
<script type="text/javascript">
(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})
(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");
ym(88079149, "init", {
clickmap:true,
trackLinks:true,
accurateTrackBounce:true,
webvisor:true
});
</script>
<noscript><div><img src="https://mc.yandex.ru/watch/88079149" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter -->
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Оркестратор pyOpenRPA</title>
<meta name="description" content="Ведущий RPA разработчик российского программного обеспечения. RPA платформа позволяет решать любые бизнес-задачи. Комплексное решение от компании RPA pyOpenRPA. Первое открытое российское RPA решение для крупного / среднего / малого бизнеса. Доступная автоматизация для каждого.">
<meta name="keywords" content="rpa, программные роботы, автоматизация бизнес-процессов, цифровые сотрудники, виртуальные сотрудники">
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/Semantic-UI-CSS-master/semantic.min.css">
<link rel="stylesheet" type="text/css" href="/orpa/resources/Web/orpa/styleset/home.css">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<script
src="/orpa/resources/Web/jQuery/jquery-3.1.1.min.js"
crossorigin="anonymous"></script>
<script src="/orpa/resources/Web/Semantic-UI-CSS-master/semantic.min.js"></script>
<script src="/orpa/resources/Web/Handlebars/handlebars-v4.1.2.js"></script>
</head>
<body>
{% include 'header.xhtml' %}
<br><br><br><br><br>
<center>
<div class="ui message">
<div class="header">Внимание</div>
<p>{{errorMsg}}</p>
</div>
<button class="ui green button" onclick="document.location='/'">Повторить попытку</button>
</center>
{% include 'footer.xhtml' %}
</body>
<style type="text/css">
body {
background-color: #FFFFFF;
}
.main.container {
margin-top: 2em;
}
.overlay {
float: left;
margin: 0em 3em 1em 0em;
}
.overlay .menu {
position: relative;
left: 0;
transition: left 0.5s ease;
}
.main.menu.fixed {
background-color: #FFFFFF;
border: 1px solid #DDD;
box-shadow: 0px 3px 5px rgba(0, 0, 0, 0.2);
}
.overlay.fixed .menu {
left: 800px;
}
.text.container .left.floated.image {
margin: 2em 2em 2em -4em;
}
.text.container .right.floated.image {
margin: 2em -4em 2em 2em;
}
.ui.footer.segment {
margin: 10.7em 0em 0em;
padding: 5em 0em;
}
.ui.search.dropdown>input.search {
width:100%;
font-family:'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
font-weight: bold;
}
.ui.search.dropdown>.text {
width:100%;
font-family:'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
}
button.ui.green.button {
font-family:'Lato', 'Helvetica Neue', Arial, Helvetica, sans-serif;
background: #368279
}
</style>
</html>
Loading…
Cancel
Save