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

#c# #asp.net-mvc #asp.net-mvc-4 #form-authentication #custom-authentication

#c# #asp.net-mvc #asp.net-mvc-4 #форма-аутентификация #пользовательская аутентификация

Вопрос:

Привет, я написал пользовательскую систему аутентификации на основе ролей для своего 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 amp; loginmodel.Password != null)
            {
                // Get userData via Stored Procedure



                if (userdata != null)
                {                                                                                     

                    FormsAuthentication.SetAuthCookie(loginmodel.UserName, false);
                    if (Url.IsLocalUrl(returnUrl) amp;amp; returnUrl.Length > 1 amp;amp; returnUrl.StartsWith("/")
                        amp;amp; !returnUrl.StartsWith("//") amp;amp; !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 файле,

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

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

Комментарии:

1. Какая строка выдает исключение ссылки на объект внутри FormsAuthentication_OnAuthenticate ? Кажется, что переменная пытается присвоить нулевую ссылку из другого объекта.

2. @TetsuyaYamamoto выдает ошибку, подобную следующей i.imgur.com/jJb18Mi.png

Ответ №1:

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

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

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

и тогда ваш ViewModel Model должен выглядеть следующим образом

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

Комментарии:

1. нужно ли мне создавать новый класс как AuthorizeUserAttribute ?

2. да, вам нужно будет. Для любых пользовательских фильтров вам нужно будет добавить новый класс, но убедитесь, что для любого используемого вами фильтра вы заканчиваете его атрибутом, а затем получаете некоторую форму наследования его базового класса

3. куда я должен поместить этот AuthorizeUserAttribute класс в любое конкретное местоположение?, мой Dashboard метод контроллера в классе домашнего контроллера

4. Способ, которым я это делаю, — создать папку с именем filters, где все они хранятся. это помогает любому, кто смотрит на ваш код, знать, что должно быть где

5. На самом деле мне немного непонятно, вы рекомендуете создать новый вызов папки, filters затем создать вызов класса AuthorizeUserAttribute внутри него, затем поместить FormsAuthentication_OnAuthenticate метод внутри AuthorizeUserAttribute класса не в Global.asax ?