/// <summary> /// Cria uma nova instância do 'delegate' para a autenticação externa /// O delegate realiza a verificação da autenticação do usuário e controle de permissão através do RBAC /// </summary> /// <param name="conn">Conexão com banco de dados MS-SQL</param> /// <param name="page">Página na qual a requisição foi iniciada</param> /// <param name="enterpriseId">ID da empresa</param> private static ExternalAccessControl GetDelegateInstance(DbBase database, Page page, Int64 enterpriseId) { ExternalAccessControl eAuth = new ExternalAccessControl(delegate(String method, String auth, AccessControl preCtrl, Dictionary <String, Object> parameters) { //Para efeitos de teste vou sempre retornar true //return true; LoginData login = null; if ((page.Session["login"] != null) && (page.Session["login"] is LoginData)) { login = (LoginData)page.Session["login"]; } //Conceitualmente o usuário pode realizar as operações com o seu próprio usuário sem necessitar de permissão no RBAC //Operações com troca de senha, logs e etc... //Essa prerrogativa vale somente para os métodos "user." if ((!String.IsNullOrWhiteSpace(method)) && (parameters != null) && (method.ToLower().Split('.')[0] == "user") && (parameters.ContainsKey("userid"))) { String user = parameters["userid"].ToString(); if (!String.IsNullOrWhiteSpace(user)) { Int64 userid = 0; try { userid = Int64.Parse(user); if (login.Id == userid) { return(new AccessControl(login.Id, true)); } } catch { } } } if ((!preCtrl.Result) && (login != null)) { using (IAMRBAC rbac = new IAMRBAC()) return(new AccessControl(login.Id, rbac.UserCan(database, login.Id, enterpriseId, "admin", method))); } else { return(preCtrl); } }); return(eAuth); }
/// <summary> /// Método utilizado para execução interna através da console de administração /// </summary> /// <param name="conn">Conexão com banco de dados MS-SQL</param> /// <param name="page">Página na qual a requisição foi iniciada</param> /// <param name="jRequest">Texto no formato JSON da requisição</param> public static String ExecuteLocal(DbBase database, Page page, String jRequest, ExecutionLog logDelegate) { try { ExecutionLog eLogs = new ExecutionLog(delegate(Boolean success, Int64 enterpriseIdLog, String method, AccessControl acl, String jRequestLog, String jResponseLog) { if (!success) { using (IAMDatabase db = (IAMDatabase)database) db.AddUserLog(LogKey.Debug, null, "API", UserLogLevel.Debug, 0, enterpriseIdLog, 0, 0, 0, 0, 0, "API Call (" + method + "). Result success? " + success, "{\"Request\":" + jRequestLog + ", \"Response\":" + jResponseLog + "}", 0, null); } if (logDelegate != null) { logDelegate(success, enterpriseIdLog, method, acl, jRequestLog, jResponseLog); } }); Int64 enterpriseId = 0; if ((page.Session["enterprise_data"]) != null && (page.Session["enterprise_data"] is EnterpriseData)) { enterpriseId = ((EnterpriseData)page.Session["enterprise_data"]).Id; } CJSONrpc jsonRpc = new CJSONrpc(database, jRequest, enterpriseId); ExternalAccessControl eAuth = GetDelegateInstance(database, page, enterpriseId); jsonRpc.ExternalAccessControl += eAuth; jsonRpc.ExecutionLog += eLogs; String ret = jsonRpc.Execute(); jsonRpc.ExternalAccessControl -= eAuth; jsonRpc.ExecutionLog -= eLogs; eAuth = null; return(ret); } catch (Exception ex) { return(null); } finally { } }
public override AccessControl ValidateCtrl(DbBase database, String method, String auth, Dictionary <String, Object> parameters, ExternalAccessControl extCtrl) { Boolean ret = false; Int64 entityId = 0; if (String.IsNullOrWhiteSpace(auth)) { ret = false; } else { DataTable tmp = database.ExecuteDataTable(String.Format("select e.id entity_id, ea.*, e.locked from entity_auth ea inner join entity e with(nolock) on ea.entity_id = e.id where e.deleted = 0 and ea.auth_key = '{0}' and end_date > getdate()", auth), CommandType.Text, null); if ((tmp == null) || (tmp.Rows.Count == 0)) { ret = false; } else if ((Boolean)tmp.Rows[0]["locked"]) { ret = false; entityId = (Int64)tmp.Rows[0]["entity_id"]; } else { //Existe a chave e está válida //Deve ser implementado aqui o RBAC ret = true; entityId = (Int64)tmp.Rows[0]["entity_id"]; } tmp.Dispose(); } if (extCtrl != null) { //Transfere a responsabilidade da autenticação para a chamada externa //Passa como parametro a decisão que foi tomada até agora this.Acl = extCtrl(method, auth, new AccessControl(entityId, ret), parameters); } else { this.Acl = new AccessControl(entityId, ret); } return(this.Acl); }
/// <summary> /// Método pricado que executa cada uma das requisições separadamente. /// </summary> private void _executeCall(Controller controller) { Dictionary <String, Object> request = controller.Request; String id = ""; if (request.ContainsKey("id")) { id = request["id"].ToString(); } if (!validate(request)) { return; } Dictionary <String, Object> _parameters = new Dictionary <string, object>(); try { _parameters = (Dictionary <String, Object>)request["parameters"]; } catch { } String _auth = (request.ContainsKey("auth") ? (String)request["auth"] : ""); //Cria a instancia da classe com base no método requerido APIBase processor = APIBase.CreateInstance(request["method"].ToString()); if (processor == null) { _setError(id, ErrorType.InvalidRequest, "JSON-rpc method class is unknow.", "", null, true); return; } Error onError = new Error(delegate(ErrorType type, String data, String debug, Dictionary <String, Object> additionslReturn) { _setError(id, type, data, debug, additionslReturn, false); }); ExternalAccessControl eAuth = new ExternalAccessControl(delegate(String method, String auth, AccessControl preCtrl, Dictionary <String, Object> paramters) { return(ExternalAccessControl(method, auth, preCtrl, paramters)); }); //Define os eventos processor.Error += onError; if (ExternalAccessControl != null) { processor.ExternalAccessControl += eAuth; } //Realiza o processamento Object oResult = null; try { oResult = processor.Process(this._database, this._enterpriseId, request["method"].ToString(), _auth, _parameters); } catch (Exception ex) { _setError(id, ErrorType.InternalError, null, ex.Message + ex.StackTrace, null, false); } //Limpa os eventos processor.Error -= onError; if (ExternalAccessControl != null) { processor.ExternalAccessControl += eAuth; } onError = null; eAuth = null; //Define o retorno if (!this.IsError) { _setResponse(id, oResult); } controller.acl = processor.Acl; }
/// <summary> /// Método utilizado pela API externa, este método interage diretamente com o page.Request e page.Response /// </summary> /// <param name="conn">Conexão com banco de dados MS-SQL</param> /// <param name="page">Página na qual a requisição foi iniciada</param> public static void Execute(DbBase database, Page page, ExecutionLog logDelegate) { //Checa se o content type está adequado Dictionary <String, String> allowed_content = new Dictionary <String, String>(); allowed_content.Add("application/json-rpc", "json-rpc"); allowed_content.Add("application/json", "json-rpc"); allowed_content.Add("application/jsonrequest", "json-rpc"); //Permite somente o método POST if (page.Request.HttpMethod != "POST") { page.Response.Status = "412 Precondition Failed"; page.Response.StatusCode = 412; page.Response.End(); return; } String contentType = page.Request.ContentType.ToLower().Trim().Split(";".ToCharArray())[0]; //Permite somente quando o ContentType estiver na listagem definida if (!allowed_content.ContainsKey(contentType)) { page.Response.Status = "412 Precondition Failed"; page.Response.StatusCode = 412; page.Response.End(); return; } //Verifica se este IP está bloqueado, se sim rejeita a conexão /*if (dsfdsafsd) * { * page.Response.Status = "403 Access denied"; * page.Response.StatusCode = 403; * page.Response.End(); * return; * }*/ if (allowed_content[contentType] == "json-rpc") { page.Response.ContentType = "application/json; charset=UTF-8"; page.Response.ContentEncoding = Encoding.UTF8; try { using (Stream stm = page.Request.InputStream) using (StreamReader reader = new StreamReader(stm, Encoding.UTF8)) { String rData = reader.ReadToEnd(); Int64 enterpriseId = 0; if ((page.Session["enterprise_data"]) != null && (page.Session["enterprise_data"] is EnterpriseData)) { enterpriseId = ((EnterpriseData)page.Session["enterprise_data"]).Id; } CJSONrpc jsonRpc = new CJSONrpc(database, rData, enterpriseId); ExternalAccessControl eAuth = GetDelegateInstance(database, page, enterpriseId); jsonRpc.ExternalAccessControl += eAuth; if (logDelegate != null) { jsonRpc.ExecutionLog += logDelegate; } String ret = jsonRpc.Execute(); jsonRpc.ExternalAccessControl -= eAuth; if (logDelegate != null) { jsonRpc.ExecutionLog -= logDelegate; } Byte[] bRet = Encoding.UTF8.GetBytes(ret); page.Response.Status = "200 OK"; page.Response.StatusCode = 200; page.Response.OutputStream.Write(bRet, 0, bRet.Length); page.Response.OutputStream.Flush(); } } catch (Exception ex) { page.Response.Status = "500 Internal Error"; page.Response.StatusCode = 500; } finally { } } }
/// <summary> /// Método stático que realiza a validação de autenticação do usuário /// /// Esta chamada fará os seguintes passos: /// 1 - Realiza a verificação interna com base na chave de autenticação passada no parâmetro 'auth' /// 2 - Verifica se está habilitado a autenticação externa (parâmetro extCtrl != null) /// 3 - Se está habilitado executa a validação externa através do delagate 'ExternalAccessControl' /// 4 - Se não retorna o resultado da autenticação interna /// </summary> /// <param name="sqlConnection">Conexão com o banco de dados MS-SQL</param> /// <param name="method">String com o método que deverá ser processado</param> /// <param name="auth">String com a chave de autenticação.</param> /// <param name="parameters">Dicionário (String, Object) contendo todos os parâmetros necessários</param> /// <param name="extCtrl">Delegate 'ExternalAccessControl' para a autenticação externa</param> public abstract AccessControl ValidateCtrl(DbBase database, String method, String auth, Dictionary <String, Object> parameters, ExternalAccessControl extCtrl);