diff --git a/1.cfm b/1.cfm index a4b273e..0e63b05 100644 --- a/1.cfm +++ b/1.cfm @@ -1,7 +1,9 @@ +
t test +
- + diff --git a/Application.cfc b/Application.cfc index 7ad7753..a2f43e9 100644 --- a/Application.cfc +++ b/Application.cfc @@ -22,20 +22,18 @@ + - - + + + - - - - @@ -77,7 +74,7 @@ - + @@ -168,128 +165,156 @@ (для начала делаем без рефреша, только проверяем протухание) А рефреш можно сделать на серверной стороне? Кладем данные из токена в реквест и наслаждаемся ---> + - - - - - - - - - - - - - - - - jwt = new lib.jwt(this.client_secret); - idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri); + } else { + //точно мы так не словим дедлок ВПР - /* - часто появляется ошибка: после неудачного запроса к IDP - в адресной строке браузера остается все, с чем его редиректил IDP, - а повторный запрос с этим контентом уже не работает. Получаем 400 Bad Request - - может быть, KeyCloak так защищается от циклических редиректов - Не очень понятно, как предотвратить повторный запрос (можно, конечно, использовать сессию, но странно) - */ - //writeOutput(getTickCount()-request.startTickCount); - if(structKeyExists(url, "code")) { //обрабатываем редирект от IDP *** наличие поля code в URL введет нас в заблуждение, но эvar = data, label =то только без валидной сессии - //dump(var = url.code, label = "URL.code"); - // Request access token from idp with the - // authorization code that we got via the URL - //aFormFields = []; - //data = idp.makeAccessTokenRequest((url.code).content, aFormFields); - try { - writeOutput("idp.makeAccessTokenRequest"); - writeOutput(getTickCount()-request.startTickCount); - resp = idp.makeAccessTokenRequest(url.code/*, aFormFields*/); - writeOutput("idp.makeAccessTokenRequest Done"); - writeOutput(getTickCount()-request.startTickCount); - //dump(resp); - data = deserializeJson(resp.content); - //writedump(data); - // Print full response from idp - //dump(var = data, label = "makeAccessTokenRequest - Response from idp"); - - //echo('Refresh token #data.refresh_token#'); - - session.auth.expires_in = data.expires_in; - session.auth.refresh_expires_in = data.refresh_expires_in; - session.auth.access_token = data.access_token; - session.auth.refresh_token = data.refresh_token; - session.auth.id_token = data.id_token; - session.auth.token_type = data.token_type; - session.idp_response_content = structCopy(data); - - //flush() - lock scope="application" type="readonly" timeout="1" { - token_data = (jwt.decode(data.access_token, application.idpCertificate,"RS256")); - } - writeOutput("jwt.decode Done"); - writeOutput(getTickCount()-request.startTickCount); - writedump(token_data); - session.auth.login = token_data.preferred_username; - session.auth.wz = token_data.ClientID; - session.auth.fullname = token_data.name; - session.auth.groups = token_data.groups; - session.auth.session_state = token_data.session_state; - session.auth.sid = token_data.sid; - session.auth.auth_time = token_data.auth_time; - session.auth.exp = token_data.exp; - session.auth.iat = token_data.iat; - //session.sid = token_data.sid; - session.token_data = structCopy(token_data); - - location(this.redirect_uri,false); - } catch (e) {echo('
****************** #e.message# : #e.detail# **********');} - - } else { - strURL = idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":session.auth_state,"allow_signup":false}); - echo('self-made Auth link (idp) #strURL#

'); - location(strUrl,false); - } -
-
- -
- + lock scope="session" type="exclusive" timeout="3" { + + //writedump(session); + //writeoutput(getTickCount()-request.startTickCount); + + //Это первая проба, с сессией + //Когда протухнет сессия, мы можем пойти к IDP и повторно аутентифицироваться. Поскольку у нас сохраняются куки IDP, его сессия, возможно, будет жива. Если мы обновляли сессию IDP в другом приложении SSO, по всей видимости, она будет продолжаться. Если мы видим, что сессия IDP состарилась и хочет протухнуть, мы можем ее освежить и получить новый access token (который мы пока не используем - мы пользуемся ответом IDP) Наверное, правильно обходиться для этих целей вообще без сессии *** ---> + + //проверить sso + //? сделать рефреш + //? сделать логаут + //? сделать отображение ошибки IDP + //+ сделать получение сертификата + if (structKeyExists(session, "auth")) { + request.auth = structCopy(session.auth); + } else { + // + session.auth_state=createGUID().toString() + + + jwt = new lib.jwt(this.client_secret); + idp = new lib.oauth2(this.client_id, this.client_secret, this.auth_endpoint, this.access_token_endpoint, this.redirect_uri); + + /* + часто появляется ошибка: после неудачного запроса к IDP + в адресной строке браузера остается все, с чем его редиректил IDP, + а повторный запрос с этим контентом уже не работает. Получаем 400 Bad Request - + может быть, KeyCloak так защищается от циклических редиректов + Не очень понятно, как предотвратить повторный запрос (можно, конечно, использовать сессию, но странно) + */ + //writeOutput(getTickCount()-request.startTickCount); + if(structKeyExists(url, "code")) { //обрабатываем редирект от IDP *** наличие поля code в URL введет нас в заблуждение, + //но эvar = data, label =то только без валидной сессии + //dump(var = url.code, label = "URL.code"); + // Request access token from idp with the + // authorization code that we got via the URL + //aFormFields = []; + //data = idp.makeAccessTokenRequest((url.code).content, aFormFields); + try { + writeOutput("idp.makeAccessTokenRequest"); + writeOutput(getTickCount()-request.startTickCount); + resp = idp.makeAccessTokenRequest(url.code/*, aFormFields*/); + writeOutput("idp.makeAccessTokenRequest Done"); + writeOutput(getTickCount()-request.startTickCount); + //dump(resp); + data = deserializeJson(resp.content); + //writedump(data); + // Print full response from idp + //dump(var = data, label = "makeAccessTokenRequest - Response from idp"); + + //echo('Refresh token #data.refresh_token#'); + + session.auth.expires_in = data.expires_in; + session.auth.refresh_expires_in = data.refresh_expires_in; + session.auth.access_token = data.access_token; + session.auth.refresh_token = data.refresh_token; + session.auth.id_token = data.id_token; + session.auth.token_type = data.token_type; + + session.idp_response_content = structCopy(data); + + //flush() + lock scope="application" type="readonly" timeout="1" { + token_data = (jwt.decode(data.access_token, application.idpCertificate,"RS256")); + } + writeOutput("jwt.decode Done"); + writeOutput(getTickCount()-request.startTickCount); + writedump(token_data); + session.auth.login = token_data.preferred_username; + session.auth.wz = token_data.ClientID; + session.auth.fullname = token_data.name; + session.auth.groups = token_data.groups; + session.auth.session_state = token_data.session_state; + session.auth.sid = token_data.sid; + session.auth.auth_time = token_data.auth_time; + session.auth.exp = token_data.exp; + session.auth.iat = token_data.iat; + //session.sid = token_data.sid; + session.token_data = structCopy(token_data); + + location(this.redirect_uri,false); + } catch (e) {echo('
****************** #e.message# : #e.detail# **********');} + + } else { + strURL = idp.buildRedirectToAuthURL({"scope":'openid profile email',"state":session.auth_state,"allow_signup":false}); + echo('self-made Auth link (idp) #strURL#

'); + location(strUrl,false); + } + + } + + } // lock session exclusive + } + @@ -418,39 +443,49 @@ - -//https://keycloak.nubes.ru/admin -//https://keycloak.nubes.ru/realms/SSH_CA/account //smishchuk@mgmt.nubes.ru -//https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints -//http://https://keycloak.nubes.ru/realms/SSH_CA/.well-known/openid-configuration + + //https://keycloak.nubes.ru/admin + //https://keycloak.nubes.ru/realms/SSH_CA/account //smishchuk@mgmt.nubes.ru + //https://stackoverflow.com/questions/28658735/what-are-keycloaks-oauth2-openid-connect-endpoints + //http://https://keycloak.nubes.ru/realms/SSH_CA/.well-known/openid-configuration -//https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка -//https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт -//только надо его обрамить -----BEGIN CERTIFICATE----- -function getIdpCertificate(certUrl) { - - var httpService = new http(); - httpService.setMethod( "get" ); - httpService.setCharset( "utf-8" ); - httpService.setUrl(arguments.certUrl); - - var result = httpService.send().getPrefix(); - var status_code = result.ResponseHeader['Status_Code']; - - if ('200' == status_code) { - var content = deserializeJson(result.FileContent); - //мы подразумеваем структуру конкретно KeyCloak - var key = ""; - for (key in content.keys) { - if ("RSA" == key.kty AND "sig" == key.use) { - return "-----BEGIN CERTIFICATE-----" & key.x5c[1] & "-----END CERTIFICATE-----"; + //https://keycloak.nubes.ru/realms/cloud/.well-known/openid-configuration тут ссылка + //https://keycloak.nubes.ru/realms/cloud/protocol/openid-connect/certs тут серт + //только надо его обрамить -----BEGIN CERTIFICATE----- + function getIdpCertificate(certUrl) { + + var httpService = new http(); + httpService.setMethod( "get" ); + httpService.setCharset( "utf-8" ); + httpService.setUrl(arguments.certUrl); + + var result = httpService.send().getPrefix(); + var status_code = result.ResponseHeader['Status_Code']; + + if ('200' == status_code) { + var content = deserializeJson(result.FileContent); + //мы подразумеваем структуру конкретно KeyCloak + var key = ""; + for (key in content.keys) { + if ("RSA" == key.kty AND "sig" == key.use) { + return "-----BEGIN CERTIFICATE-----" & key.x5c[1] & "-----END CERTIFICATE-----"; + } } + throw(message="RSA cetificate not found"); + } else { + throw (message="Cannot obtain IDP certificate, request failed", detail="Status_Code #status_code#"); } - throw(message="RSA cetificate not found"); - } else { - throw (message="Cannot obtain IDP certificate, request failed", detail="Status_Code #status_code#"); } -} - + + + + + + + + + + + \ No newline at end of file diff --git a/index.cfm b/index.cfm index 774a235..39178ff 100644 --- a/index.cfm +++ b/index.cfm @@ -70,6 +70,7 @@ VCD Computing: #dateFormat(report.qComputingAge.dt_load,'YYYY-MM-DD')# #timeF VCD Storage: #dateFormat(report.qStorageAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qStorageAge.dt_load,'HH:MM:SS')# S3 хранение: #dateFormat(report.qS3VolAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3VolAge.dt_load,'HH:MM:SS')# S3 операции и трафик: #dateFormat(report.qS3OpsTrfAge.dt_load,'YYYY-MM-DD')# #timeFormat(report.qS3OpsTrfAge.dt_load,'HH:MM:SS')# +Цены GPL

@@ -83,7 +84,7 @@ S3 операции и трафик: #dateFormat(report.qS3OpsTrfAge.dt_load, Артикул Кол-во (метрика) Ед.изм. - Цена ₽ со скид., с НДС + Цена ₽ GPL, с НДС Стоимость ₽ с НДС     @@ -92,8 +93,8 @@ S3 операции и трафик: #dateFormat(report.qS3OpsTrfAge.dt_load, Компонент - GPL с НДС - Скидка% + - #price# - #discount# + #metric# diff --git a/json.cfm b/json.cfm index db0af4e..1a1df0b 100644 --- a/json.cfm +++ b/json.cfm @@ -61,13 +61,14 @@ - - +}/>