Pergunta

Eu estou trabalhando em uma aplicação web Rails, e está actualmente a ser utilizado por cerca de 20 usuários.

Algumas partes da aplicação são acessíveis apenas por alguns usuários, de modo que já temos uma estrutura de autorização básica no lugar, o que eu implementado usando o acts_as_authenticated plugin.

privilégios dos utilizadores dependem de qual departamento em que trabalham, assim, por exemplo administração tem acesso a todas as partes do aplicativo, enquanto contabilidade só tem acesso às peças relacionadas com a contabilidade, e as vendas só tem acesso a partes relacionadas a vendas , etc.

Por outro lado, os usuários vêem os links para ações para as quais têm privilégios unsufficient. Por exemplo, aqueles no departamento de vendas ver um link para os registros financeiros no menu principal, mas quando clicar sobre ele, nada acontece. Isto é assim porque AFAIK não há nenhuma maneira eficiente para consulta os privilégios de usuário usando acts_as_authenticated.

Eu quero mudar isso de duas maneiras:

  1. Eu quero apresentar mais autorização de grão fino. Atualmente, a autorização é feito no nível do controlador. Eu quero fazer isso no nível de ação ou modelo. Por exemplo, eu quero aqueles no departamento de vendas para ser capaz de criar e pagamentos de atualização, mas não excluí-los.

  2. Eu quero ser capaz de consultar os privilégios de usuário de forma eficiente, para que eu possa remover links desnecessários (e confuso) a partir da interface.

O que você acha que é a maneira mais elegante de implementar isso?

respostas

Rails específicas, não são necessários, eu só quero saber como isso deve ser implementado em um aplicativo orientado a dados.

Finalmente, aqui está como ele é implementado atualmente:

def authorized?
  current_user.role.foo? or current_user.role.bar?
end

E aqui está a minha ideia inicial, que eu acho que não é a melhor maneira de resolver este:

+------------+------------+---------+
| department | controller | action  |
+------------+------------+---------+
| accounting | payments   | index   |
| accounting | payments   | new     |
| accounting | payments   | create  |
| accounting | payments   | edit    |
| accounting | payments   | update  |
| accounting | payments   | destroy |
| sales      | payments   | new     |
| sales      | payments   | create  |
| sales      | payments   | edit    |
| sales      | payments   | update  |
+------------+------------+---------+

ou

+------------+----------+-------+--------+------+--------+--------+
| department | model    | list  | create | read | update | delete |
+------------+----------+-------+--------+------+--------+--------+
| accounting | payments | TRUE  | TRUE   | TRUE | TRUE   | TRUE   |
| sales      | payments | FALSE | TRUE   | TRUE | TRUE   | FALSE  |
+------------+----------+-------+--------+------+--------+--------+
Foi útil?

Solução

O conceito básico de autorização, como eu entendo, é um papel. Papel pode expressar várias coisas:

  1. relação de um usuário para o sistema como um todo (por exemplo. A ser um administrador do sistema)
  2. relação de um usuário para algum tipo de entidades (ex. A ser um moderador dos comentários)
  3. relação de um usuário para alguma entidade particular (por exemplo. A ser um proprietário de algum recurso)
  4. alguma outra relação complexa (por exemplo. A ser um amigo de um usuário que seja proprietário de algum recurso)
  5. que o usuário tem algum atributo (s) ou responde a alguma mensagem de alguma forma particular (por exemplo. A ser um adolescente)

Um sistema de autorização realmente grão fino deve permitir-lhe definir o papel de um usuário com base em qualquer um dos critérios acima mencionados. Além disso, deve permitir que você defina mais de uma função para um usuário. (As formas mais simples de plugins de autorização para Rails geralmente permitem que você definir apenas o primeiro tipo de papéis e definir apenas um papel para um usuário.)

A outra parte da authoriation é um mecanismo que decide qual parte do código para ser executado (ou não executar) baseado no fato de se um usuário se encaixa em algum papel (conjunto de papéis) ou não. Para aplicar esse mecanismo, nós temos que encontrar os pontos em que a autorização deve tomar lugar e selecionar funções para as quais o código deve ou não ser executados.

A maneira que funciona para mim em Rails é definir papéis no nível do modelo e para deixar mecanismo de autorização (definindo papéis permitidos para partes do código que eu quero ser autorizado e perguntando se o usuário atual tem o papel que é permitido executar a parte) inteiramente para controladores / views.

Por isso eu uso tweaked rails-autorização-plugin que tem todas as possibilidades que acabei de mencionar construído na direita (vários tipos de papéis, muitos papéis para um usuário, autorização no controle e visão de nível).

Outras dicas

Você pode precisar de introduzir a noção de 'pontos de função' ou 'recursos' em seu modelo como controle de pontos de acesso; um 'recurso' pode ter um 'recurso pai' opcional para formar uma hierarquia. Você começa a decidir o que é e não é um recurso, e verificar se há permissões programaticamente. Isso também deve permitir-lhe verificar se há acesso de nível de recurso antes de desenhar um menu, de modo que os usuários nunca ver links para páginas que não têm permissão para acessar.

a situação / solução semelhante é descrita aqui

De suas duas propostas, a primeira opção parece um pouco melhor, pois permite que você adicione as ações que podem não ser as acções a nível modelo. Eu estou supondo que você vai correr em um caso em que o segundo modelo não chega a fazer o suficiente, e você precisa se quer alterar o esquema ou iniciar aspersão permissões lógica em toda a sua aplicação (ex. "Os usuários sem acesso 'criar' também não pode executar método xxx ")

Penso que a razão a solução não parece muito DRY é que não há repetição:

  1. Nos nomes de departamento, e
  2. Nos capacidades de departamento

No que diz respeito ao nº 1, não faria sentido criar uma tabela de departamentos e dar a cada departamento de uma Id.

No que diz respeito ao nº 2, eu concordo com o primeiro comentário. Provavelmente pode agrupar os vários controladores e acções em grupos funcionais, e, em seguida, definir uma relação de muitos para muitos (tabela de mapeamento) entre os utilizadores e funções. Funções teria, então, uma relação de um-para-muitos com o que ações / controladores eles permitem. Isso iria deixá-lo, com a repetição mínima, dizer coisas como "contabilidade e vendas deve ser capaz de ler todas as tabelas financeiras."

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top