Pergunta

O problema que vejo com esse código, é que ele vai ser reutilizado um monte; qualquer coisa que está sendo editado / criado por um usuário autenticado (exceto para administradores do site) só terá acesso a um seus "estúdios" objetos.

A minha pergunta a todos vocês; como você re-fator isso para a camada de serviço pode ser abstraída a partir do conhecimento do cliente. Tenho a intenção de reutilizar a camada de serviço em um aplicativo de desktop stand-alone mais tarde.

Por favor, lançar alguma luz sobre os meus caminhos errados! Eu aprecio muito isso.

AuthorizeOwnerAttribute.cs (AuthorizeAttribute)

protected override bool AuthorizeCore(HttpContextBase httpContext)
{
    // Get the authentication cookie
    string cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = httpContext.Request.Cookies[cookieName];

    // If the cookie can't be found, don't issue the ticket
    if (authCookie == null) return false;

    // Get the authentication ticket and rebuild the principal & identity
    FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    string[] userData = authTicket.UserData.Split(new[] { '|' });

    int userId = Int32.Parse(userData[0]);
    int studioID = Int32.Parse(userData[1]);
    GenericIdentity userIdentity = new GenericIdentity(authTicket.Name);
    WebPrincipal userPrincipal = new WebPrincipal(userIdentity, userId, studioID);
    httpContext.User = userPrincipal;

    return true;
}

Dentro do meu "Usuário" Controller anexar esse atributo para qualquer método que requer um proprietário

    [AuthorizeOwner]
    public ActionResult Edit(int Id)
    {
        IUser user = userService.GetById(HttpContext.User, Id);
        return View(user);
    }

Agora, no meu serviço camada é onde eu estou verificando o passado para baixo IPrincipal se ele tem acesso ao objeto que está sendo solicitado. Este é o lugar onde ele está ficando mau cheiro:

UserService.cs

    public IUser GetById(IPrincipal authUser, int id)
    {
        if (authUser == null) throw new ArgumentException("user");

        WebPrincipal webPrincipal = authUser as WebPrincipal;
        if (webPrincipal == null) throw new AuthenticationException("User is not logged in");

        IUser user = repository.GetByID(id).FirstOrDefault();
        if (user != null)
        {
            if (user.StudioID != webPrincipal.StudioID) throw new AuthenticationException("User does not have ownership of this object");
            return user;
        }

        throw new ArgumentException("Couldn't find a user by the id specified", "id");
    }
Foi útil?

Solução

Eu não tenho certeza eu estaria armazenando os IDs reais no cookie, que é um pouco demasiado exposta. Eu estaria mais inclinado a usar o hash de sessão para armazenar os dados mantendo-se assim no servidor e não expostos.

Eu também usar o Modelo (passando o ID do usuário) para determinar quais objetos para retornar, ou seja, aqueles que têm um studioID correspondente. Dessa forma, o controlador apenas iria ter que chamar "GetObjects (id int)", se eles não têm acesso a qualquer coisa então você obtém um nulo ou uma coleção de volta vazio. Que se sente mais limpo para mim.

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