private IPrincipal ExtraiPrincipalDeTicket(FormsAuthenticationTicket ticket) { if (ticket.Version != VersaoTicket) { Log.ErrorFormat("Ticket com versão diferente da atual. Versão atual = {0}, versão do ticket = {1}", VersaoTicket, ticket.Version); return(null); } try { Log.Debug("Carregando informações do ticket"); var serializedUserData = Convert.FromBase64String(ticket.UserData); IDictionary userData; using (var ms = new MemoryStream(serializedUserData)) using (var gzs = new GZipStream(ms, CompressionMode.Decompress)) { var fmt = new BinaryFormatter(); userData = (IDictionary)fmt.Deserialize(gzs); } if (Log.IsDebugEnabled) { Log.Debug("Dados do usuário:"); foreach (DictionaryEntry de in userData) { Log.DebugFormat(" {0} = {1}", de.Key, de.Value); } } var id = (int)userData["id"]; var nomeCompleto = (string)userData["nomeCompleto"]; var papeis = (string[])userData["papeis"]; var principal = new SuprifattusPrincipal(id, ticket.Name, nomeCompleto, papeis, userData); this.ValidaPrincipalDeTicket(ticket, principal); return(principal); } catch (SerializationException ex) { Log.Error("Erro ao deserializar dados do usuário conectado", ex); return(null); } catch (Exception ex) { Log.Error("Erro ao recuperar informações do usuário conectado", ex); if (!(ex is AppError) && !(ex is SecurityException)) { throw; } return(null); } }
/// <summary> /// Valida o <see cref="SuprifattusPrincipal"/> criado a partir do <paramref name="ticket"/>. /// A validação padrão verifica se o IP de criação do ticket é o mesmo, e, caso /// <typeparamref name="T"/> suporte <see cref="IAppUser"/>, verifica também o hash. /// </summary> protected virtual void ValidaPrincipalDeTicket(FormsAuthenticationTicket ticket, SuprifattusPrincipal principal) { var ip = (string)principal.Properties["ip"]; if (ip != AspNetContext.Request.UserHostAddress) { throw new SecurityException("Ticket inválido") .SetAdditionalInfo("ip original: {0}, ip atual: {1}", ip, AspNetContext.Request.UserHostAddress); } if (!typeof(T).IsSubclassOf(typeof(IAppUser))) { return; } var hash = (string)principal.Properties["hash"]; if (String.IsNullOrEmpty(hash)) { throw new AppError("Hash em branco", "É obrigatório o uso de hash com IAppUser"); } var usuario = (IAppUser)this.LoadAppUser(principal.Identity.UserID); if (hash != this.ObtemTokenParaLoginAutomatico(usuario, false, true)) { throw new SecurityException("Hashs não conferem"); } }