Por que não expor uma chave primária

48

Na minha educação, foi-me dito que é uma ideia falha expor as chaves primárias reais (não apenas chaves DB, mas todos os acessadores primários) ao usuário.

Sempre achei que fosse um problema de segurança (porque um invasor pode tentar ler coisas que não são deles).

Agora eu tenho que verificar se o usuário tem permissão para acessar de qualquer maneira, então há uma razão diferente por trás disso?

Além disso, como meus usuários precisam acessar os dados de qualquer maneira, precisarei ter uma chave pública para o mundo externo em algum lugar entre eles. Agora que a chave pública tem os mesmos problemas que a chave primária, não é?

Houve um pedido de um exemplo sobre por que fazer isso de qualquer maneira, então aqui está um. Tenha em mente que a questão pretende ser sobre o princípio em si, não apenas se for aplicável neste exemplo. Respostas endereçando outras situações são explicitamente bem-vindas.

Aplicativo (Web, Mobile) que lida com atividades, tem várias interfaces de usuário e pelo menos uma API automatizada para comunicação entre sistemas (por exemplo, o departamento de contabilidade quer saber quanto cobrar do cliente com base no que foi feito). O aplicativo tem vários clientes para separação de seus dados (logicamente, os dados são armazenados no mesmo banco de dados) é um deve ter do sistema. Cada solicitação será verificada quanto à validade, não importa o quê.

A atividade é granular muito fina, por isso, estamos juntos em algum objeto contêiner, vamos chamá-lo de "Tarefa".

Três casos:

  1. O usuário A quer enviar o Usuário B para alguma Tarefa, de modo que ele envie um link (HTTP) para realizar alguma Atividade lá.
  2. O usuário B precisa sair do prédio para abrir a tarefa em seu dispositivo móvel.
  3. A contabilidade deseja cobrar o cliente pela tarefa, mas usa um sistema de contabilidade de terceiros que carrega automaticamente a tarefa / atividade por algum código que se refere à API REST do aplicativo

Cada um dos usos requer (ou fica mais fácil se) o agente possuir algum identificador endereçável para a Tarefa e a Atividade.

    
por Angelo Fuchs 13.11.2013 / 07:49
fonte

9 respostas

5

Esta é uma resposta combinada dos outros (ou seja, o que aprendi). Se você sentir vontade de fazer um upvoting, você deve pelo menos fazer um upvote de um dos outros, assim como eles fizeram o trabalho real. Se você estiver mais interessado, leia as outras respostas.

Você não deve expor a chave primária dos bancos de dados, mas sim usar uma chave substituta

  1. Se você quiser que seus usuários consigam se lembrar (pelo menos um pouco) ou reconhecer o identificador de uma entrada. ( Resposta do Graystone28s )
  2. Se você quiser planejar com antecedência e considerar que pode alterar sistemas (banco de dados ou outros) que provavelmente alterarão sua PK. ( Resposta da Telastyns )
  3. Se você deseja garantir que seus usuários tenham uma maneira consistente de acessar dados que não serão alterados, mesmo que sua empresa mude de propriedade e os dados sejam migrados para um sistema diferente. ( Resposta de Michael Durrants )
  4. Se sua PK for previsível (como uma sequência), seu sistema poderá sofrer problemas de coleta de recursos. ( CodeCasters Answer ) Isso se aplica somente se o seu sistema tiver informações que valham a pena ser colhidas e que sejam acessíveis por qualquer pessoa ou pelo menos alguém que tenha interesse em colheita.

Observação: sua chave criada deve ser (meio) compreensível para seres humanos ( Resposta do Sqlvogels ).

Se o seu sistema não precisa de 1. a 4. então não há razão para não usar o banco de dados PK como seu identificador público (várias das respostas). Também a segurança não é um problema aqui (várias das respostas).

    
por 14.11.2013 / 10:17
fonte
33

Also, as my users have to access the data anyway I will need to have a public key for the outside world somewhere in between.

Exatamente. Pegue o HTTP sem estado, que de outra forma não saberia qual recurso ele deve solicitar: ele expõe o ID da sua pergunta 218306 na URL. Talvez você esteja realmente se perguntando se um identificador exposto pode ser previsível ?

Os únicos lugares em que ouvi uma resposta negativa a isso, usaram a lógica: "Mas eles podem alterar o ID na URL!" . Então, eles usaram GUIDs em vez de implementar a autorização adequada.

Posso imaginar uma situação em que você não deseja que seus identificadores sejam previsíveis: a coleta de recursos. Se você tem um site que hospeda publicamente determinados recursos em que outros podem ser interessantes e hospeda-os como /images/n.jpg ou /videos/n.mp4 , em que n é um número incremental, qualquer pessoa que pesquise tráfego para seu site pode coletar todos seus recursos.

Portanto, para responder diretamente à sua pergunta: não, não é ruim expor diretamente os identificadores que só têm significado para o seu programa, geralmente é necessário que o seu programa funcione com sucesso.

    
por 13.11.2013 / 09:52
fonte
28

Você não deve expô-lo porque as pessoas que o virem começarão a usá-lo como seu "número de conta", o que NÃO é. Por exemplo, para minha conta bancária, sei qual é o número da minha conta. Memorizei, usei no telefone com o atendimento ao cliente, uso-o no preenchimento de formulários para outros bancos para fazer transferências, para documentos legais, para o meu serviço de pagamento automático, etc, etc. Não quero para mudar. A chave primária (para minha conta), por outro lado, eu não sei nem vejo.
O sistema que o armazena muda ao longo dos anos de um sistema para outro, através de fusões bancárias, upgrades e substituições de sistemas, etc, etc.
As chaves primárias podem mudar através de algumas dessas transformações, por isso, se nunca foram expostas, escritas ou lembradas por qualquer usuário regular, isso é uma coisa muito boa . As chaves sem significado comercial são frequentemente denominadas chaves substitutas e são frequentemente (mas nem sempre) usadas como chaves primárias.

btw, isso até acontece internamente quando as pessoas constroem interfaces e programas que usam e exponham chaves primárias e as tornam parte de tais sistemas, em vez de apenas fazerem uma única coisa - identificando unicamente um registro de banco de dados internamente. Na verdade, aprendi o exposto ao longo de um período de seis anos apoiando um sistema de armazenamento de dados em um hospital.

    
por 13.11.2013 / 20:09
fonte
22

porque as chaves primárias são um detalhe de implementação.

Se você migrar bancos de dados, suas chaves primárias podem mudar devido à ordem de inserção, remoção de registros antigos ... por alguns motivos diferentes. Se você migrar as plataformas de banco de dados , poderá não ter mais uma chave primária real. Expor a PK acima da camada de acesso a dados é uma abstração gotejante, com todas as preocupações de acoplamento que isso implica.

    
por 13.11.2013 / 15:05
fonte
8

Uma razão que descobri, no tempo todo, vi usuários finais solicitarem que seu identificador significa algo (como ter um prefixo ou um indicador do ano em que foi criado). Mudar um PK é difícil, mas um substituto é muito mais fácil.

Sua chave primária provavelmente será algo que você deseja indexar seu banco de dados por motivos de desempenho, e você pode, por motivos técnicos, alterá-la, por exemplo, de um número para um guia ... você não sabe quais razões são novas tecnologias ou conhecimento podem guiá-lo para baixo. Seu pk é seu item técnico de dados, a chave pública é para consumo de usuários finais.

    
por 13.11.2013 / 12:50
fonte
1

Isto é de um comentário sobre a resposta de Greystone28 por CodeCaster. É um exemplo do que você está dizendo:

I expose InvoiceNumber, which has a meaning to and is changeable by the customer, but I also expose InvoiceID, which my code uses to uniquely identify the invoice. You don't have to (and more often don't want to) let the user-key be the storage-key. This question is about the latter.

Qual é a finalidade do seu aplicativo de exibir o InvoiceID?

Por expor, estou assumindo que você quer dizer que o usuário pode vê-lo. Exponha-o apenas se o usuário precisar dele para usar seu aplicativo. Pode ser usado por suporte técnico ou algum material administrativo. Eu trabalhei com alguns aplicativos que fazem isso. Isso facilita o fornecimento de suporte quando conheço o registro específico em questão.

    
por 13.11.2013 / 14:58
fonte
1

Para a maioria das aplicações, é muito importante que você exponha as chaves aos usuários. Para usar um sistema de informações de forma eficaz, os usuários desse sistema normalmente precisarão de uma maneira de identificar as informações contidas nele e de relacionar essas informações a algo do mundo externo ao banco de dados. Em termos de banco de dados relacional, esses identificadores são chaves.

Um padrão de design bem usado é criar uma chave adicional "puramente técnica" para as tabelas do banco de dados como meio de abstração. Por exemplo, para fornecer uma chave estável (relativamente imutável) em que alguma chave alternativa está sujeita a alterações. Essas chaves técnicas normalmente não são expostas aos usuários finais porque isso prejudica a abstração pretendida dos requisitos do usuário. Não tem nada a ver com segurança.

O problema / desentendimento implícito em sua pergunta é devido ao uso inadequado do termo principal chave. Uma chave primária é apenas uma entre várias chaves "candidatas" (vários identificadores possíveis em uma tabela de banco de dados). A chave primária não requer necessariamente qualquer propriedade fundamentalmente diferente de qualquer outra chave, de modo que as asserções e princípios de design que se aplicam especificamente às chaves primárias e não a outras chaves são sempre suspeitas e freqüentemente erradas.

Considerando que você geralmente precisará expor uma chave ao seu usuário, qual deve ser essa chave? Tente tornar suas chaves Familiar, Simples e Estável. Familiaridade e simplicidade tornam as teclas fáceis de ler e lembrar e ajudam a evitar erros de entrada de dados. Estabilidade significa que a chave muda com pouca frequência, o que também ajuda a evitar a possibilidade de erros de identificação.

    
por 13.11.2013 / 16:31
fonte
1

É completamente normal que as entidades tenham um identificador exclusivo exposto ao mundo externo. Para alguns objetos, pode ser possível encontrar um identificador que realmente tenha um significado (por exemplo, número da fatura), mas para outro não existe esse identificador e, portanto, ele deve ser gerado.

Por uma questão de consistência e legibilidade, acho uma boa prática que todas as entidades em um sistema usem exatamente o mesmo tipo e nome para o identificador. Normalmente, esse identificador seria exposto ( <type> getId() ) em alguma classe base abstrata.

Pela mesma razão, cada serviço no sistema (por exemplo, serviço de faturamento) deve fornecer métodos idênticos para acessar entidades por seu identificador. Normalmente, esse método ( findById(<type> id) ) seria herdado de uma interface de serviço genérica ou classe base.

Esse identificador não precisa ser a chave primária da entidade, mas pode ser uma. A única coisa que se deve assegurar é que a estratégia de geração de chaves produz identificadores razoavelmente únicos (não é necessário universalmente único, mas pelo menos dentro do sistema).

Se o sistema for migrado posteriormente (grande na minha experiência) para outro banco de dados, não será um problema usar uma estratégia diferente (não baseada em chaves primárias) para criar os identificadores, desde que a estratégia seja compatível com o original 1.

    
por 14.11.2013 / 13:21
fonte
0

A chave primária está lá, apenas como um identificador para a tupla (registro, linha) que você tenta acessar como um desenvolvedor. Ele também é usado na integridade referencial (restrições de chave estrangeira) e talvez tenha um ou mais casos de uso também.

Essencialmente, não há nada de ruim em expor isso aos usuários ou até mesmo aos hackers. Porque eu não sei de um ataque que usa chave primária, por exemplo.

Mas, em segurança, temos muitos princípios (que aceitamos e não aprovamos) e precisamos aderir a eles:

  1. O princípio do privilégio de aluguel
  2. Segurança através da obscuridade

E alguns outros princípios. O que eles dizem essencialmente é que:

Se você não precisa expor seus dados, por que você faria isso?

    
por 13.11.2013 / 18:09
fonte