Web Api外部承载身份验证和将用户注入存储库

时间:2014-03-11 13:40:21

标签: asp.net-web-api dependency-injection controller authorization

我有一个webapi项目和一个存储库项目。

我已经配置使用oauth,它使用owin中间件承载令牌身份验证。

我有一个包含多个存储库的单元工作。

在存储库中,我想根据登录用户过滤数据。

我希望所有存储库都能通过依赖注入来获取登录用户。

我可以在webapi操作中访问登录用户,但是我很难弄清楚是否/如何使用DI注入当前用户;因为授权是通过webapi授权?:

进行的
[Authorize(Roles = "User")]
    public IQueryable<Folder> Folders()
    {
       // return UnitOfWork.FolderRepository.All().OrderBy(o=>o.FolderId).Skip(10).Take(50);
        var test = HttpContext.Current.GetOwinContext().Authentication;
        //test is populated with the logged on user here, but I don't want to set the user details of the UOW in every action in my controllers
        return UnitOfWork.FolderRepository.All();
    }

因此,在操作文件夹中,授权注释会记录用户。但是我已经使用DI实现了控制器构造函数中的工作单元:

public FolderController(IUnitOfWork uow, UserManager<IdentityUser,int> usermanager)
    {
        UnitOfWork = uow;
        UserManager = usermanager;
    }

IOC容器:

public static IContainer Initialize()
    {
        ObjectFactory.Initialize(x =>
        {
            x.Scan(scan =>
            {
                scan.TheCallingAssembly();
                scan.WithDefaultConventions();
            });

            x.For<HttpContextBase>()
                .HybridHttpOrThreadLocalScoped()
                .Use(() => new HttpContextWrapper(HttpContext.Current));

            x.For<IUnitOfWork>().HttpContextScoped().Use(
                () => new UnitOfWork(new BreezeValidator
                                        (new UserManager<AspNet.Identity.SQLServer.IdentityUser, int>(new UserStore(new SqlDatabase()))))
            );
       }
 }

我曾尝试传入HttpContext.Current.GetOwinContext(),但此时授权尚未发生,因此尚未设置Principal。

我已经查看了actionfilters(在授权过滤器之后运行),但无法弄清楚我将如何使用已登录的用户集返回一个新的工作单元实例,返回控制器。

...或者我是否可以通过动作过滤器在控制器上设置属性?

所以问题是,如何在我所有控制器的单元工作中设置用户详细信息,而不会造成大量重复?

由于

编辑:我有一个有效的解决方案,但仍然不确定这是正确的方法:

我创建了一个动作过滤器,然后从那里获取控制器并在控制器的unitOfWork属性上设置UserPrincipal属性。

using Project1.Web.Controllers;
using System;
using System.Linq;
using System.Web.Http.Controllers;
using System.Web.Http.Filters;

namespace Project1.Web.Filters
{
public class InjectUserAttribute : ActionFilterAttribute
{

        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            var action = actionContext.ControllerContext.Controller;
            UowApiController ctrl = (UowApiController)actionContext.ControllerContext.Controller;
            ctrl.UnitOfWork.UserPrincipal = actionContext.RequestContext.Principal;
        }

}

然后,在UserPrincipal的UnitOfWork设置器中,我在包含的存储库中设置了UserPrincipal:

public IPrincipal UserPrincipal
    {
        get
        {
            return this.userPrincipal;
        }
        set
        {
            this.userPrincipal = value;

            ((Repository<Folder>)FolderRepository).UserPrincipal = value;
        }
    }

现在可以使用了,但它没有实现依赖注入。

此外,我想知道这是一种“正确”的方式,或者更好的方法是什么?

1 个答案:

答案 0 :(得分:0)

我正在寻找同样的事情并决定这一点。我认为这个答案也与你有关。 Proper way to dependency inject authenticated user to my repository class

我刚刚在服务类中添加了一个getter,它在请求时访问用户身份。

public class MyService
{
    //ctor...

    public IEnumerable<Results> GetResults()
    {
        return _ResultRepository.GetResultsByUser(UserIdentity);
    }

    IIdentity UserIdentity
    {
        get { return Thread.CurrentPrincipal.Identity; }
    }
}