Para algumas das minhas tabelas, quero adicionar "second_primary_key", que será uuid ou alguma chave longa aleatória. Eu preciso disso porque, para algumas tabelas, não quero expor números inteiros ao meu aplicativo da web. Ou seja, em uma página "/ invoices", tenho uma lista de faturas e um link para "/ invoices /: id", em que: id é um número inteiro. Não quero que um usuário saiba quantas faturas no meu sistema existem. Portanto, em vez de "/ invoices / 123", quero usar o "second_primary_key" para que o URL seja "/ invoices / N_8Zk241vNa"
O mesmo vale para outras tabelas em que quero ocultar o ID real.
Eu me pergunto, isso é uma prática comum? Qual é a melhor maneira de implementar isso?
E como é chamada essa técnica, afinal, para que eu faça uma pesquisa nela?
fonte
Respostas:
Você pode adicionar uma coluna UUID, mas realmente não precisa (e não deveria). Essa é uma preocupação da camada de apresentação. Você não sonharia em dizer, armazenar um valor em moeda de US $ 1.999 e 1999.
Você quer apenas uma maneira de obscurecer o valor rapidamente para o aplicativo. Você pode fazer isso no próprio aplicativo ou como uma exibição do banco de dados.
Como estamos falando apenas de um único valor, talvez seja uma criptografia bidirecional, como AES ou similar - quanto mais leve, melhor.
O hash pode ser outra possibilidade - depende se você deseja recuperar o número da fatura, pois o hash é uma maneira.
fonte
Ter uma "chave primária alternativa" é um conceito bem conhecido na modelagem de banco de dados relacional, é chamado de "chave alternativa" ou, às vezes, também "chave secundária". O conjunto de "chaves primárias em potencial" é chamado "chaves candidatas". Consulte https://beginnersbook.com/2015/04/alternate-key-in-dbms/
A maneira como você implementa isso é totalmente sua, especialmente se você deseja ocultar o número total de registros. Não existe a "melhor maneira", você deve verificar seus requisitos, como conjunto de caracteres permitido ou útil, tamanho máximo, se desejar que os IDs diferenciam maiúsculas de minúsculas ou não, se deseja que sejam legíveis em uma fatura impressa, se alguém deve poder revendê-los ao telefone sem erros e assim por diante.
fonte
A maioria das faturas possui um número de fatura que, pela maioria das regras contábeis, precisa ser seqüencial ou um contador pode não assinar os resultados do ano ou o IRS (ou similar em seu país) pode desejar fazer uma auditoria completa em suas guias.
Um usuário pode deduzir do número da fatura quantos clientes você atendeu ou quanto tempo levou para você alterar a estratégia de numeração nas faturas.
Quantas faturas são armazenadas no banco de dados não é uma medida do total geral de suas faturas. Existem outros meios de descobrir isso, incluindo a solicitação de relatórios do ano da Câmara de Comércio.
No entanto, bloquearia a fatura atrás de uma tela de login do usuário, para que nem todos possam solicitá-la. Em seguida, no login do usuário, eles podem usar uma metodologia ajax para solicitar suas faturas pendentes, etc. Isso protege seus dados, oculta o URL pelo ajax (normalmente ninguém pode se incomodar em ver os detalhes de como a solicitação ajax é criada) e você controla como os dados são exibidos e oferecidos.
fonte
Você pode usar hashids para isso, ele foi projetado para resolver exatamente esse cenário.
Ele codificará o ID do seu banco de dados em um hash curto (semelhante ao URL de um vídeo do YouTube) e não exigirá a adição de chaves secundárias à sua tabela.
fonte
Você pode criar outra chave exclusiva, mas não deve. Não pelo motivo exposto. Existem maneiras mais simples de esconder os tamanhos das mesas.
O armazenamento
N_8Zk241vNa
custa 12 bytes por linha na tabela e ainda mais no índice. Isso é um grande desperdício para o que você precisa.Criptografar o número inteiro não
id
custa espaço e quase nada no tempo de execução. Como você faz isso depende da sua linguagem de programação e / ou do seu banco de dados.Observe que, com o AES, você obtém um número inteiro de 128 bits, o que significa 22 caracteres em base64, provavelmente mais do que você deseja. Uma cifra com um tamanho de bloco de 64 como DES ou 3DES fornece 11 caracteres, exatamente como você deseja.
Use chaves diferentes para tabelas diferentes.
Se tudo o que você precisa é ocultar o tamanho das tabelas, você pode usar uma sequência comum para todas as tabelas. Observe que pode haver gargalo se houver inserções frequentes em muitas de suas tabelas. Com algo como o Hibernate e um algoritmo Hi-Lo, esse problema desaparece.
fonte
byte[]
, você pode escrever o seuid
em quatro ou oito bytes, adicionar um número de tabela exclusivo e criptografar (a entrada deve ser exatamente de 16 bytes). Se houver modos para escolher, o BCE está certo.IMHO criando duas chaves primárias diferentes não é possível. É claro que você pode colocar esse uuid em um banco de dados para tê-lo como "alias" da chave primária atual. Você pode colocar um índice acima dessa coluna com restrição exclusiva, mas a chave primária é (a partir de sua essência) única em uma única tabela. Pode haver chave primária composta, mas não é isso que você está procurando.
Então, sugiro colocá-lo lá, mas tê-lo apenas com índice. Você pode criar um componente de manipulação para consultar dados por PK, além de outra coluna exclusiva. Ao manipular a solicitação de "/ invoices / ...", basta verificar o parâmetro - se for inteiro, procure o ID, caso contrário, procure o uuid. Ou você pode ter a pesquisa por uuid como um substituto quando a pesquisa por ID não encontrou nada.
E sobre a geração de alguns uuids "aleatórios": por que não algo como "use ID, adicione CONSTANT, converta para hexadecimal". Iniquidade de ID fornecerá exclusividade de uuid, o número hexadecimal é mais difícil de ler para mortais normais + a adição constante evitará ter uuid como 00000001.
fonte
/invoices/123
,/invoices/124
, ...) para pesquisar apenas por UUID a partir do URL.Se ambas as teclas estão apontando para o mesmo fato, e nunca colidiriam. Por que não derivar a outra chave da chave original usando alguma função escalar que criaria código hash personalizado da sua chave original.
Como alternativa, você pode criar uma tabela de mapeamento de anexo que armazene as duas versões da chave. esta tabela atuará como um dicionário para pesquisar a chave secundária.
De acordo com meu entendimento, chaves são índices implícitos e, quanto mais você adicionar índices, mais inserções lentas serão.
fonte
Outra abordagem para o seu caso de uso específico é que, em vez de modificar o banco de dados e o aplicativo, você pode apenas criar uma rota personalizada para as faturas, de modo que / invoices /: f (id) em que f (id) seja alguma função da identificação.
A rota personalizada é responsável por mapear uma solicitação para a ação correta do lado do servidor.
fonte
É uma prática totalmente aceitável, também chamada de 'Chave Alternativa' (AK). Basicamente, o AK é outro índice ou restrição exclusivos.
Você pode até criar restrições de chave estrangeira com base no seu AK.
Um possível caso de uso é o que você explicou: você tem uma PK agrupada em um número de identidade cada vez maior, mas não deseja que esse número seja exibido ou usado como critério de pesquisa, porque pode ser simplesmente adivinhado. Além disso, você tem um identificador exclusivo aleatório ou número de referência como AK, e esse é o ID que você apresenta ao usuário
fonte
Existem vários tipos de chaves / índices. Uma chave primária é um índice exclusivo especial e, como as respostas dizem, você certamente pode criar outra chave exclusiva. E eu concordo que é melhor não expor os dados internos do banco de dados, a menos que haja um motivo muito bom.
Como a pergunta está no contexto de faturas e números, pode valer a pena pesquisar como o setor contábil espera que os números das faturas sejam: http://smallbusiness.chron.com/assign-invoice-numbers-52422.html
Pode parecer confuso ter um ID interno que seja uma chave primária e outro campo exclusivo com o número da fatura visível do aplicativo / cliente. Mas não é tão impuro quando, digamos, um ano depois, o cliente deseja adotar um novo esquema de numeração de faturas. Nesse caso, você não perturbaria o id interno e suas relações em outras tabelas para renumerar toda a bola de cera. Você manteria seu ID interno e renumerará o número da fatura não interna.
Idealmente, você se esforça para não amarrar tabelas em chaves / chaves estrangeiras que provavelmente mudarão e mantém suas tabelas e relações internas transparentes à camada do aplicativo.
fonte
Vá em frente.
Isso não é diferente do campo "lesma" que os artigos de blog e afins costumam ter - uma maneira exclusiva de se referir ao registro do banco de dados separado da chave primária, adequado para uso em um URL. Eu nunca ouvi alguém argumentar contra isso.
fonte