Práticas recomendadas para funções vs. declarações em identidade ASP.NET

94

Eu sou completamente novo no uso de claimsin ASP.NETIdentitye quero ter uma ideia das melhores práticas no uso de Roles and/or Claims.

Depois de toda essa leitura, ainda tenho dúvidas como ...

P: Não usamos mais funções?
P: Em caso afirmativo, por que as funções ainda são oferecidas?
P: Devemos usar apenas reivindicações?
P: Devemos usar funções e reivindicações juntos?

Meu pensamento inicial é que "devemos" usá-los juntos. Eu vejo Claimscomo subcategorias para o que Roleseles suportam.

POR EXEMPLO:
Função:
Reivindicações contábeis : CanUpdateLedger, CanOnlyReadLedger, CanDeleteFromLedger

P: Eles pretendem ser mutuamente exclusivos?
P: Ou é melhor ir SOMENTE para reivindicações e "qualificar totalmente" suas reivindicações?
P: Quais são as melhores práticas aqui?

EXEMPLO: Usando funções e declarações juntas
Claro, você teria que escrever sua própria lógica de atributo para isso ...

[Authorize(Roles="Accounting")]
[ClaimAuthorize(Permission="CanUpdateLedger")]
public ActionResult CreateAsset(Asset entity)
{
    // Do stuff here

    return View();
}

EXEMPLO: Qualificando totalmente suas reivindicações

[ClaimAuthorize(Permission="Accounting.Ledger.CanUpdate")]
public ActionResult CreateAsset(Asset entity)
{
    // Do stuff here

    return View();
}
Prisioneiro ZERO
fonte
1
Então, estou enfrentando o mesmo problema agora, como você resolve isso e como você pode subRole a Permissão no aplicativo?
Loai

Respostas:

77

Uma função é uma categoria simbólica que reúne usuários que compartilham os mesmos níveis de privilégios de segurança. A autorização baseada em funções requer primeiro a identificação do usuário, depois a verificação das funções às quais o usuário está atribuído e, finalmente, a comparação dessas funções com as funções autorizadas a acessar um recurso.

Em contraste, uma declaração não é baseada em grupo, mas sim na identidade.

da documentação da Microsoft :

Quando uma identidade é criada, ela pode ser atribuída a uma ou mais declarações emitidas por uma parte confiável. Uma declaração é um par de valor de nome que representa o que o sujeito é, não o que o sujeito pode fazer.

Uma verificação de segurança pode determinar posteriormente o direito de acessar um recurso com base no valor de uma ou mais declarações.

Você pode usar ambos em conjunto ou usar um tipo em algumas situações e o outro em outras situações. Depende principalmente da interação com outros sistemas e de sua estratégia de gerenciamento. Por exemplo, pode ser mais fácil para um gerente gerenciar uma lista de usuários atribuídos a uma função do que gerenciar quem tem uma reivindicação específica atribuída. As reclamações podem ser muito úteis em um cenário RESTful onde você pode atribuir uma reclamação a um cliente, e o cliente pode então apresentar a reclamação para autorização em vez de passar o nome de usuário e a senha para cada solicitação.

Claies
fonte
6
Não acredito que isso seja totalmente correto. Eu acredito que as reivindicações indicam identidade, não autorização. O que eles estão autorizados a fazer é administrado separadamente. Ou seja, eles podem ter uma reclamação que tem sua data de nascimento indicando que são maiores de 18 anos. Essa reclamação seria passada a um gerente de autorização que poderia conter uma regra que diz "se eles tiverem mais de 18 anos, eles podem editar o recurso X", mas a afirmação em si não indica o que eles podem / não podem fazer ou acessar. O mesmo vale para funções e outras reivindicações. As declarações indicam quem você é e são usadas para determinar o que você pode fazer, mas não dizem diretamente
ChrisC
A documentação de suporte para @ChrisC é da autorização baseada em declarações da Microsoft no ASP.NET Core : "Uma declaração é um par de valores de nome que representa o que o assunto é, não o que o assunto pode fazer."
DrGriff
@DrGriff Obrigado por fornecer esse link; Eu vinha me questionando há algum tempo sobre a exatidão da descrição que fiz; Acho que esclareci a resposta com base nesse link agora.
Claies
29

Como @Claies explicou perfeitamente, as afirmações poderiam ser mais descritivas e um tipo profundo de papel. Eu penso sobre eles como seus ids de papéis. Eu tenho um id de academia, então pertenço ao papel dos membros. Eu também estou nas aulas de kickboxing, então eu tenho uma reivindicação de id de kickboxing para eles. Minha inscrição precisaria da declaração de uma nova função para se adequar aos meus direitos de membro. Em vez disso, tenho ids para cada classe de grupo ao qual pertenço, em vez de muitos novos tipos de associação. É por isso que as reivindicações se encaixam melhor para mim.

Há um ótimo vídeo explicativo de Barry Dorrans, falando sobre a vantagem de usar reivindicações sobre papéis. Ele também afirma que as funções ainda estão no .NET para compatibilidade com versões anteriores. O vídeo é muito informativo sobre como funcionam as reivindicações, funções, políticas, autorização e autenticação.

Você pode encontrá-lo aqui: Autorização ASP.NET Core com Barr Dorrans

Jonathan Ramos
fonte
8

Tendo usado várias técnicas de autenticação e autorização ao longo de décadas, meu aplicativo MVC atual usa a seguinte metodologia.

As reivindicações são usadas para todas as autorizações. Os usuários são atribuídos a uma função (várias funções são possíveis, mas eu não preciso disso) - mais abaixo.

Como é prática comum, uma classe de atributo ClaimsAuthorize é usada. Como a maioria das ações do controlador são CRUD, eu tenho uma rotina na geração do banco de dados do código que itera todas as ações do controlador e cria tipos de declaração para cada atributo de ação do controlador de Ler / Editar / Criar / Excluir. Por exemplo, de,

[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]

Para uso em uma visão MVC, uma classe de controlador de base apresenta itens de bolsa de visão

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            // get user claims
            var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;

            if (user != null)
            {
                // Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
                List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();

                // set Viewbag with default authorisations on this controller
                ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
                ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
                ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
                ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
            }

            base.OnActionExecuting(filterContext);
        }

Para menus de sites e outras ações sem controle, tenho outras reivindicações. Por exemplo, se um usuário pode visualizar um campo monetário específico.

bool UserHasSpecificClaim(string claimType, string claimValue)
{
    // get user claims
    var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;

    if (user != null)
    {
        // Get the specific claim if any
        return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
    }

    return false;
}

public bool UserHasTradePricesReadClaim
{
    get
    {
        return UserHasSpecificClaim("TradePrices", "Read");
    }
}

Então, onde as funções se encaixam?

Eu tenho uma tabela que vincula uma função a um conjunto de declarações (padrão). Ao definir a autorização do usuário, o padrão é dar ao usuário as declarações de sua função. Cada usuário pode ter mais ou menos reivindicações do que o padrão. Para simplificar a edição, a lista de declarações é mostrada por controlador e ações (em uma linha), com outras declarações então listadas. Os botões são usados ​​com um pouco de Javascript para selecionar um conjunto de ações para minimizar o "clique" necessário para selecionar reivindicações. Ao salvar, as reivindicações dos usuários são excluídas e todas as reivindicações selecionadas são adicionadas. O aplicativo da web carrega declarações apenas uma vez, portanto, quaisquer alterações devem solicitar uma recarga dentro desses dados estáticos.

Os gerentes podem, portanto, selecionar quais declarações estão em cada função e quais declarações um usuário possui após defini-lo para uma função e essas declarações padrão. O sistema tem apenas um pequeno número de usuários, portanto, o gerenciamento desses dados é simples

pixelda
fonte
3

Para entender a diferença entre funções e reivindicações, você enfrenta a limitação de funções e para sentir como as reivindicações resolvem esses problemas, então vou lhe dar 2 cenários para reconhecer o poder das reivindicações em que a função não pode resolver esses problemas:

1- seu site tem dois módulos (páginas, serviço ..etc) o primeiro módulo para criança (menor de 18 anos) e outro para adulto (maior de 18 anos) sua identidade de usuário tem reivindicação de aniversário

você precisa criar uma política sobre esta reivindicação para que a autorização para cada módulo seja dada neste valor e se a idade do usuário for maior de 18 anos, ele poderá ir para o módulo adulto e não antes desta idade

Role é um tipo de dado booleano que você pode ter ou não. O papel role não tinha valores maltados

2- seu site tem função de usuário e você não quer impedir o acesso de usuários para fazer alguma manutenção sem alterar o código

em declarações, você pode criar a política UnderConstrain que, se o usuário verdadeiro não puder visualizar a página, dê autorização de propriedade para a função de usuário.

mohammed rashed
fonte