What should I do if someone tries to access page which is only allowed after being logged in to users. I have done this but it doesn't work, please help:
public ActionResult ViewMyAtdRecord()
{
int EmplID = Convert.ToInt32(Session["Employee"]);
if (Session["Employee"] == "")
{
ViewBag.Message = "NOT AUTHORIZED TO VIEW THIS PAGE";
return View();
}
else
{
IEnumerable<GetAtdRecord_SpResult> MyAtdRecord = DataContext.GetAtdRecord_Sp(EmplID).ToList();
var names = (from n in DataContext.HrEmployees select n).Distinct();
return View(MyAtdRecord);
}
}
Actually session begins here.
public ActionResult AfterLogIn(int EmplID, String EmpPwd)
{
int Num_Rows = (int)DataContext.GetUser_Pwd(EmplID, EmpPwd).First().No_Rows;
if (Num_Rows == 1)
{
Session["Employee"] = EmplID.ToString() ;
ViewBag.Message = Session["Employee"];
}
else
{
ViewBag.Message = "Log-in Failed";
}
return View();
}
First, avoid using session for storing authentication evidence. It makes you vulnerable to session fixation - someone can easily copy and reuse the contents of the ASP.NET_SessionId cookie, particularly if the site is accessible over HTTP and not HTTPS.
Use authentication cookies instead. Yes, cookies have some disadvantages, such as giving malicious users the ciphertext of your authentication cookie. However the FormsAuthenticationProvider has been developed with this in mind. This is why it is generally considered safer to use cookies.
Second, try to avoid using session at all. One of the huge advantages of ASP.MVC is the ability to run sessionless, allowing you to easily scale up your site if needed.
I would recommend using FormsAuthentication (as suggested by #akton) and decorate the actions/controller with the Authorize attribute
If you want to go with Session rather than FormsAuthentication then you could try this out :
public ActionResult ViewMyAtdRecord()
{
int empId = 0;
int.TryParse((string)Session["Employee"], out empId); // parse variable to int
if (empId > 0) // we have an employee id, lets show that record.
{
IEnumerable<GetAtdRecord_SpResult> MyAtdRecord = DataContext.GetAtdRecord_Sp(empId ).ToList();
var names = (from n in DataContext.HrEmployees select n).Distinct();
return View(MyAtdRecord);
}
else // we do not have an employee id, show not authorized message.
{
ViewBag.Message = "NOT AUTHORIZED TO VIEW THIS PAGE";
return View();
}
}
Related
I'm trying to pass TempData through a couple actions, but I can't get it to persist beyond one pass. I've read a ton of questions on StackOverflow about this, but I just can't get their solutions to work. I know TempData only persists for one redirect, but it is suggested that .Keep() or .Peek() should allow it to persist on another redirect. That unfortunately has not worked for me. I have also tried reassigning TempData and straight hard-coding of TempData from the second redirect and it still will not pass through. I'm obviously missing something. My code:
//First redirect
public ActionResult Index(int? userId, int? reportingYear)
{
if (Session["State"] == null)
{
TempData["Timeout"] = "Your session has timed out. Please login to continue.";
return RedirectToAction("LogOff", "Account");
}
}
//Second redirect
[AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult LogOff()
{
//Delete the application cookie and clear session variables
var cookies = Request.Cookies;
List<string> tempCookies = new List<string>();
foreach (string cookie in cookies)
{
if (cookie.ToString() != "quailCoord")
{
tempCookies.Add(cookie);
};
}
foreach (string cookie in tempCookies)
{
HttpCookie deleteCookie = Request.Cookies[cookie];
deleteCookie.Expires = DateTime.Now.AddDays(-1);
Response.Cookies.Add(deleteCookie);
}
Session.Abandon();
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
//When checking that the key exists, it does and enters the if statement to keep the data
if (TempData.ContainsKey("Timeout")
{
TempData.Keep("Timeout");
}
return RedirectToAction("Login");
}
//Third action
public ActionResult Login(string returnUrl)
{
ViewBag.ReturnUrl = returnUrl;
//It does not find any TempData keys
if (TempData.ContainsKey("Timeout"))
{
ViewBag.Timeout = TempData["Timeout"] as string;
}
return View();
}
I have also attempted these in place of the TempData.Keep("Timeout") method:
TempData.Peek("Timeout")
TempData["Timeout"] = TempData["Timeout"]
TempData["Timeout"] = "Your session has timed out. Please login to continue."
None of these methods pass to the Login() action. TempData is always empty upon entering that action. When debugging, the minute I step over the return RedirectToAction("Login") line, the count in TempData turns to 0. What am I missing? Is deleting the cookies a problem?
Because TempData will store data in Session object which might store SessionId in cookie, if you delete that server will create another SessionId (object) for you instead of the original one.
so that if you want to keep TempData to multiple actions we might need to keep SessionId value from the cookie.
From your code, we can try to add
a judgement to check cookie key whether if yes don't delete the cookie.
foreach (string cookie in cookies)
{
if (cookie.ToString() != "quailCoord" && cookie.ToString() != "ASP.NET_SessionId")
{
tempCookies.Add(cookie);
};
}
Hello I have online course website. I have authorizecontroller for admin area and you can access there by typing www.name.com/area then you log in and go to the admin area. I also need students to log in here but they should go to different link like wwww.name.com./LoginStudent. So the students will come from the page www.name.com/Course/Detail and in the detail page button leads him/her to log in controller in admin area. So I want to check if user came from www.name.com/Course/Detail I want redirect him/her to wwww.name.com./LoginStudent how can I control where did he come from ?
here is my log in controller ;
public ActionResult Login(string returnUrl, LoginModel input)
{
if (!ModelState.IsValid)
{
ShowErrorMessage("Hatalı Giriş Yaptınız.");
return View(input);
}
var yonetici = Db.Members.FirstOrDefault(p => p.Mail == input.EMail && p.Active == true && p.Authority == Authority.Admin);
if (yonetici == null)
{
ShowErrorMessage("Hatalı E-Posta adresi.");
ModelState.AddModelError("EMail", " ");
return View(input);
}
if (yonetici.ValidatePassword(input.Sifre) == false)
{
ShowErrorMessage("Hatalı şifre");
ModelState.AddModelError("Sifre", " ");
return View(input);
}
I dont want to send login page by pressing button because I'm using [Authorize] so it checks if loged in before or not
well I did this to make it easy but how to make it work on page load
var itemUrl = Request.Url.ToString();
if (itemUrl.Contains("Participant"))
{
ShowErrorMessage("Hatalı Giriş Yaptınız.");
return View(input);
}
You can find the previous page (referrer) using HttpContext.Current.Request.UrlReferrer.ToString();
Then show appropriate login screen.
You will need to save this kind of the information somewhere, maybe on a database? If so, you use a column at the database to save the Source Redirect, so You can query and measure on the future. You can pass it before redirect.
How can I redirect a user from one Asp.net Mvc site to another Asp.net MVC site and automatically log them in?
The situation is that we will have some customers that need to go to one site and some that will need to go to the other. I've been asked to make it so that when customers are redirected to the correct site that they are also auto logged in to the site they are redirected to.
Assuming you don't want to integrate existing single sign-on solution and that you are using forms authentication for both sites and those sites are not on the same domain. The forms authentication in MVC is done via cookie. So the task is when you're logged in to Site1 to create authentication cookie on Site2.
Usually you craft a request to Site2 like:
/Impersonate/Start?encryptedToken=some_encrypted_stuff
And Site2 handling it like:
[DataContract]
public class Token
{
[DataMember(Name = "u")]
public string UserName { get; set; }
[DataMember(Name = "t")]
public DateTime TimeStamp { get; set; }
[DataMember(Name = "m")]
public string Magic { get; set; }
public Token()
{
Magic = MAGIC;
TimeStamp = DateTime.Now;
}
public const string MAGIC = "SOME_RANDOM_STRING";
}
public class ImpersonateController : Controller
{
[HttpGet]
public ActionResult Start(string encryptedToken)
{
// symmetric encryption - hopefully you know how to do it :)
string decryptedToken = Decrypt(encryptedToken);
var serializer = new DataContractJsonSerializer(typeof(Token));
Token token;
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(decryptedToken)))
{
token = serializer.ReadObject(stream);
}
if (!string.Equals(token.Magic, Token.MAGIC) ||
(DateTime.Now - token.TimeStap).TotalMinutes > 1))
{
// magic doesn't match or timestamp is too old
throw new Exception("Invalid token.");
}
FormsAuthentication.SetAuthCookie(token.UserName, true);
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
}
Maybe needless to say /Impersonate/Start should be under https.
As for crafting the request - you can put it directly into view & make request via json.
In Site1:
public class LoginController : Controller
{
public ActionResult Login(string userName, string password)
{
// ... validate user logs to site 1 etc
var site2UserName = userName;
var token = new Token { UserName = site2UserName };
var serializer = new DataContractJsonSerializer(typeof(Token));
string decryptedToken;
using (var stream = new MemoryStream())
{
serializer.WriteObject(stream, token);
decryptedToken = Encoding.UTF8.GetString(stream.ToArray());
}
// symmetrical encryption
return new View(new LoginMode { Token = HttpUtility.UrlEncode(Encrypt(decryptedToken)) });
}
}
View (assuming you have jQuery)
$(function() {
$.get("https://site2.com/Impersonate/Start?token=#Html.Raw(Model.Token)");
});
So right after you log-in to Site1 you serve view that uses AJAX to send request to Site2 that will authenticate user also there. It is usually better idea to do it on request - the form authentication cookie for Site2 will eventually expire. So I'd favor something like like this on Site1:
Continue to site 2
And
[HttpGet]
[Authorize]
public ActionResult StartImpersonation()
{
// this is essentially similar to Login action
string encryptedToken = "";
string redirectUrl = string.Format(CultureInfo.InvariantCulture,
"https://site2.com/Impersonate/Start?encryptedToken={0}",
HttpUtility.UrlEncode(encryptedToken));
return Redirect(redirectUrl);
}
Which is better because a) cookie on Site2 can't expire b) if there is an error in impersonation user will see why (if there is an error in AJAX impersonation you can show some error to user, but it will look weird - authentication to site 2 haven't succeeded - why they're trying to authenticate me there ? :).
You want a single-sign-on (SSO) solution. This may be done any number of ways. OpenID is popular: https://en.wikipedia.org/wiki/OpenID This goes into plenty of details on a slightly older approach: http://www.codeproject.com/Articles/114484/Single-Sign-On-SSO-for-cross-domain-ASP-NET-appl Even more stuff here: C# ASP.NET Single Sign-On Implementation
HTH
On the link that would take someone from one site to the other, here's some of what you could put in the JS in a few places that may do what you want:
On clicking the link, a $.get is done to grab the HTML of the log-in page.
Then put into JS variables the login and password of the user for the second site's security into that HTML.
Post the data through a $.ajax request so that the person is logged in through the JS behind the scenes.
Now, either redirect in the current window or open a new window with the other site's home page and voila they are signed in without having to do any extra lifting if their own.
Note that some of this could be done earlier if you want to make the transition easier as when the page with the link loads, this could be done in the JS when the document is ready. The key point here is to have the cookies required for the authentication on the second site done without the user having to do any extra clicks.
when I was writing ASP.NET applications I used the Forms Authentication with my custom login page, like so:
Once login is a success I checked him as authenticated:
FormsAuthentication.RedirectFromLoginPage(userId.ToString(), true);
In order to check if a user is logged in, I had a class that inherited from a base page and all pages inherited from it, which contained a method that returned a bool after checking if the user is authenticated, with the following command:
return HttpContext.Current.User.Identity.IsAuthenticated;
Now, I'm doing an ASP.NET MVC application, and was wondering what is the best was to do that on MVC?
Thanks
ok MVC is very simple and similar
for your question you can use like .......
in your controller
public ActionResult LogOn()
{
return View();
}
//
// POST: /Account/LogOn
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
var userInfo = new UserInfo()
{
UserName = model.UserName,
Password = model.Password,
};
var service = new CSVService();
if(service.ValidateUser(userInfo))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return Redirect("~/");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
The best way to authenticate website / web-application is using the Membership which is provided by Microsoft built in for Easy-ness .
From this you can do following things(features)
it maintains Log-in status (you don't have to bother about Authentication).
It allows to provide Roles & Users and Assigning permission who can see which page
(Page Restriction)
It provides built-in Stored Procedures and UI tools like Log-in, Log-out,user,Password Recovery, Etc elements. & Highly secure (Hack-Proof)
for more info:
Walk through Membership (MSDN)
I have an asp.net mvc4 application, in which i have to logout from an account :
if (_fonction == "User")
{
if (_is_admin == true) return RedirectToAction("Index");
else
{
Session["user"] = _u;
return RedirectToAction("Index", "User");
}
}
in the controller User
public ActionResult Index()
{
if (Session["user"] == null) return RedirectToAction("Index", "Home");
return View(Session["user"]);
}
the action Logout
public ActionResult Logout()
{
if (_is_admin) { Session["user"] = null; return RedirectToRoute("Administration"); }
else { Session["user"] = null; return RedirectToAction("Index", "Home"); }
}
i do this : i log in to a user account then i disconnect so i'am in the home page , then i click into the back button of the browser i got the page of the account. When i refresh i returned to the home page. i think that the problem is in the cache and i don't think that make it null is a good idea .
So how can i fix this problem?
You can try to add [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] as an attribute to your User controller's Index action to force non-cached results.
But I would strongly suggest to just use AuthorizeAttribute because this will prevent unauthorized web requests done on a specific view. The benefit of using this is that you still give the users the liberty to cache your views and be secured at the same time.
if you do not want to clean your cache then below is the javascript which helps you to hard refresh your page on click of the browser back button
if (window.name != "") { // will be '' if page not prev loaded
window.name = ""; // reset to prevent infinite loop
window.location.reload(true);
}
window.name = new Date().getTime();
put the above "javascript" code on your page. so, it will hard refresh your page.