如何设计控制器动作来响应猜测和授权用户

本文关键字:响应 用户 授权 控制器 | 更新日期: 2023-09-27 18:15:33

我在控制器设计中为已经在系统中注册的用户设置了一个动作:

 [Authorize]
 public ActionResult getUserData()
 {
      string UserId = User.Identity.GetUserId();
      return getDataFromDB(UserID);
 }

并且工作正常。如果您还没有通过身份验证,也可以重定向到LOGIN页面。

但我也想有一个虚拟函数getFakeData()匿名用户访问页面,这样他们就可以看到类似的页面演示。

我应该在哪里放置验证以查看用户是否经过身份验证并更改行为?

  1. 在网页上,我可以设置基于用户是否被认证的dataUrl。我可以做一个没有[Authorize]标签的分离函数

    @if (Request.IsAuthenticated)
    {
         dataUrl = '=/Project/Controller/getUserData'
    } else {
         dataUrl = '=/Project/Controller/getFakeData'    
    }
    
  2. 或者我可以在相同的动作控制器上做,并检查用户是否经过身份验证?但我不确定这是否可能。

  3. 或者是更好的方法?

如何设计控制器动作来响应猜测和授权用户

有多种方法可以做到这一点,但这里是我的建议

// For ASP.Net MVC 5 simply inherit from AuthorizationAttribute and override the methods.
public class AccessControlAttribute : Attribute, IAuthorizationFilter
{
    private readonly Roles role;
    public AccessControlAttribute(Roles role) {
        this.role = role;
    }
    private Boolean AuthorizationCore(AuthorizationFilterContext context) {
        var username = context.HttpContext.Request.Cookies["loginCookie_username"];
        var password = context.HttpContext.Request.Cookies["loginCookie_password"];
        if (role == Roles.FakeFullAccess) {
            username = "FAKE";
            goto final;
        }
        //In ASP.Net MVC 5 use Ninject for dependency injection and get the service using : [NinjectContext].GetKernel.Get<DbContext>();
        DbContext db = (DbContext) context.HttpContext.RequestServices.GetService(typeof(DbContext));
        if (username != null && password != null) {
            var findUser = db.Set<Login>().Find(username);
            if (findUser != null && findUser.Password.Equals(password) && findUser.RoleId == (int)role) {
                goto final;
            }
        }
        return false;
        final: {
            context.HttpContext.User.AddIdentity(new System.Security.Principal.GenericIdentity(username));
            return true;
        }   
    }
    private void HandleUnauthorizedRequest(AuthorizationFilterContext context) {
        context.Result = new RedirectToRouteResult(new {
            area = "",
            controller = "",
            action = ""
        });
    }        
    public void OnAuthorization(AuthorizationFilterContext context)
    {
        if (AuthorizationCore(context))
        {
            // If using a combination of roles, you have to unmask it
            if (role == Roles.FakeFullAccess) {
                context.HttpContext.Request.Headers.Add("Render", "FakeAccess");
            }
            else if (role == Roles.Admin)
            {
                context.HttpContext.Request.Headers.Add("Render", "AdminAccess");
            }
        }
        else {
            HandleUnauthorizedRequest(context);
        }
    }
}
[Flags]
public enum Roles
{
    FakeFullAccess = 0, 
    ReadOnly = 1,
    Admin = 2,
    Supervisor = 1 << 2,
    AnotherRole = 1 << 3
}

在您的视图中,您可以读取添加的标题和自定义视图(在ASP。Net Core没有访问ControllerContext和ViewBag,如果使用ASP。. Net MVC 5你不需要使用头的技巧)

// For ASP.Net MVC 5 use the ViewBag or ViewData
@Html.Partial(HttpContext.Request.Header["Render"])
//Assuming this renders the menu with proper functions.

现在您拥有了完全可定制的基于角色的身份验证系统,并具有用于测试的假访问。

更新:要使用该属性,请执行以下操作

[AccessControl(Role.Admin)]
public TestController: Controller {
    ...
}
// Dedicated for testing
[AccessControl(Role.FakeAccess)]
public PreviewController: TestCoontroller{}

如果需要的话,你也可以像[AccessControl(Role.FakeAccess | Role.ReadOnly)]那样组合角色,但是你必须实现一个揭开面具的方法。

相关文章: