I have web application in Asp.Net MVC4 and I want to use cookie for user's login and logout. So my actions as follows:
Login Action
[HttpPost]
public ActionResult Login(string username, string pass)
{
if (ModelState.IsValid)
{
var newUser = _userRepository.GetUserByNameAndPassword(username, pass);
if (newUser != null)
{
var json = JsonConvert.SerializeObject(newUser);
var userCookie = new HttpCookie("user", json);
userCookie.Expires.AddDays(365);
HttpContext.Response.Cookies.Add(userCookie);
return RedirectToActionPermanent("Index");
}
}
return View("UserLog");
}
LogOut Action
public ActionResult UserOut()
{
if (Request.Cookies["user"] != null)
{
var user = new HttpCookie("user")
{
Expires = DateTime.Now.AddDays(-1),
Value = null
};
Response.Cookies.Add(user);
}
return RedirectToActionPermanent("UserLog");
}
And I use this cookie in _Loyout as follow:
#using EShop.Core
#using Newtonsoft.Json
#{
var userInCookie = Request.Cookies["user"];
}
...
#if (userInCookie != null && userInCookie.Value)
{
<li>Salam</li>
<li>Cıxış</li>
}
else
{
<li>Giriş</li>
}
But When I click *UserOut* action this action happen first time, but then it doesn't work. I put breakpoint for looking process but it get UserLog action doesn't UserOut.
My question is that where I use wrong way of cookie? What is a best way using cookie in Asp.Net Mvc4 for this scenario ?
Try using Response.SetCookie(), because Response.Cookies.Add() can cause multiple cookies to be added, whereas SetCookie will update an existing cookie.
We are using Response.SetCookie() for update the old one cookies and Response.Cookies.Add() are use to add the new cookies. Here below code CompanyId is update in old cookie[OldCookieName].
HttpCookie cookie = Request.Cookies["OldCookieName"];//Get the existing cookie by cookie name.
cookie.Values["CompanyID"] = Convert.ToString(CompanyId);
Response.SetCookie(cookie); //SetCookie() is used for update the cookie.
Response.Cookies.Add(cookie); //The Cookie.Add() used for Add the cookie.
userCookie.Expires.AddDays(365);
This line of code doesn't do anything. It is the equivalent of:
DateTime temp = userCookie.Expires.AddDays(365);
//do nothing with temp
You probably want
userCookie.Expires = DateTime.Now.AddDays(365);
Related
I'm currently working on the login system of my WebApp, which I'm developing in ASP.NET MVC. I am currently using the .NET Framework 4.8.x. Now I have developed the UI and my backend is running. This allows the user to log in and out without any problems. But my question now is whether my way of working is safe?
This is what my login function looks like:
Note: Currently, I am saving the password as it is for testing purpose but later i will change it as a hashed one with salt added to it.
String mycon = "my-connection-string";
SqlConnection scon = new SqlConnection(mycon);
String myquery = "select * from loginDetails where uName=#uName and paswrd=#paswrd";
scon.Open();
SqlCommand cmd = new SqlCommand(myquery, scon);
cmd.Parameters.AddWithValue("#uName", lc.userName);
cmd.Parameters.AddWithValue("#paswrd", lc.password);
SqlDataReader sdr = cmd.ExecuteReader();
if (sdr.Read())
{
Session["username"] = lc.userName.ToString();
return RedirectToAction("Index", "Home");
}
else
{
ViewData["Message"]= "Invalid Username or Password";
}
scon.Close();
return View(lc);
This is what my logout function looks like:
if (Session["username"] != null)
{
Session.Clear();
Session.RemoveAll();
Session.Abandon();
}
return View();
Do I have any mistakes here? It doesn't seem very safe to me if only the username is checked by the server. Wouldn't it be safer if I used a SessionID and it expired after 24 hours for example? Unfortunately I don't know how to do that. I know how the automatic logout works via session-timeout. But I think the SessionIDManager would help me a lot. However, I don't use an entity framework and therefore I can't give the class SessionIDManager a context instance.
To authorize the user I use a filter. It looks like this:
public class Authorize : System.Web.Mvc.ActionFilterAttribute, System.Web.Mvc.IActionFilter
{
public override void OnActionExecuting(System.Web.Mvc.ActionExecutingContext filterContext)
{
if (HttpContext.Current.Session["username"] == null)
{
filterContext.Result = new System.Web.Mvc.RedirectToRouteResult(new System.Web.Routing.RouteValueDictionary
{
{ "Controller", "Login"},
{ "Action", "Index"},
});
}
base.OnActionExecuting(filterContext);
}
}
Does anyone have an improvement suggestion for me?
Is it safe to use the session variable for authorization?
You can use login with model (secure method) ;
public ActionResult Login(string username, string password)
{
// LoginDetails -> Your Model Name && db -> Your Database Context Name
LoginDetails loginDetails = db.LoginDetails.Where(item => item.username == username && item.password == password).FirstOrDefault();
if(loginDetails == null)
// Login Failed
else
// Login Successful
}
the idea is to create session and store it as a row in the database upon login, the session is created and get an id every time a login occurs, however updating the session with the user information does not work for now. I might be missing some tiny detail. I'm new to MVC in general and never implemented session befor, I took over this application and need to work further on it.
Code of the login page is strait forward nothing fancy other than there are two login ActionResults [Get] and [Post] one for creating the session(working) and the other suppose to update the session with the status and user information (not working!). Controller code looks like below:
[HttpGet]
public ActionResult Login()
{
SessionAid aid = new SessionAid();
var mysession = aid.CreateSession();
if (mysession.SessionID != 0)
{
Session["mySessionId"] = mysession.SessionID;
return View();
}
else
{
return Redirect("~/error");
}
}
[HttpPost]
public ActionResult Login(Login model)
{
string username = model.username;
string password = model.password;
if (ModelState.IsValid)
{
var session= new SessionData();
Session["SessionUserID"] = model.username;
Session["LastActiveTime"] = DateTime.UtcNow;
Session["CookiesId"] = sessionData.CookieID;
if (username == "name" && password == "password")
{
return RedirectToAction("Index", "Home");
}
return View();
}
then there is the session controller where the update Session table with userId and cookieId method is implemented
public ActionResult SaveSession(SaveRequest saveRequest)
{
var respon = new SessionResponse();
response.Session = new SessionData
{
SessionID = updatedSession.SessionID,
CookieID = updatedSession.CookieID,
SessionUserID = updatedSession.SessionUserID,
};
response.Success = true;
}
return response;
}
My question is how do I read the sessionId that is created in [HTTPGet] login method in the [HttpPost] login method, so I can update the session row in the database with cookieId and userID? What am I missing?
from what I understand, you can use the Session object you are storing the SessionID at.
ex:
int SessionId = Session["mySessionId"] as int;
this way you can get any thing you've stored in the Session object anywhere you want.
I have a .NET MVC5 website, where the user is logged in using Microsoft Identity. I have multiple form posts for adding and editing items across the site. I'm looking to know which order I should perform validation in:-
ModelState.IsValid and then User.Identity.IsAuthenticated
User.Identity.IsAuthenticated then ModelState.IsValid
I currently have the following code which works, but it seem to be a case of 'the chicken and egg':-
var user = UserAccountFunctions.GetUser(User);
if (user != null)
{
ClientProfile profile = ClientProfile.GetUser(user.Id, db);
if (profile != null)
{
if (ModelState.IsValid)
{
// Do logic here
}
}
}
Should I swap this code round to check the model first, before checking authentication so that I have:-
if (ModelState.IsValid)
{
var user = UserAccountFunctions.GetUser(User);
if (user != null)
{
ClientProfile profile = ClientProfile.GetUser(user.Id, db);
if (profile != null)
{
// Do logic here...
}
}
}
Or is there simply no difference here? I repeat this code a lot throughout the site, so looking for which is the better option? I currently use the top one, because I feel that you shouldn't even attempt to check the model unless they are authenticated?
Any advice here?
Thanks!
Here is example of updating users's email:
[AcceptVerbs(HttpVerbs.Post)]
[Authorize]
[ValidateAntiForgeryToken()]
public ActionResult emailupdate(UserEmailEditModel editmodel_post)
{
if (!ModelState.IsValid)
{
// redirect to email view and show errors
}
// check if posted id is the same as stored in session
if (User.Identity.GetUserId() != editmodel_post.user_id.ToString())
{
// redirect to email view and show errors
}
}
So
Use Authorize attribute
Use ValidateAntiForgeryToken attribute
Check ModelState
Check against session or database
I wanted to implement this solution to handle antiforgery in ajax requests. I know there are other solutions but this is the one I like most.
The problem is I have to deal with System.Web.Webpages 1.0 so I cannot make use of AntiForgeryConfig.CookieName in my code.
public override void OnAuthorization(AuthorizationContext filterContext)
{
var request = filterContext.HttpContext.Request;
// Only validate POSTs
if (request.HttpMethod == WebRequestMethods.Http.Post)
{
// Ajax POSTs and normal form posts have to be treated differently when it comes
// to validating the AntiForgeryToken
if (request.IsAjaxRequest())
{
string cookieName = AntiForgeryData.GetAntiForgeryTokenName(context.Request.ApplicationPath);
var antiForgeryCookie = request.Cookies[AntiForgeryConfig.CookieName];
var cookieValue = antiForgeryCookie != null
? antiForgeryCookie.Value
: null;
AntiForgery.Validate(cookieValue, request.Headers["__RequestVerificationToken"]);
}
else
{
new ValidateAntiForgeryTokenAttribute()
.OnAuthorization(filterContext);
}
}
}
How can I retrieve (programmatically) the cookie name set by the antiforgery system in Mvc3? I suspect the AntiForgery.Validate part will also be a problem but I'll handle that before. Any thoughts?
The actual cookie name always starts from "__RequestVerificationToken" with some suffix. So you can find the cookie like this:
private static string FindCookieValueByName(HttpRequestBase request)
{
return request.Cookies
.Cast<string>()
.Where(cn => cn.StartsWith("__RequestVerificationToken", StringComparison.OrdinalIgnoreCase))
.Select(cn => request.Cookies[cn].Value)
.FirstOrDefault();
}
I have a javascript function that updates a cookie in the following manner:
aspx page:
function setCookie()
{
//...
document.cookie = "myCookie = HelloWorld";
//...
}
After an asp control triggers an event, the entire page gets sent back from the client. I want to be able to read the value of my cookie. How do I do that?
I've tried:
string temp = Request.ServerVariables["myCookie"].ToString(); but that is the wrong way to do it.
How do I read the client cookie on the server
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);
Source MSDN
Here is the helper method to retrieve cookie at server side.
public static String GetCookie(String cookieName)
{
try
{
if (HttpContext.Current.Request.Cookies[cookieName] == null)
return String.Empty;
return HttpContext.Current.Request.Cookies[cookieName].Value;
}
catch
{
return String.Empty;
}
}
Usage
var result = GetCookie("myCookie");
If you want to set cookie at client side, look at this Cookie plugin.