7 pontos por GN⁺ 9 시간 전 | 2 comentários | Compartilhar no WhatsApp
  • O princípio Don't Roll Your Own ... se aplica não só à criptografia, mas também à UI web, e recursos que o navegador já oferece de forma confiável não devem ser substituídos sem necessidade
  • Substituir comportamentos básicos como rolagem própria, tratamento de links, seleção de texto e copiar/colar quebra respostas de entrada familiares e faz o usuário voltar a prestar atenção em como operar a interface
  • Assim como nos links de arquivos e issues do GitHub, quando o JavaScript intercepta a navegação por links, às vezes abrir em uma nova aba é mais rápido do que esperar o processamento na aba atual
  • O campo de senha padrão e <input type="date"> funcionam junto com autocompletar, gerenciadores de senha, ferramentas de acessibilidade e teclados móveis, então trocá-los por uma UI falsa pode quebrar recursos
  • Layouts e controles de formulário que mudam a cada poucos meses fazem o usuário gastar tempo reaprendendo em vez de trabalhar; é preferível manter os comportamentos estáveis e padrão do navegador

Aplicando o princípio “Não crie o seu próprio” à UI web

  • A regra de não implementar criptografia por conta própria significa não depender de implementações privadas e não verificadas em software operacional que protege dados sensíveis
  • Isso não quer dizer que ninguém jamais deva escrever código de criptografia, mas sim que, sempre que possível, devem ser usados pacotes e ferramentas revisados e validados
  • Cerca de 20 anos atrás, existiam de fato implementações próprias de RC4 com problemas como vetores de inicialização inadequados, fluxo de chave previsível e vazamento de partes do texto plano
  • Hoje, grandes sites de comércio eletrônico e bancos em geral não usam criptografia própria em serviços web, e em áreas reguladas como pagamentos, saúde e tratamento de dados pessoais, violar requisitos fortes de criptografia pode levar a multas pesadas
  • Design de sites não é a mesma coisa que criptografia, mas reimplementar funções que o navegador já lida bem e nas quais os usuários confiam todos os dias pode piorar a experiência de uso

Problemas ao substituir recursos nativos do navegador

  • Implementar a rolagem da página por conta própria pode quebrar as respostas familiares a mouse, touchpad e teclado
  • Ao sobrescrever o comportamento padrão de rolagem, a página pode se mover devagar demais ou rápido demais, e a rolagem por teclado pode até deixar de funcionar
  • Quando um comportamento usado sem pensar muda para algo estranho, o usuário precisa voltar a prestar atenção à própria navegação na página
  • Entre os recursos típicos que não deveriam ser reimplementados estão navegação por links, seleção de texto, menu de contexto, copiar/colar, campo de senha e seletor de data
  • Ao adicionar recursos de interface a sites voltados para trabalho sério, é preciso decidir com cautela entre incluir efeitos sofisticados ou deixar a cargo do comportamento padrão do navegador

Navegação por links e o caso do GitHub

  • O navegador já lida bem com seguir links, e a navegação por links é uma função central dele
  • Se parece necessário atrapalhar o funcionamento normal de links, vale revisar se o objetivo desejado é importante o bastante para quebrar a navegação por links comum
  • No GitHub, ao clicar em links de arquivos ou de issues, um grande recurso implementado em JavaScript assume o tratamento do clique
  • No Firefox ou Chrome, dá para verificar isso abrindo as ferramentas de desenvolvedor com F12, escolhendo click em Mouse dentro de Event Listener Breakpoints na aba Debugger ou Sources, e então clicando em um link do GitHub
  • No GitHub, às vezes abrir o link em uma nova aba é mais rápido do que esperar o processamento da navegação em JavaScript na aba atual

Campo de senha e seletor de data

  • O campo de entrada de senha do navegador pode oferecer salvamento de senha, preenchimento automático e geração de senhas fortes para novas contas
  • O campo de senha padrão avisa quando a senha será enviada por uma conexão HTTP insegura e também funciona junto com gerenciadores de senha, autocompletar, teclados móveis e ferramentas de acessibilidade
  • Se ele for substituído por um campo de senha falso, esses recursos podem quebrar; e se um campo de texto comum for mascarado manualmente, navegador, sistema operacional e ferramentas assistivas podem tratar a senha como texto visível normal
  • <input type="date"> não oferece suporte direto à seleção de intervalo de datas, mas é possível manter o seletor de data nativo do navegador fornecendo dois campos: data inicial e data final
  • Seletores de data personalizados variam de implementação para implementação: pode ser preciso ampliar para a visualização por ano, clicar dezenas de vezes no botão de ano anterior para escolher o ano de nascimento, ou a digitação direta da data pode ser bloqueada
  • Se for necessário um widget de calendário para navegadores com suporte insuficiente ao seletor de data nativo, é melhor adicioná-lo como um widget auxiliar que manipula o mesmo campo, em vez de substituir <input type="date">

O custo de mudanças frequentes na UI

  • Alterar controles de formulário sem muito critério quase sempre resolve problemas existentes ao mesmo tempo que introduz novos
  • Se o layout e a interface de um site mudam a cada poucos meses, alguns usuários podem se adaptar, mas usuários mais velhos enfrentam o peso de aprender uma nova ferramenta toda vez
  • Quando vários sites continuam mudando suas interfaces, o usuário acaba gastando um tempo considerável reaprendendo o que já conhecia, sem ganho funcional real
  • Assim como seria desagradável se uma distribuição Linux redesenhasse a cada poucos meses todos os comandos centrais e suas opções de linha de comando, ou se a disposição dos botões da máquina de lavar mudasse toda manhã, rearranjos repetitivos de UI se tornam uma experiência frustrante
  • Como a UI web é uma ferramenta que o usuário usa para concluir seu trabalho, é preferível não substituir sem necessidade comportamentos familiares e estáveis que o navegador já oferece

2 comentários

 
kirinonakar 3 시간 전

Acho que não deve haver muitos países com tantos programas próprios de criptografia e segurança quanto o nosso.

 
GN⁺ 9 시간 전
Opiniões no Lobste.rs
  • Concordo que rolagem de página não deve ser implementada manualmente. Você não vai conseguir fazer tão bem quanto o nativo, e a única exceção que eu aceitaria seria algo como mapas, onde há a convenção de mapear a rolagem para zoom

    Discordo fortemente de transformar em regra a ideia de não implementar navegação por links manualmente. Para um site de conteúdo comum eu não recomendaria roteamento do lado do cliente (CSR), mas em alguns apps isso pode até ser fortemente recomendado, e serviços como o GitHub ficam no meio-termo

    Ainda assim, é preciso sempre usar um elemento real de link para que os recursos nativos do navegador continuem funcionando. Em apps como clientes de webmail, faz sentido usar CSR, e no GitHub também houve melhora quando isso era aplicado de forma leve como antigamente, mas a abordagem recente de frontend piorou bastante

    O problema é que CSR com frequência é implementado de forma descuidada demais e não é feito para ser robusto em condições ruins de rede. O navegador é forte nessas situações, e otimizações como o indicador de carregamento da aba ou o bfcache também podem ser prejudicadas pelo CSR

    Implementar seleção de texto manualmente só parece justificável em casos muito específicos, como apps de anotação no celular em que o dedo funciona como um marca-texto. Eu até acrescentaria que não se deveria usar ::selection. É um design ruim que a área selecionada possa simplesmente desaparecer só por adicionar ::selection{} à folha de estilos

    Discordo da proibição de implementar menu de contexto manualmente. Em apps como cliente de e-mail, gerenciador de arquivos ou processador de texto, há necessidade de itens próprios, e como o navegador não oferece um jeito de estender isso, um menu totalmente personalizado é hoje uma escolha prática. Ainda bem que no Firefox dá para forçar a abertura do menu nativo com Shift+clique direito

    Quanto à proibição de implementar copiar/colar manualmente, posso concordar ou discordar dependendo da interpretação, então isso precisaria estar mais claro

    Quase nunca vi casos de campos de senha implementados manualmente fora de demos técnicas. Não considero que trocar o `` de password para text com um botão de mostrar/ocultar se enquadre nisso

    Também discordo da ideia de não implementar seletor de data manualmente. Eu recomendaria controles nativos, mas as limitações e inconsistências são grandes, e nos últimos 10 anos quase não houve interesse em corrigir isso. Não dá para acrescentar informações ao seletor, e a interação para escolher datas antigas, como data de nascimento, é horrível em algumas plataformas. Ex.: Safari's date-picker is the cause of 1/3 of our customer support issues

    Seletores de data customizados têm muitos problemas de acessibilidade, mas muitas vezes ainda são melhores para o usuário comum, e em muitos casos não dá para usar o controle nativo porque faltam recursos. Para selecionar uma única data eu prefiro o nativo no meu navegador porque ele permite digitação direta, mas para muitos usuários o nativo simplesmente não é bom o bastante. Intervalo de datas feito com dois `` provavelmente é muito pior para a maioria das pessoas

    • Expressões que contrapõem pessoas que precisam de recursos de acessibilidade — ou que se beneficiam deles — a “pessoas comuns” tendem a afastar parte dos leitores. Como você parece realmente se importar bastante com a experiência e as necessidades de quem usa recursos de acessibilidade, achei importante apontar isso

    • Depois de usar eu mesmo o seletor de data do Safari, entendi o quanto ele é limitado. Mas sempre fiquei me perguntando por que os sites substituem o seletor de data nativo por um widget de calendário

      Não daria para colocar um widget de calendário ao lado do widget nativo? Isso talvez confunda a UI por parecer que existem dois métodos de entrada, mas parece que daria para resolver com rótulos adequados, marcando um deles como seletor de data avançado. Assim você não perde quem já usa bem o seletor nativo do navegador e ainda ajuda quem acha o seletor do navegador insuficiente

      Entendo que apps web como ferramentas de edição de documentos ou diagramas precisem de menu de contexto, mas ainda acho incômodo quando o clique direito faz o menu comum do navegador desaparecer. Por isso costumo deixar dom.event.contextmenu.enabled = false nas configurações do Firefox. Aí o menu do Firefox aparece por cima e o menu do app web atrás, mas como o menu nativo funciona, isso acaba sendo um desvio aceitável. Quando possível, é melhor usar a barra de menus do app web e não mexer no menu de contexto nativo do navegador. A dica de Shift+clique direito também é uma boa solução

    • Pessoas que precisam de controles acessíveis também são pessoas normais

    • Casos de campo de senha implementado manualmente podem ser vistos em quase todos os bancos do Peru

      Eu queria poder usar o seletor de data nativo, mas do lado de quem implementa parece haver pouco interesse em melhorá-lo. No Firefox há problemas relacionados à UI de seleção de hora/relógio, e o andamento é lento: https://bugzilla.mozilla.org/show_bug.cgi?id=datetime

  • No caso de formulários web, são observações muito boas. Confiar no navegador é o jeito mais simples, rápido e quase sempre mais consistente de fazer isso

    Mas no caso de código criptográfico é diferente. Escrever código de criptografia correto não é fácil, mas também não é impossível. Em algumas situações, as opções são tão poucas que fazer você mesmo pode ser a melhor escolha

    O problema aqui com os puristas da segurança é a tendência de presumir que, para escrever código criptográfico novo, você precisa pertencer ao círculo interno deles. Se você não tiver um doutorado em criptografia ou estágio com DJB ou Dan Boneh, então não pode escrever código criptográfico. “Para estudo” tudo bem, mas aplicar de verdade o que aprendeu já não pode. Às vezes eles parecem até ter dificuldade em reconhecer competência real fora do grupo. Curiosamente, a sobreposição entre esses puristas da segurança e os criptógrafos de fato que publicam artigos parece ser muito pequena

    Agora isso está até se expandindo para “não escreva nada em linguagem sem segurança de memória”. Mesmo que 70% das falhas críticas venham daí, qual era a causa real? Eu diria que a maior parte dos problemas veio de usar malloc() ou new explícito para cada objetinho fora da stack, ou de lidar com strings terminadas em nulo. Se tivessem usado arenas e slices, haveria muito menos desses problemas. Claro, em alguns cenários de alto risco é preciso eliminar completamente certas classes de bug, e aí segurança de memória vira prioridade máxima

    O próximo passo é dizer para não escrever nada que processe entrada não confiável? Não reinventar a roda mesmo quando todas as rodas disponíveis são quadradas? Ainda assim, se você evitar o inchaço em JavaScript e usar os formulários que o navegador já oferece, eu não veria grande problema nem em criar seu próprio framework web

    • Acho que o pecado original de C está no fato de que, ao passar arrays, ele perde a informação de limite e tudo colapsa para ponteiros

    • Sempre entendi “não implemente criptografia manualmente” não como uma verdade absoluta, mas como um alerta muito forte. É verdade que dá para implementar com segurança sem doutorado, mas ainda exige um aprendizado enorme

      Se a ideia for só implementar uma especificação com bastante cuidado, talvez isso pese bem menos. Mas a maior parte do software quer implementações criptográficas rápidas, e aí a complexidade sobe muito. A vulnerabilidade no Monocypher mencionada no link é um bom exemplo. De repente você precisa entender como isogenia dupla, pontos de Edwards e Montgomery ladder se conectam

      Credenciais como doutorado ajudam os outros a confiarem que você sabe o que está fazendo. Auditoria é outro caminho. Pelo visto o Monocypher foi auditado por dois doutores da Cure53. O problema é que a maioria dos programadores não está preparada para avaliar se uma biblioteca criptográfica é segura, então acaba dependendo de sinais não técnicos, como credenciais ou as credenciais dos auditores. Seria bom haver formas mais diretas, mas credenciais acabam funcionando razoavelmente bem

    • Claro que é possível escrever criptografia manualmente. Se fosse impossível, bibliotecas criptográficas nem existiriam. A questão não é se dá para fazer, mas se dá para confiar em criptografia feita por você ou por mim em um ambiente de produção que vai fazer hash de senhas de usuários e proteger dados privados. Eu não confiaria

    • Em um emprego anterior, código legado usava MD5 para verificação de licença, e tivemos que reimplementar MD5 porque precisávamos validar isso em um ambiente onde o C++ antigo não podia ser executado. Procuramos bibliotecas existentes, mas não havia nenhuma com suporte a mudar o IV

    • Eu não teria coragem de implementar criptografia manualmente, mas parece um pouco exagerado que o setor de segurança agora diga que nem autenticação própria você deve fazer

  • Seria bom se o navegador oferecesse um campo de seleção múltipla utilizável sem precisar implementar por conta própria

    • Até existe, mas é péssimo
  • A forma de receber início e fim com dois `` é inconveniente para intervalos de datas e também não é intuitiva. Você acaba dividindo algo que conceitualmente é uma unidade em duas views separadas que visualmente parecem sem relação

    A ausência de intervalo de datas é só um dos vários problemas de ``. Por exemplo, não dá para excluir datas específicas, então em praticamente qualquer serviço de reservas ele já não serve desde o começo

    Tenho dúvidas de que a posição majoritária seja aceitar o pequeno custo de usar dois campos só para ter datas sempre da mesma forma em todo lugar. O usuário médio odeia campos, e pior do que um campo são dois. O argumento da familiaridade também não convence muito. Pela minha experiência, entrada de data nativa na web é rara

    • Já vi vários sites com dois widgets de calendário customizados que nem funcionavam direito separadamente para data inicial e data final de um intervalo. Para piorar ainda mais

    • Eu também não concordei com a parte sobre intervalo de datas. Costumo usar intervalo de datas como exemplo de um controle que conceitualmente é único, mas mostra o quanto pode ser complexo na prática. O slogan “sempre use controles nativos” pode piorar a experiência do usuário quando você consegue oferecer um controle melhor e mais específico para o problema

      Um recurso útil de controles de data/intervalo de data que não dá para fazer com o nativo é a exibição de preços. Ao buscar passagem aérea ou hotel, é muito útil ver diretamente no seletor quais dias são mais baratos ou mais caros. Num controle nativo você precisaria clicar muito mais ou consultar uma tabela separada para ver essa informação, enquanto um controle customizado pode anexar esse tipo de metadado a cada data

      O exemplo clássico é entrada de data de nascimento. O seletor de data normalmente abre mostrando o mês atual, o que não tem quase nenhuma relação com a data desejada e é péssimo. Aqui até dá para usar um controle customizado, mas muitas vezes uma combinação de caixas de texto é melhor. Não é um controle totalmente próprio, mas uma composição de controles nativos; o ponto é que não existe um seletor de data “universal” que funcione bem para todos os casos

  • Já faz alguns anos, então eu precisaria conferir de novo, mas havia um motivo triste pelo qual eu não tive escolha a não ser implementar isso manualmente em vez de usar o seletor de data html5. A UI de `` em alguns navegadores era realmente horrível

    Implementar menu de contexto manualmente é raro, mas quando necessário é muito útil. Por exemplo, se eu estiver criando um editor de diagramas dentro de uma página web, eu gostaria que ele oferecesse um menu de contexto customizado ao clicar num nó do diagrama para realizar ações úteis. Não é bom empurrar toda interação para uma UI de clique esquerdo, como alternar entre uma paleta de ações e o clique no nó

    Concordo fortemente com o restante da lista

  • Não sei bem como interpretar no mesmo nível o exemplo de criptografia e o problema do comportamento de rolagem. Parecem domínios muito diferentes

    Concordo com a ideia geral de que sites estão fazendo coisa demais. Mas esse comportamento depende dos objetivos do usuário e do site

    Será que algo como prefers-user-scroll, à semelhança de prefers-reduced-motion, não poderia ser uma solução intermediária?

    • Não existe caso de uso legítimo para usar scrolljacking a fim de implementar uma área de rolagem vertical. Esse tipo de código nunca deveria ter sido escrito

      Dito isso, essa afirmação vale só para área de rolagem vertical. Existem casos de uso em que a rolagem é remapeada para um comportamento que não é rolagem, e embora isso ainda seja bem problemático, dá para discutir, por exemplo, o mapeamento de vertical para horizontal em sistemas de escrita vertical. Pode até haver um ou outro caso legítimo além disso, mas a forma como isso costuma ser implementado ainda está errada na maior parte das vezes

  • Concordo fortemente com proibir a implementação manual da rolagem da página. Na KotlinConf ouvi uma palestra interessante sobre as dificuldades da implementação de rolagem do Compose Multiplatform for Web

    Um dos problemas era que navegadores web enviam menos eventos de rolagem do que apps nativos, então o algoritmo de cálculo da direção da rolagem falhava. O método desenhava uma parábola passando por todos os pontos e usava a inclinação no último ponto, mas se houvesse poucos pontos a direção da rolagem podia até sair invertida

    Ao portar de outras plataformas ou reimplementar interações assim, é fácil partir de suposições erradas ou esquecer comportamentos “estranhos” que o navegador já fornece por padrão

    • Fiquei curioso sobre para que esses eventos de rolagem eram usados no app original a ponto de precisarem ser replicados também no contexto web. Sempre desconfio um pouco de usar rolagem como entrada motora para outra coisa
  • O conselho “apoie-se na plataforma” está correto, mas acompanhar a plataforma continuamente é difícil. Há coisas como enterkeyhint e inputmode cuja existência a gente lembra vagamente, mas esquece o efeito

    Nesta semana nossa equipe lançou [0] para ajudar com isso. Ele fornece boas práticas de implementação em formato de skill. A documentação também é bem legível para humanos. Ex.: [1]

    [0] https://github.com/GoogleChrome/modern-web-guidance [1] https://github.com/GoogleChrome/modern-web-guidance/…

  • O tom do texto está desalinhado. Seria muito mais produtivo explicar bem quando e por que as pessoas não precisam reinventar a roda

    O texto explica bem os motivos, mas fica pior por causa da formulação dogmática de “não implemente manualmente”

    O slogan “não implemente criptografia manualmente” também acaba soando como dogma. Quem são os especialistas que podem usá-la e quem os nomeou? Eles sequer olharam o código diretamente antes de falar isso? Ao ver falhas como Heartbleed, não fica claro que na prática eram erros bem básicos?

    • São pessoas que dedicaram a vida à criptografia. Ninguém as nomeou; elas conquistaram essa legitimidade publicando pesquisa útil e sendo validadas por quem entende da área

      Os algoritmos são públicos, revisados, publicamente atacados, aprimorados e padronizados. Não é algo feito a portas fechadas. Os artigos são públicos e o código também. Você pode olhar quando quiser. O fato de você não ter visto não significa que ninguém viu. As pessoas olham e tentam quebrar. Nós usamos isso porque resistiu aos ataques

      Se a solução que você tira do Heartbleed é reimplementar o OpenSSL por conta própria, eu garanto que o seu OpenSSL teria cinquenta Heartbleeds para cada Heartbleed do OpenSSL real. A diferença é que o OpenSSL real é revisado, testado, auditado, atacado e corrigido por gente que entende. O seu só ficaria errado em privado

    • O ponto principal não é que exista um especialista impecável que sabe chamar AES sem medo. É que, usando um wrapper popular que funcione com segurança, se surgir um bug ele pode ser encontrado e corrigido em um único lugar

      Mesmo que um novo ataque de canal lateral seja descoberto, dá para reagir em um só lugar. Algo feito manualmente por você não ganha essas melhorias a menos que você passe a acompanhar novas formas de ataque em tempo integral

  • Isso parece mais uma reclamação sobre gente usando mal as ferramentas web. Teria sido mais interessante se também cobrisse casos de uso em que implementar manualmente é justificável. Assim o leitor aprenderia algo útil, em vez de ficar preso ao modelo infantil de “nunca faça isso manualmente” em hipótese nenhuma

    Maturidade é ter o conhecimento e a habilidade para construir algo manualmente, junto com a sabedoria de saber quando não fazer isso

    Ainda assim, compartilho da frustração. Eu também tive muitas frustrações parecidas. O problema é que não houve muito esforço para documentar interações web de forma suficientemente minuciosa e abrangente para que desenvolvedores web possam consultá-las com facilidade. Existe um problema sério de conhecimento adjacente à programação não ser bem documentado nem transmitido à geração seguinte, e por isso continuamos redescobrindo os mesmos problemas. Em geral, dentro do setor, certos conjuntos de comportamentos e interações acabam se consolidando como padrão vencedor, mas ninguém os registra por escrito