如何在ASP.NET MVC View中通过自定义Action Filter对用户进行身份验证?

时间:2016-12-23 20:09:34

标签: c# asp.net

我有一个使用我的身份验证过滤器的操作方法:

public class TutorAuthenticationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var req = filterContext.HttpContext.Request;
        var auth = req.Headers["Authorization"];
        if (!string.IsNullOrEmpty(auth))
        {
            var cred = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
            var user = new { Name = cred[0], Password = cred[1] };
            if (userService.AuthorizeTutor(user.Name, user.Password))
            {
                return;
            }
        }
        filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", $"Basic realm= {BasicRealm}");

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

我想在主页上显示已经过这种方式验证的用户的内容,但这在我的视图中不起作用:(

@if (Request.IsAuthenticated)
{
    <h1>Hello</h1>
}

我知道它不起作用,因为我不使用Identity,但有什么方法可以做到这一点吗?

感谢您的回答:)

5 个答案:

答案 0 :(得分:3)

为请求对象创建一个新的扩展方法说(IsUserAuthenticated())&amp;在该方法中检查用户是否有效。 完成此操作后,您可以像使用Request.IsAuthenticated属性一样使用此新扩展方法。

以下是示例代码,您需要根据需要进行调整。 (特别是

userservice 

初​​始化)

public class RequestValidator
{
    public bool IsValid(HttpRequest request)
    {
       bool isValid  = false;

       //TODO: Intitialize your userService here, may be using DI or a concrete object creation depending on your implementation

       var auth = request.Headers["Authorization"];
       if (!string.IsNullOrEmpty(auth))
       {
           var cred = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(auth.Substring(6))).Split(':');
           var user = new { Name = cred[0], Password = cred[1] };

           isValid = userService.AuthorizeTutor(user.Name, user.Password))            
       }

      return isValid; 
    }
}

您的属性会像这样改变

public class TutorAuthenticationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var req = filterContext.HttpContext.Request;
        RequestValidator validator = new RequestValidator(); 
        if(validator.IsValid(request))
        {
            return; 
        }

        filterContext.HttpContext.Response.AddHeader("WWW-Authenticate", $"Basic realm= {BasicRealm}");

        filterContext.Result = new HttpUnauthorizedResult();
    }
}

在视图上使用的扩展方法将是

public static class Extensions
{
    public static bool IsUserAuthenticated(this HttpRequest request)
    {
        RequestValidator validator = new RequestValidator(); 
        return validator.IsValid(request); 
    }
}

像这样使用

@if(Request.IsUserAuthenticated())
{
     <p>Hello</p>
}

答案 1 :(得分:3)

我想,在标头中发送登录名和密码并不安全。更好的解决方案是用户验证的一次。检查后,您可以检查所有请求。

例如,如果您使用FormsAuthentication和authCookie,则非常简单:

  1. 在web.config中设置auth mentod:<authentication mode="Forms" />

  2. 当登录名和密码有效时,使用FormsAuthentication.SetAuthCookie(userName, createPersistentCookie = true);当用户登录应用程序时,此步骤仅执行一次。

  3. 然后您可以在视图中使用属性this.Request.IsAuthenticated或在控制器(或过滤器)中使用HttpContext.Current.Request.IsAuthenticated

  4. 它在conntrolers或actions(conntrollers中的公共方法)上运行属性[Authorize]。当请求未经过身份验证时,请求将重定向到默认(或在web.config中设置)登录页面。

答案 2 :(得分:1)

如果要传递指示用户是否经过身份验证的布尔值,可能只需使用模型对象并将其传递给视图即可。

或许您应该检查一下您的表单身份验证,以使Request.IsAuthenticated正常工作。 This thread将有助于开始挖掘。

另一种选择是考虑使用IAuthorizationFilter而不是自定义操作过滤器。 This thread将是一个起点。

希望有所帮助!

答案 3 :(得分:1)

为了达到您的目的,您需要将HttpContext.User设置为某个有效的IPrincipal。 因此,如果根据您的条件,用户有效,您只需创建一个GenericPrinicpal并使用您刚创建的实例设置HttpContext.User

这样的事情:

var genericIdentity=new GenericIdentity(user.Name,  "CustomAuthType");
var genericPrincipal=new GenericPrincipal(genericIdentity, null);

HttpContext.User = genericPrincipal;

使用GenericIdentity时,IsAuthenticated的值取决于Name属性,因此只要GenericIdentity具有名称,就会认为它已经过身份验证。

在此示例中,我设置了HttpContext.User而不是Thread.CurrentPrincipal,以便您可以从IsAuthenticated属性中获取Request.IsAuthenticated

一些额外的相关信息:

GenericIdentity Class

Principal and Identity Objects

Create GenericPrincipal and GenericIdentity Objects

Replacing a Principal Object

答案 4 :(得分:0)

在您的startup.cs文件中

添加此

app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Login"),

            SlidingExpiration = true,
            ExpireTimeSpan = TimeSpan.FromMinutes(40)


        });