Session1 For MVC

MVC tutorial

  1. MVC and WebApi

For MVC, we have Controller, View, Model. Controller expose functions which will return View.
Controller:
we call the factory to get the data and populate it to the viewModel, and then we populate the View template with the Viewmodel and return the result back to the Client.

Now, we create a sample 'hello world'

Controller code:

public ControllerName:Controller
{
    public ActionResult ActionName(parameters){
        //...do some logical

        return View("ViewName",paramterObject);
    }
}

View code:

@using namespace;
@model paramterObject;
<html>
/... html content.
</html>

We need to configure the Route for the Controller. we can do this in the file /App_Start/RouteConfig.cs. we can add block like this:

routes.MapRoute(
                name: "RouteName",// this is used by server side code for redirection.
                url: "{controller}/{action}/{id}",// controllerName , ActionName is necessary, even though we can provide default. id is not necessary.
                defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } // we provide the default value here.
            );

Keep in mind, in the RouteConfig.cs file, a serize of routes.MapRoute defined, so the match is by the sort of MapRoute definition.
we can also use another way to do the Route definition, that is annotation. Detail Doc.
This feature is involved from MVC5, we need to add this to our RouteConfig.cs file routes.MapMvcAttributeRoutes(); we can keep both styles, so here is a simple example:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute(“{resource}.axd/{*pathInfo}”);
 
    routes.MapMvcAttributeRoutes();
 
    routes.MapRoute(
        name: “Default”,
        url: “{controller}/{action}/{id}”,
        defaults: new { controller = “Home”, action = “Index”, id = UrlParameter.Optional }
    );
 }

  1. we talk about something in the Global.asax.cs. we can see this content in this file
public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }

As Route has been taled in step1, we can talk about others

  1. Authentication usage

3.1 Form Authentication

for the process, we can refer a link.
several classes are needed to show the detail: FormsAuthentication, FormsAuthenticationTicket.
In the FormsAuthenticationTicket, we have an example.
sample code here About generating an authentication ticket:

if (Membership.ValidateUser(username, password))
    {
      string userData = "ApplicationSpecific data for this user.";

      FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1,
        username,
        DateTime.Now,
        DateTime.Now.AddMinutes(30),
        isPersistent,
        userData,
        FormsAuthentication.FormsCookiePath); // we create a Authentication ticket here.

      // Encrypt the ticket.
      string encTicket = FormsAuthentication.Encrypt(ticket);

      // Create the cookie.
      Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));

      // Redirect back to original URL.
      Response.Redirect(FormsAuthentication.GetRedirectUrl(username, isPersistent));

. How to use the Authorization?

we have an attribute AuthorizeAttribute.
some relative Class should be familar with, e.g. HttpContext, Iprincipal, Identidy

here is a very useful atrical about custom Authentication

Now, Let's summary the process about the customer Authentication and authorization.

  1. First we need something to represent the user Identity, it contains userName, isAuthenticated. Then mvc wrap it with an interface Iprincipal, which contains the Idendity and a method bool IsInRole(string).
  2. Then mvc already provide us a BuildIn attribute AuthorizeAttribute, which includes "Roles","users" properties, and "OnAuthorization(AuthorizationContext)" methods. so if we need to implete our customer authorize attribute, we need to inherit from AuthorizeAttribute class.
    we override the "OnAuthorization(AuthorizationContext)" method, and add the Authorize logical here and if Authorization failure, we add ActionResut to the AuthorizationContext.Result by supply the RedirectToRouteResult object.
  3. for mvc4+, we also need to define the event_handler protected void Application_PostAuthenticateRequest(Object sender, EventArgs e), In this handler, we need to exact the userinfo from the cookie and replace the HttpContext.current.user, so that we can add some plain info to it.
  4. we need to use the customized AuthorizeAttribute, we need to register it , we can do it by functions in the App_Client/FilterConfig.cs, filters.Add(new CustomerAuthorizeAttribute());
  5. Now we can use the customizedAuthorizedAttribute in our controller and Action.

To Keep an example, we keep a copy of code here:

CustomPrincipal

public class CustomPrincipal : IPrincipal
 {
    public IIdentity Identity { get; private set; }
    public bool IsInRole(string role)
    {
        if (roles.Any(r => role.Contains(r)))
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    
    public CustomPrincipal(string Username)
    {
        this.Identity = new GenericIdentity(Username);
    }
    
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string[] roles { get; set; }
 }

WebConfig

 <system.web>
    <authentication mode="Forms">
    <forms loginUrl="Login.aspx"
        protection="All"
        timeout="30"
        name=".ASPXAUTH" 
        path="/"
        requireSSL="false"
        slidingExpiration="true"
        defaultUrl="default.aspx"
        cookieless="UseDeviceProfile"
        enableCrossAppRedirects="false" />
    </authentication>
</system.web>

CustomAuthorizeAttribute

public class CustomAuthorizeAttribute : AuthorizeAttribute
 {
    public string UsersConfigKey { get; set; }
    public string RolesConfigKey { get; set; }
    
    protected virtual CustomPrincipal CurrentUser
    {
        get { return HttpContext.Current.User as CustomPrincipal; }
    }
    
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAuthenticated)
        {
            var authorizedUsers = ConfigurationManager.AppSettings[UsersConfigKey];
            var authorizedRoles = ConfigurationManager.AppSettings[RolesConfigKey];
            
            Users = String.IsNullOrEmpty(Users) ? authorizedUsers : Users;
            Roles = String.IsNullOrEmpty(Roles) ? authorizedRoles : Roles;
            
            if (!String.IsNullOrEmpty(Roles))
            {
                if (!CurrentUser.IsInRole(Roles))
                {
                    filterContext.Result = new RedirectToRouteResult(new
                    RouteValueDictionary(new { controller = "Error", action = "AccessDenied" }));
                    
                    // base.OnAuthorization(filterContext); //returns to login url
                }
            }
    
            if (!String.IsNullOrEmpty(Users))
            {
                if (!Users.Contains(CurrentUser.UserId.ToString()))
                {
                    filterContext.Result = new RedirectToRouteResult(new
                    RouteValueDictionary(new { controller = "Error", action = "AccessDenied" }));
                    
                    // base.OnAuthorization(filterContext); //returns to login url
                }
            }
        }
    
    }
 }

Register CustomAuthorizeAttribute in FilterConfig.cs

namespace WebApplication1
{
    public class FilterConfig
    {
        public static void RegisterGlobalFilters(GlobalFilterCollection filters)
        {
            filters.Add(new HandleErrorAttribute());
            filters.Add(new AuthorizeAttribute());//New Line
            filters.Add(new CustomAuthorizeAttribute());//New Line
        }
    }
}

Generating Authorization cookies

public class AccountController : Controller
 {
    DataContext Context = new DataContext();
    //
    // GET: /Account/
    public ActionResult Index()
    {
        return View();
    }
    
    [HttpPost]
    public ActionResult Index(LoginViewModel model, string returnUrl = "")
    {
        if (ModelState.IsValid)
        {
            var user = Context.Users.Where(u => u.Username == model.Username && u.Password == model.Password).FirstOrDefault();
            if (user != null)
            {
                var roles=user.Roles.Select(m => m.RoleName).ToArray();
                
                CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
                serializeModel.UserId = user.UserId;
                serializeModel.FirstName = user.FirstName;
                serializeModel.LastName = user.LastName;
                serializeModel.roles = roles;
                
                string userData = JsonConvert.SerializeObject(serializeModel);
                FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
                1,
                user.Email,
                DateTime.Now,
                DateTime.Now.AddMinutes(15),
                false, //pass here true, if you want to implement remember me functionality
                userData);
                
                string encTicket = FormsAuthentication.Encrypt(authTicket);
                HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
                Response.Cookies.Add(faCookie);
                
                if(roles.Contains("Admin"))
                {
                    return RedirectToAction("Index", "Admin");
                }
                else if (roles.Contains("User"))
                {
                    return RedirectToAction("Index", "User");
                }
                else
                {
                    return RedirectToAction("Index", "Home");
                }
            }
        
            ModelState.AddModelError("", "Incorrect username and/or password");
        }
        
        return View(model);
    }
    
    [AllowAnonymous]
    public ActionResult LogOut()
    {
        FormsAuthentication.SignOut();
        return RedirectToAction("Login", "Account", null);
    }
 }

Exact user info from Authorization Cookies

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
 {
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
    if (authCookie != null)
    {
    
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
        
        CustomPrincipalSerializeModel serializeModel = JsonConvert.DeserializeObject<CustomPrincipalSerializeModel>(authTicket.UserData);
        CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
        newUser.UserId = serializeModel.UserId;
        newUser.FirstName = serializeModel.FirstName;
        newUser.LastName = serializeModel.LastName;
        newUser.roles = serializeModel.roles;
        
        HttpContext.Current.User = newUser;
    }
 
 }

user example for CustomAuthorizeAttribute
Controller Level

[CustomAuthorize(Roles= "Admin")]
 // [CustomAuthorize(Users = "1")]
 public class AdminController : BaseController
 {
    //
    // GET: /Admin/
    public ActionResult Index()
    {
        return View();
    }
 }

Roles or users from webconfig

<add key="RolesConfigKey" value="Admin"/>
<add key="UsersConfigKey" value="2,3"/>
//[CustomAuthorize(RolesConfigKey = "RolesConfigKey")]
[CustomAuthorize(UsersConfigKey = "UsersConfigKey")]
 
 public class AdminController : BaseController
 {
    //
    // GET: /Admin/
    public ActionResult Index()
    {
        return View();
    }
 }

 [CustomAuthorize(RolesConfigKey = "RolesConfigKey")]
// [CustomAuthorize(UsersConfigKey = "UsersConfigKey")]
 public class UserController : BaseController
 {
    //
    // GET: /User/
    public ActionResult Index()
    {
        return View();
    }
 }

if we don't need to filter by user and role, windows can help to much more,
for example, we can add this step to authorize the Authorized cookies. FormsAuthentication.SetAuthCookie(u.UserName, false), we can also use this to logoff FormsAuthentication.SignOut().

posted @ 2016-10-21 10:10  kongshu  阅读(125)  评论(0编辑  收藏  举报