How to persist data in MVC 5 project - asp.net-mvc

I am wanting to develop a MVC 5 project that can provide the same look and feel in terms of styling, header, menu and footer etc, from the calling website.
So for example, the calling website will post a header, menu and footer, or a encrypted key for database lookup, so the MVC project can take this and create a view that will look like the calling website.
This works fine, and I could use TempData and TempData.Keep() to persist the page styling throughout all the requests.
However, now I want to allow the user on the MVC site to login / authenticate, so that they can see some privileged pages.
The problem I have is I can let the user login, and still persist the styling using TempData. The problem comes when the user session expires, and they click, I lose the styling information.
At the moment I have this controller and action which deals with the login;
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(User user)
{
TempData["User"] = null;
if (ModelState.IsValid)
{
if (user.IsValid(user.Email, user.Password, Request.UserHostAddress))
{
string userData = user.Email;
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(user.Email, false);
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(authCookie.Value);
FormsAuthenticationTicket newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, userData);
authCookie.Value = FormsAuthentication.Encrypt(newTicket);
Response.Cookies.Add(authCookie);
TempData.Keep("CmsContent");
return RedirectToAction("Index", "ManageAccount");
}
else
{
TempData["User"] = user;
TempData.Keep("CmsContent");
return RedirectToAction("Index", "Home");
}
}
else
{
user.Message = "Invalid email/password";
TempData["User"] = user;
TempData.Keep("CmsContent");
return RedirectToAction("Index", "Home");
}
}
Currently the styling information is being persisted using TempData.Keep("CmsContent"), but when the session expires it is lost.
How best can I deal with this sort of issue.

Related

ASP.NET MVC 5 - let admin change other users password. Password changed in database but can't login

I'm told to make admin have a functionality to change other users password without knowing their original password. I wrote a code that changes and saves password successfully in database, but when I try to login as that user I can't.
UsersController:
public ActionResult ChangePassword()
{
return View();
}
[HttpPost]
public ActionResult ChangePassword(int id, ViewModels.ChangePasswordViewModel model)
{
if (!SessionControlService.CheckIsLoginStillTrue(_loginsService, HttpContext))
return RedirectToAction("Login", "Account");
if (!User.IsInAnyRoles("Admin", "PropertyManager"))
return RedirectToAction("Error", "Errors",
new { error = Facility.Web.Resources.Resources.ErrorNotHavePermission });
var user = _userService.GetUser(id);
if (user == null)
return RedirectToAction("Error", "Errors",
new { error = Facility.Web.Resources.Resources.ErrorURLNotExist });
user.Password = model.NewPassword;
_userService.UpdateUser(user);
return RedirectToAction("Details", new { id = id });
}
Why can't I use the changed password which is saved in the database to login?
How can I make this work?
In ASP.NET MVC5, password is hashed... you cannot save a plaintext password like that.
You need to use these two methods:
var manager = new ApplicationUserManager(...);
var token = manager.GeneratePasswordResetToken(userId)
manager.ResetPassword(userId, token, newPassword)
You could also try ApplicationUserManager.UpdatePassword(...), or RemovePassword(...) and AddPassword(...)
ApplicationUserManager is normally in IdentityConfig.cs

Redirect after login in mvc5

In MVC, when writing a project, it writes a login scenario, the login screen, and the registry, and everything.
I created the admin page, but before you go to the page if I have not created a cookie, send me the login page. I want to do it after you log in. I do not know how to redirect to the admin page after logging in.
You have the code itself that writes the viewbag.retutnurl while you are building a project, but I do not know what the controller is.
Now I'm not sure where the value comes from.
If anyone knows exactly and done, please advise.
In the default generated method change the first case, which executes when the login is successful, and add you custom redirection here like this:
switch (result)
{
case SignInStatus.Success:
return RedirectToAction("Index", "Admin", null); // new code
case SignInStatus.LockedOut:
return View("Lockout");
case SignInStatus.RequiresVerification:
return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = false });
case SignInStatus.Failure:
default:
// If the user does not have an account, then prompt the user to create an account
ViewBag.ReturnUrl = returnUrl;
ViewBag.LoginProvider = loginInfo.Login.LoginProvider;
return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = loginInfo.Email });
}
And in your admin class you should put the [Authorize] data annotation
//admin controller
[Authorize]
public ActionResult Index()
{
return View();
}
You can try any of these two ways to deal with it.
public ActionResult Index() {
return RedirectToAction("AdminAction");
//Or you can try this
return RedirectToAction("whateverAction", "whateverController");
}

Windows Authentication Logout / SigninwithDifferent User

I am using windows authentication in ASP.NET MVC.
I want to Logout? So I researched and found the following
The code is based on decompiling the Microsoft.TeamFoundation.WebAccess which has the "Sign in as a different User" function.
public ActionResult LogOut()
{
HttpCookie cookie = Request.Cookies["TSWA-Last-User"];
if(User.Identity.IsAuthenticated == false || cookie == null || StringComparer.OrdinalIgnoreCase.Equals(User.Identity.Name, cookie.Value))
{
string name = string.Empty;
if(Request.IsAuthenticated)
{
name = User.Identity.Name;
}
cookie = new HttpCookie("TSWA-Last-User", name);
Response.Cookies.Set(cookie);
Response.AppendHeader("Connection", "close");
Response.StatusCode = 0x191;
Response.Clear();
//should probably do a redirect here to the unauthorized/failed login page
//if you know how to do this, please tap it on the comments below
Response.Write("Unauthorized. Reload the page to try again...");
Response.End();
return RedirectToAction("Index");
}
cookie = new HttpCookie("TSWA-Last-User", string.Empty)
{
Expires = DateTime.Now.AddYears(-5)
};
Response.Cookies.Set(cookie);
return RedirectToAction("Index");
}
Is the above code reliable?
ANd how to redirect to another page like logout succesful
after response.clear??

How do I handle invalid asp MVC routes

I have a number of MVC views that only make sense in the context of a workflow. E.g. user submits information on another page and is then redirected to a page which only display "success"..
Since the redirect is a GET, there is no way to stop users manually navigating to the page by adjusting their URL.
What should I do in this situation? Redirect to an error page, show a blank page?
In my opinion sucess information views should not have routes, as they are not intended to be served from a browser url. in our projects we usually return the success view directly from an post action.for example,
[HttpPost]
public ActionResult ChangePassword(ChangePasswordModel model)
{
if (ModelState.IsValid)
{
bool changePasswordSucceeded;
try
{
MembershipUser currentUser = Membership.GetUser(User.Identity.Name, userIsOnline: true);
changePasswordSucceeded = currentUser.ChangePassword(model.OldPassword, model.NewPassword);
}
catch (Exception)
{
changePasswordSucceeded = false;
}
if (changePasswordSucceeded)
{
var infoModel = new AnyInfoModel();
return View("ChangePasswordSuccess", infoModel); // This is not redirected, but success shown in the current route url.
}
else
{
ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
}
}
return View(model);
}
But this has a drawback also, if an user accidentally hit he F5 button the browser, it will try to repost the form.

MVC 3 Authentication / Authorization: Roles missing

We use MVC 3. The default user management is not usable for us as our account info is stored in our own data-store and access goes via our own repository classes.
I'm trying to assign a principal add roles to the HttpContext.User and give out an authorization cookie.
Based on a code snipped I found I tried something like this:
if (UserIsOk(name, password))
{
HttpContext.User =
new GenericPrincipal(
new GenericIdentity(name, "Forms"),
new string[] { "Admin" }
);
FormsAuthentication.SetAuthCookie(name, false);
return Redirect(returnUrl);
}
When the next request is done, the user is authenticated, but he is not in the "Admin" role.
What am I missing?
I think you should implement FormsAuthenticationTicket.
More info here : http://msdn.microsoft.com/en-us/library/aa289844(v=vs.71).aspx
In Mvc it is quite similar.
I have a class called UserSession that is injected into LoginController and that I use in LogOn action :
[HttpPost, ValidateAntiForgeryToken]
public ActionResult Index(LoginInput loginInput, string returnUrl)
{
if (ModelState.IsValid)
{
return (ActionResult)_userSession.LogIn(userToLog, loginInput.RememberMe, CheckForLocalUrl(returnUrl), "~/Home");
}
}
Here's my UserSession LogIn implementation (notice I put the "Admin" role hard coded for the example, but you could pass it as argument) :
public object LogIn(User user, bool isPersistent, string returnUrl, string redirectDefault)
{
var authTicket = new FormsAuthenticationTicket(1, user.Username, DateTime.Now, DateTime.Now.AddYears(1), isPersistent, "Admin", FormsAuthentication.FormsCookiePath);
string hash = FormsAuthentication.Encrypt(authTicket);
var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
if (authTicket.IsPersistent) authCookie.Expires = authTicket.Expiration;
HttpContext.Current.Response.Cookies.Add(authCookie);
if (!String.IsNullOrEmpty(returnUrl))
return new RedirectResult(HttpContext.Current.Server.UrlDecode(returnUrl));
return new RedirectResult(redirectDefault);
}
Then in the base controller I've overriden OnAuthorization method to get the cookie :
if (filterContext.HttpContext.Current.User != null)
{
if (filterContext.HttpContext.Current.User.Identity.IsAuthenticated)
{
if( filterContext.HttpContext.Current.User.Identity is FormsIdentity )
{
FormsIdentity id = filterContext.HttpContext.Current.User.Identity as FormsIdentity;
FormsAuthenticationTicket ticket = id.Ticket;
string roles = ticket.UserData;
filterContext.HttpContext.Current.User = new GenericPrincipal(id, roles);
}
}
}
I hope this helps. Let me know.
You sure, that roles are enabled, and there is such role?
If not, do following:
In Visual Studio:
Project -> ASP.NET Configuration
Then choose Security, enable roles. Create role "Admin".
Then try your approach

Resources