繁体   English   中英

在多层Web应用程序的服务层中引用Microsoft.AspNet.Identity是否被认为是不好的做法?

[英]Is it considered bad practice to reference the Microsoft.AspNet.Identity in the service layer of a multi layered web application?

在我的MVC应用程序中,当前正在Application_PostAuthenticateRequest()方法中设置Thread.CurrentPrincipal = HttpContext.Current.User,例如

    protected void Application_PostAuthenticateRequest()
    {
        Thread.CurrentPrincipal = HttpContext.Current.User;
    }

这使我可以在其他程序集即服务层中使用Thread.CurrentPrincipal。 例如:

using System.Security;
using System.Security.Permissions;
using System.Threading;
using Microsoft.AspNet.Identity;

namespace ServiceLayer
{
public class FinancialAccount
{
    public decimal Balance { get; set; }
    public string Owner { get; set; }
}

public class FinancialAccountRepository
{
    public FinancialAccount GetById(int id)
    {
        if (id == 1)
            return new FinancialAccount {Owner = "ac40fe16-1971-4b0d-b4d5-af850d0c2c05", Balance = 40324234};

        return new FinancialAccount {Owner = "3e2d1b43-1c63-4263-8c52-44d050279596", Balance = 100};
    }
}

public class FinancialService
{
    private readonly FinancialAccountRepository _financialAccountRepository;

    public FinancialService()
    {
        _financialAccountRepository = new FinancialAccountRepository();
    }

    [PrincipalPermission(SecurityAction.Demand, Role = Constants.RoleNames.AccountHolder)]
    [PrincipalPermission(SecurityAction.Demand, Role = Constants.RoleNames.BankManager)]
    public string GetFinancialAccountDetails(int accountId)
    {
        FinancialAccount financialAccount = _financialAccountRepository.GetById(accountId);
        ThrowExceptionIfUnauthorized(financialAccount);
        return "The account balance of account: " + accountId + " is " + financialAccount.Balance.ToString("C");
    }

    private void ThrowExceptionIfUnauthorized(FinancialAccount financialAccount)
    {
        if (financialAccount.Owner != Thread.CurrentPrincipal.Identity.GetUserId() && !Thread.CurrentPrincipal.IsInRole(Constants.RoleNames.BankManager))
            throw new SecurityException();
    }
}
}

尽管我有两个担忧,但这一切似乎都可以正常工作:

  1. 可以在PostAuthenticationRequest方法中设置Thread.CurrentPrincipal吗?
  2. 是否可以在服务层中引用使用Microsoft.AspNet.Identity?

我需要引用Microsoft.AspNet.IDentity的原因是因为IPrincipal不包含userId,而仅包含用户名。

如果有任何这样的做法被认为是不好的做法,我该如何解决当前的问题?

  1. 可以在PostAuthenticationRequest方法中设置Thread.CurrentPrincipal吗?

是的,可以将Principal对象(HttpContext.Current.User)分配给当前线程是可以的。

  1. 是否可以在服务层中引用使用Microsoft.AspNet.Identity?

尽管您可以访问它,但这不是一个好习惯。

原因是-

  1. 服务层不应与表示层紧密结合。
  2. 很难对服务层进行单元测试。

相反,如果要在服务层中使用UserId,则希望将UserId作为参数传递。

在您的方案中

您想返回FinancialAccount而不是字符串值,并让表示层使用string.Format()创建文本。

原因是您要维护“ 单一责任原则” 换句话说,如果您想稍后更改经常发生的文本,则确实要再次触摸服务层。

public FinancialAccount GetFinancialAccountDetails(int accountId)
{
   return _financialAccountRepository.GetById(accountId);        
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM