Пользовательская система аутентификации на основе ролей в ASP.NET MVC, направляющая на ошибку

Здравствуйте, я написал настраиваемую систему аутентификации на основе ролей для своего приложения ASP.NET MVC.

Итак, изменения, которые мне понравились

В файле Global.asax.cs добавлен следующий метод

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

}
protected void FormsAuthentication_OnAuthenticate(Object sender, FormsAuthenticationEventArgs e)
{
try
{
   if (FormsAuthentication.CookiesSupported == true)
   {
    if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
    {
        try
        {                              
            string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name;
            string roles = string.Empty;

            if(!string.IsNullOrEmpty(username))
            {
                // user --> Roles Getting from DB using Stored Procdure

                roles = user.RoleName;
            }

            e.User = new System.Security.Principal.GenericPrincipal(
              new System.Security.Principal.GenericIdentity(username, "Forms"), roles.Split(';'));
        }
        catch (Exception)
        {
           throw;
        }
    }
}
}
catch (Exception)
{
    throw;
}

}

в Web.Config

<authentication mode="Forms">
  <forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>

в FilterConfig.cs в папке App_Start

public class FilterConfig
{
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new HandleErrorAttribute());
    }
}

в методе контроллера входа

    [AllowAnonymous]
    public ActionResult Login(string returnUrl)
    {
        ViewBag.ReturnUrl = returnUrl;
        return View();
    }

    // POST: /Account/Login

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public async Task<ActionResult> Login(LoginUserViewModel loginmodel, string returnUrl)
    {
       try
       { 
            UserViewModel userdata=null;

            if (loginmodel.UserName != null & loginmodel.Password != null)
            {
                // Get userData via Stored Procedure



                if (userdata != null)
                {                                                                                     

                    FormsAuthentication.SetAuthCookie(loginmodel.UserName, false);
                    if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
                        && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Dashboard", "Home");
                    }


                }
                else
                {
                    ModelState.AddModelError("", "Login failed.");
                }

            }   
            else
            {
                ModelState.AddModelError("", "Login failed.");
            }

            return View(userdata);
       }
       catch (Exception)
       {
           throw;
       }
    }

Страница Login.cshtml

                @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" }))
                {
                    @Html.AntiForgeryToken()
                    @* rest of data *@
                    @Html.ValidationSummary(true, "", new { @class = "text-danger" })

                    <div class="form-group ">
                        <div class="col-sm-12 col-lg-12 col-md-12">
                            <button type="submit" >Login</button>
                        </div>
                    </div>
                }

Наконец, в HomeController.cs

    [Authorize(Roles="admin")]
    public ActionResult Dashboard()
    {
      //rest of fetching
    }

Здесь все работало отлично, но я случайно отладил / запустил страницу просмотра панели без входа,

Теперь я получаю следующую ошибку в методе FormsAuthentication_OnAuthenticate в файле Global.asax,

В экземпляре объекта не задана ссылка на объект.

Теперь, когда я начинаю отлаживать этот проект, он заканчивается


person Kelum    schedule 20.10.2016    source источник
comment
Какая строка выдает исключение ссылки на объект внутри FormsAuthentication_OnAuthenticate? Кажется, что переменная пытается присвоить нулевую ссылку из другого объекта.   -  person Tetsuya Yamamoto    schedule 20.10.2016
comment
@TetsuyaYamamoto получает ошибку, например, после i.imgur.com/jJb18Mi.png   -  person Kelum    schedule 20.10.2016


Ответы (1)


ваш атрибут Authorize не использует вашу реализацию, то, что вы создали, вы действительно должны были сделать в пользовательском AuthoriseAttribue, который наследует AuthorizeAttribute

что-то вроде этого с вашим собственным кодом, получающим роли и аутентификацию

public class AuthorizeUserAttribute : AuthorizeAttribute
{
 .... 
 //your code here 
}

и тогда ваша ViewModel\Model должна выглядеть так

[AuthorizeUserAttribute(Roles="admin")]
public ActionResult Dashboard()
{
  //rest of fetching
}
person Simon Price    schedule 20.10.2016
comment
мне нужно создать новый класс как AuthorizeUserAttribute? - person Kelum; 20.10.2016
comment
да, вам нужно будет. Для любых пользовательских фильтров вам нужно будет добавить новый класс, но убедитесь, что для любого фильтра, который вы используете, вы заканчиваете его атрибутом, а затем имеете некоторую форму наследования его базового класса. - person Simon Price; 20.10.2016
comment
где я должен поместить этот класс AuthorizeUserAttribute в любое конкретное место?, мой метод контроллера Dashboard в классе домашнего контроллера - person Kelum; 20.10.2016
comment
Я делаю это так, чтобы иметь папку с именем фильтры, где они все хранятся. это помогает любому, кто смотрит на ваш код, знать, что и где должно быть - person Simon Price; 20.10.2016
comment
На самом деле мне это немного неясно, вы рекомендуете создать новый вызов папки filters, затем создать вызов класса AuthorizeUserAttribute внутри него, а затем поместить метод FormsAuthentication_OnAuthenticate внутри класса AuthorizeUserAttribute не в Global.asax? - person Kelum; 20.10.2016
comment
да, это то, что я говорю, что вам нужно сделать, потому что в данный момент вы не вызываете свою реализацию - person Simon Price; 20.10.2016
comment
Но тогда я заканчиваю со следующей ошибкой :( The name 'Request' does not exist in the current context в следующих строках --> if (Request.Cookies[FormsAuthentication.FormsCookieName] != null) строка и string username = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value).Name; строка - person Kelum; 20.10.2016