Por cerca de 10 anos, trabalhei em vários aplicativos clientes de desktop internos com repositórios de dados do SQL Server. Raramente iniciei esses projetos - a maioria é trabalho de aquisição.
Uma coisa que parecia constante em todos os lugares foi que havia uma única conta de usuário global do SQL Server que esse aplicativo usava que concedia permissão ao banco de dados comum e sim, em algumas situações ingênuas, usava a sa
conta de usuário, que geralmente tentava corrigir quando possível .
Você não pode ocultar efetivamente esse nome de usuário e senha que o aplicativo usa para acessar o banco de dados. Eles são geralmente armazenados em um ini
ou config
arquivo, ou, eventualmente, cozido no executável em si. Em todos os casos, eles ficam visíveis para o usuário se eles fizerem uma pequena escavação. Em um caso, na verdade, usamos um config
arquivo, mas o criptografamos, mas é claro que a chave de criptografia tinha que ser armazenada no executável (não éramos ingênuos às limitações disso, mas efetivamente impedia as pessoas de bisbilhotar quem era esperto o suficiente procurar nos config
arquivos).
Todos esses sistemas tinham um sistema de autenticação de usuário embutido no aplicativo, mas é claro que todos foram gerenciados pelo próprio aplicativo, o que significa que as informações do usuário foram armazenadas no banco de dados. O aplicativo restringia o que você poderia fazer com base no seu nível de acesso, mas é muito discutível se você puder se conectar ao banco de dados e executar consultas ad-hoc.
Estou interessado em saber o que outros sistemas fazem para solucionar esse problema. Aqui estão as opções que eu conheço:
- Use o mecanismo de segurança do SQL Server para manter uma lista de usuários e funções e fazer com que o aplicativo da área de trabalho adicione e remova usuários por meio de consultas T-SQL.
- Em vez de se conectar diretamente ao banco de dados, crie algum tipo de serviço da web que seja executado no servidor e coloque a lógica de autenticação. Faça todas as solicitações de validação de segurança.
As primeiras opções são um pouco feias porque você está separando os usuários do banco de dados, de modo que os usuários não são mais entidades de primeira classe e não é possível referenciá-los com relacionamentos de chave estrangeira etc.
O segundo parece ser um grande problema de desempenho e muito trabalho extra, além de você não poder usar com facilidade os mapeadores ORM como o NHibernate (eu acho).
Alguém tem experiência com isto? Melhores Práticas?
Editar
Pensando um pouco mais, a autenticação do SQL Server pode realmente resolver esse problema? Por exemplo, se o usuário precisar inserir e atualizar registros do quadro de horários para que você possa editá-lo, não há como o SQL server proibir o acesso a outras linhas na tabela de detalhes do quadro de horários, o que significa que você também pode ler e escrever quadros de horários de outras pessoas.
Respostas:
Receio que adicionar uma camada de serviço da Web seja provavelmente a solução correta para o seu problema.
A separação do cliente da implementação do banco de dados subjacente provavelmente também o ajudará a longo prazo.
Adicionar uma camada de serviço da web não necessariamente prejudica o desempenho ...
De fato, com uma API apropriada, um serviço da Web pode realmente melhorar o desempenho, agrupando várias consultas ao banco de dados na LAN do datacenter, em vez de exigir várias viagens de ida e volta pela WAN.
E, é claro, uma camada de serviço da Web geralmente pode ser dimensionada horizontalmente e adicionar armazenamento em cache apropriado às consultas do banco de dados, talvez até um mecanismo de notificação de alterações.
Uma camada de servidor adiciona segurança que você não pode garantir com os aplicativos em execução em um cliente remoto. Tudo o que é executado em um cliente pode ser "hackeado" e realmente não deve ser considerado de maneira alguma confiável. Você só deve realmente colocar a lógica de apresentação no cliente e hospedar qualquer coisa importante no hardware do qual tenha controle total.
Não sei sobre seus aplicativos, mas meus aplicativos da web são naturalmente divididos em várias camadas, com o código de apresentação separado da camada de persistência por pelo menos um nível de lógica de negócios que mantém os dois separados. Acho que isso facilita muito o raciocínio sobre meu aplicativo e é muito mais rápido adicionar ou modificar a funcionalidade. Se as camadas forem separadas de qualquer maneira, é relativamente fácil manter a camada de apresentação no cliente e o restante em um servidor sob meu controle.
Portanto, enquanto você pode resolver seus problemas sem introduzir uma camada de "serviço da Web", quando tiver escrito todos os procedimentos armazenados (ou equivalentes) necessários para preencher os buracos na implementação padrão de segurança do banco de dados, você provavelmente estaria melhor escrevendo um aplicativo do lado do servidor para o qual você pode escrever testes de unidade adequados.
fonte
Semelhante à resposta de jmoreno, você pode negar ao usuário o acesso a tudo, exceto as permissões EXECUTE nos procedimentos armazenados, e aproveitar o encadeamento de propriedade para que o procedimento armazenado execute as operações necessárias nas tabelas.
Consulte aqui para detalhes https://msdn.microsoft.com/en-us/library/bb669058(v=vs.110).aspx
Quando o usuário digita seu nome de usuário / senha no lado do cliente, eu os armazeno e os envio como parâmetros para cada chamada de procedimento armazenado. Você pode verificá-los em relação aos valores armazenados em uma tabela antes de executar a operação desejada.
Definitivamente, não é a última palavra em segurança, mas pode ser necessária se seus PCs tiverem logons genéricos, limitando sua capacidade de usar grupos do AD para obter permissões ou se você tiver acesso limitado ao próprio AD.
fonte
Uma abordagem é usar grupos de anúncios e procedimentos armazenados para limitar o que o usuário pode fazer - por exemplo, o banco de dados da planilha de horas, pode permitir inserir, atualizar e excluir as horas dos usuários, mas não a atualização das horas de mais ninguém. O ID do usuário seria fornecido pelo mecanismo do banco de dados, o usuário não teria acesso direto às tabelas do banco de dados, apenas aos sps que executavam consultas com base em seu ID de login.
Claro que isso nem sempre é viável, mas pode ser. A melhor abordagem dependerá de seus requisitos e recursos.
fonte
O que você sugere como 'serviço da web' é chamado de arquitetura de n camadas . Geralmente, é o caminho a seguir nos casos em que problemas de segurança ou configuração são prováveis (por exemplo, distribuição de um aplicativo em muitos escritórios). Porém, ele não precisa ser baseado na Web. Muitos trabalham com outros protocolos.
Você cria um servidor de aplicativos para atuar como intermediário entre o cliente e o banco de dados (e outros recursos). O servidor de aplicativos lida com a autenticação baseada em aplicativo e executa ações em nome do cliente. De fato, idealmente, você não faria nenhum SQL em seu cliente - em vez disso, chama métodos no servidor de aplicativos. O servidor de aplicativos lidaria com toda manipulação de dados.
Há vários benefícios na abordagem. Você não precisa configurar conexões e drivers de banco de dados nos clientes. Você não armazena usuários, senhas e servidores de banco de dados. A configuração dos clientes nem é necessária - basta apontá-los no código para o URL ou endereço certo. Além disso, com a 'lógica' no servidor de aplicativos, você não precisa se repetir ao desenvolver outros aplicativos - o mesmo servidor de aplicativos pode ser reutilizado por diferentes tipos de clientes.
fonte
A tecnologia mudou um pouco. Se você autentica cada usuário no próprio banco de dados e usa funções de banco de dados, agora pode usar o que é chamado de Exibição Atualizável para resolver esse problema, pelo menos no SQL Server.
Aqui está a aparência de uma exibição atualizável para uma tabela chamada
SomeTable
onde cada linha dessa tabela está vinculada a um funcionário. O funcionário deve poder ver as linhas vinculadas a eles e os membros da função de RH devem ver todas as linhas, por exemplo:Então, o que você faz é conceder permissões de leitura (e possivelmente gravar) na view (
vwSomeTable
) a todos os usuários e não dar permissões na tabela (SomeTable
).Você pode testar isso assim:
... que devem retornar apenas suas linhas. Ou:
... que retornará todas as linhas. Observe que você precisará das permissões de execução como (representação) para fazer esse teste.
As visualizações são atualizáveis, portanto, mesmo o usuário comum pode fazer isso, desde que a linha esteja vinculada à sua
Employee
linha:fonte
Usar autenticação baseada em certificado é a maneira "correta" de implementar uma conta sql compartilhada. O objetivo é eliminar o uso de senha para esse tipo de coisa.
Atualizar:
Suponho que não entendi a pergunta. Eu pensei que tinha a ver com tentar encontrar uma alternativa para colocar um nome de usuário e senha db em uma configuração de aplicativo ou fazer backup no próprio aplicativo.
Você pode eliminar o problema de gerenciar senhas em aplicativos usando certificados do lado do cliente. O certificado em si não é suficiente, você precisa ter um sistema de distribuição e gerenciamento capaz de operar como revogação de certificado.
Referência: http://en.wikipedia.org/wiki/Public-key_infrastructure
fonte
Criando uma nova solução de segurança para desktop, optamos pela solução de serviço da web que tentarei descrever a seguir.
Compilamos os executáveis de aplicativos de desktop em um ambiente separado dos desenvolvedores. E calcule um HASH daquele executável que é registrado no banco de dados.
Um serviço da web que fornece todas as informações necessárias para a execução do aplicativo, a senha do banco de dados, as informações da cadeia de conexão, as permissões do usuário, etc.
usamos o logon único do banco de dados por aplicativo e registramos os detalhes do usuário no banco de dados em variáveis de sessão para poder auditar registros.
Uma DLL lida com toda a comunicação do aplicativo da área de trabalho ao serviço da Web, acessível apenas com um token incorporado à DLL.
Para poder obter a senha do banco de dados do aplicativo no serviço da Web, a DLL calcula o HASH dos chamadores da DLL em tempo de execução e passa como parâmetro para o serviço da Web que valida o token da DLL e o tempo de execução do executável calculou o HASH para aquele registrado quando foi implantado (o aplicativo está disponível apenas em uma única instalação compartilhada em rede).
Dessa forma, caímos é uma boa solução para o problema de segurança com o qual estamos mais preocupados e bem cientes de algumas falhas de design. Estamos quase terminando esta implementação e até agora estamos felizes com os resultados.
Editar: você pode substituir a ideia de hash usando assinaturas digitais e certificados X.509.
fonte