【问题标题】:How to access the current user in a specific aspect如何在特定方面访问当前用户
【发布时间】:2019-03-19 03:00:10
【问题描述】:

如果我采用thesis 中的最后一个方案:

那么我的主要层会是这样的:

  • UI 服务(MVC 应用程序)
  • 业务层
  • 安全服务(用作 MS 身份的包装类库 框架)
  • 使用以前的安全服务授权的方面 业务层方法。

 public class EditEmployeeData : OnMethodBoundaryAspect
    {

        public override void OnEntry(MethodExecutionArgs args)
        {
            Employee emp = (Employee)args.Instance;
            ((System.Security.Claims.ClaimsIdentity)System.Web.HttpContext.Current.User.Identity).HasClaim("Employee", "EditName");
        }
    } 

我想在运行时设置当前用户。


  • 如何访问当前用户以授权他在特定的 业务层的功能?
  • 授权是否应该更靠近 UI 以禁用/隐藏功能并防止调用不允许的操作方法?(在首选方案中,安全层和 UI 之间没有任何交互!!)

【问题讨论】:

  • 您能看看我下面的答案,让我知道它是否有效吗?在此先感谢...

标签: asp.net-mvc asp.net-identity domain-driven-design aop postsharp


【解决方案1】:

更新

请参阅this answer 关于使用声明...


在控制器中,您可以像这样获取当前用户:

using Microsoft.AspNet.Identity.Owin;

public class MyController : Controller
{
    // this code will return 0 if user is not authenticated
    protected long GetUserId()
    {
       // note: I have changed the default UserId type from Guid to long
       return User.Identity.GetUserId<long>(); 

       /* 
        * use this if you are using Guid UserIds (which is the default)     
        * return User.Identity.GetUserId();
        */
    }

如果您想知道如何更改UserId 的类型,请参阅this

如果你可以访问HttpContext,你可以这样获取用户:

// note that I have changed UserId from Guid to long
HttpContext.Current.User.Identity.GetUserId<long>()

如果你想获得 ApplicationUser 使用这个more info here):

// this is how you get user manager from OwinContext    
var userManager = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
// Get ApplicationUser from UserManager 
ApplicationUser user = UserManager.FindById(User.Identity.GetUserId());

如何访问当前用户以授权他在特定的 业务层的功能?

如果您需要访问服务中的当前用户,可以通过注入。使用 ninject,您可以将UserId 注入到服务中:

kernel.Bind<MyService>().ToConstructor(ctorArg => new MyService(
            HttpContext.Current.User.Identity.GetUserId<long>()).InRequestScope(); 

这就是MyService 类的样子:

public class MyService
{
    private readonly long _userId;

    public MyService(long userId)
    {
       // this service always has access to current user (if logged in)
        _userId = userId;
    }
    // more code...

我不确定你的授权过程是什么... ASP.NET Identity,已经为你实现了授权任务。这是在 ASP.NET MVC 默认模板附带的 ApplicationUserManagerApplicationSignInManager 中实现的。您可以在您的操作/类上使用[Authorize] 属性来防止未经授权的访问:

[Authorize] // <-- restricts all action methods of the class, unless marked [AllowAnonymous]
public class MyController : Controller
{
    [HttpPost]
    [Authorize] // <-- restricts this particular action method
    public ActionResult MyAction(long id)
    {
       // do some action which requires authorization
    }

关于 DDD 层,看看这个this link,它解释了属于每个层的服务。

【讨论】:

    【解决方案2】:

    如何访问当前用户以授权他使用业务层的特定功能?

    要访问业务层上的用户信息,可以键入一个名为 ICurrentUser 的接口

    namespace AOPSample
    {
        public interface ICurrentUser
        {
            User GetCurrentUser();
        }
    
        public class User
        {
            public int Id { get; set; }
            public string Username { get; set; }
            public string Role { get; set; }
        }
    }
    

    CurrentUser 类必须能够从公共位置读取用户信息。 HttpContext 可用于此。

    让我们为此编写一个辅助类。

    using System.Web;
    
    namespace AOPSample
    {
        public class ContextHelper
        {
            public T Get<T>()
            {
                T local = default(T);
                string key = typeof(T).GUID.ToString();
                if (HttpContext.Current.Items.Contains(key))
                {
                    local = (T)HttpContext.Current.Items[key];
                }
                return local;
            }
    
            public T Get<T>(string key)
            {
                T local = default(T);
                if (HttpContext.Current.Items.Contains(key))
                {
                    local = (T)HttpContext.Current.Items[key];
                }
                return local;
            }
    
            public void Set<T>(T value)
            {
                string str = typeof(T).GUID.ToString();
                HttpContext.Current.Items[str] = value;
            }
    
            public void Set<T>(T value, string key)
            {
                HttpContext.Current.Items[key] = value;
            }
        }
    }
    

    我们的 CurrentUser 类将使用您的帮助类返回用户信息

    namespace AOPSample
    {
        public class CurrentUser : ICurrentUser
        {
            public User GetCurrentUser()
            {
                return new ContextHelper().Get<User>();
            }
        }
    }
    

    现在用户信息使用 ContextHelper 类写入 HttpContext 并为此使用正确的位置拦截器类

    public class EditEmployeeData : OnMethodBoundaryAspect
        {
    
            public override void OnEntry(MethodExecutionArgs args)
            {
                Employee emp = (Employee)args.Instance;
                ((System.Security.Claims.ClaimsIdentity)System.Web.HttpContext.Current.User.Identity).HasClaim("Employee", "EditName");
    
                new ContextHelper().Set<User>(new User
                {
    
                });
            }
        } 
    

    您可以使用 ICurrentUser 从域层访问用户信息。 HttpContext 对于每个请求和响应都是唯一的

    授权是否应该更靠近 UI 以禁用/隐藏功能并防止调用不允许的操作方法?(在首选方案中,安全层和 UI 之间没有任何交互!!)强>

    这是你的选择

    在我看来,您可以获取用户权限并使用缓存记录它们并将它们用于客户端操作,但根据您用于服务器端的技术,您可以以类似的方式存储每个请求的用户信息。例如;为 wcf 存储 OperationContext 的正确位置。

    【讨论】:

      【解决方案3】:

      如果您使用ASP.NET Identity,您可以尝试以下方法来获取当前用户:

      ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
      
      //If you use int instead of string for primary key, use this:
      ApplicationUser user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(Convert.ToInt32(System.Web.HttpContext.Current.User.Identity.GetUserId()));
      

      希望这会有所帮助...

      【讨论】:

        猜你喜欢
        • 2022-12-31
        • 1970-01-01
        • 1970-01-01
        • 2017-07-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多