sfDoctrineGuardPluggin rehashes the password from fixture after data-dump - symfony1

I have s symfony 1.4 with Doctrine and sfDoctrineGuardPlugin.
I am experiencing a problem with loading fixtures for sfGuardUser which are made from symfony doctrine:data-dump
The core of the problem is that the passwords in the fixture file are not encrypted and they will be encrypted in the process of fixture loading.
In the other hand - when we dump data from the data base, the passwords are already encrypted and if we try to load them again, the value of the password will be rehashed for the second time.
Does anybody know how to avoid this situation?
I am using this process to prevent data loss when the model needs to be changed. If anybody knows other solution for this particular problem, I will appreciate!

There's a solution to this in the old symfony forum.
In short: create a setEncryptedPassword function in your user model like this:
public function setEncryptedPassword($v)
{
if ($v !== null) {
$v = (string) $v;
}
if ($this->password !== $v) {
parent::_set('password', $v);
}
return $this;
}
And in your dump change all password occurences to encrypted_password.

Related

Keeping User Information in Session in MVC is not Secure

I had a Posting on a blog about Sessions AND Cookies. Here are details
Sessions
Sessions are More Secure
Sessions are on the server
Cookies
Cookies are On client side
Less Secure
Once it is disable on browser the difficult to use.
On the basis of above argument i used sessions in Login system to keep UserId,UserName & roleName
Now on the the basis of roleName i will decide either this is Admin to enter to administrator section or not.
I have used this Code in Model in MVC
public bool LoginMe()
{
Int64 Error;
//create db
Database db = DatabaseFactory.CreateDatabase("DBContext");
DbCommand dbCommand = db.GetStoredProcCommand("ValidateUser");
db.AddInParameter(dbCommand, "#Username", DbType.String, this.UserName);
db.AddInParameter(dbCommand, "#Password", DbType.String, EncryptPassword(this.Password));
db.AddOutParameter(dbCommand, "#Error", DbType.Int64, 10);
DataSet dsResult = db.ExecuteDataSet(dbCommand);
Error = Convert.ToInt64(db.GetParameterValue(dbCommand, "#Error"));
if (Error == 1100)
{
try
{
var query = (from o in dsResult.Tables[0].AsEnumerable()
select new AllUser
{
UserId = o.Field<int>("UserId"),
UserName = o.Field<string>("UserName"),
roleName = o.Field<string>("roleName"),
}).Single(); // this will raise an exception if there isn't just one record returned
Session["UserId"] = query.UserId;
Session["UserName"] = query.UserName;
Session["roleName"] = query.roleName;
return true;
}
catch {
// do nothing and let method return false as something has gone wrong.
// add logging here if you are using it to show there has been a problem
}
}
return false;
}
I used it in View like #Session["UserId"]
Now an expert comment on this like
If you aren't using https and securing the session cookie then this might make it easy to hack your site, although that's the same for any session based site (nearly all of them)
It might be nice to add some check so that if you remove a user's rights, the session variables are deleted the next time that user requests something from the server,
otherwise they could carry on using the site even though their account it banned.You'd have to decide if this is likely and then how you want to do this (using an authorization filter maybe.)
Above comments confused me.Can any body make it clear?What is the best way to keep these information?
Session state uses client tickets to identify the server-side session, it may be susceptible to session ID spoofing and injection attacks.
So, to hack session values one would require hacking the remote-server.
And yes, for highly secure application(such as online banking) use https.
http://msdn.microsoft.com/en-us/magazine/cc163730.aspx#S9
Secure sockets layer (SSL) should be used to prevent network-level sniffing of session IDs, authentication tickets, application cookies, and other request/response information.
Can session value be hacked?
Use HTTPS if you application handles sensitive information(credit-card number,account num,passwords).
Store the User object (model with userId,username,role) in the session than separate attributes
Set setHttpOnly attribute for SESSION_ID.
It might be costly to refresh the User object stored in session before invoking every operation to reflect the current rights stored in database.

How to check whether username already exists using ajax in asp.net?

I am working on an application which has a registration form and I have to display to the user whether the username exists or not.
I am using asp.net mvc3 and planned to use AJAX to achieve this.
I have a form
<tr>
<td>User Name*</td>
<td><input id="UserName" name="UserName" type="text" onblur="check(this.value);"/></td>
<td id= "UName"></td>
</tr>
which calls a .js file that has the folling contents
function check(User) {
...
var url = "/UserNameCheck/Index";
url += "?User=" + User;
xmlHttp.onreadystatechange = state_Change;
xmlHttp.open("GET", url, true);
xmlHttp.send(null);
}
function state_Change() {
if (xmlhttp.readyState == 4) {// 4 = "Response loaded"
if (xmlhttp.status == 200) {// 200 = Response Error Free
document.getElementById("UName").innerHTML = xmlHttp.responseText
}
else {
alert("Problem retrieving XML data");
}
}
}
I alerted the username and I am getting the correct value that i had entered. Now, the URL is /UserNameCheck/Index where UserNameCheck is a controller and Index is a method in that.
The controller has this code.
public ActionResult Index(string User)
{
string UserName;
try
{
Response.Cache.SetCacheability(HttpCacheability.NoCache);
UserName = Request.QueryString["User"];
ConnectionPackage.ConnectionClass cc = new ConnectionPackage.ConnectionClass();
conn = cc.con;
string sql = "Select UserName FROM UserDetails where UserName = '" + UserName + "'";
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
cmd.CommandType = CommandType.Text;
object p = cmd.ExecuteScalar();
cmd.ExecuteNonQuery();
string u = (string)p;
if (u.Length==0 || u.Equals("NULL") || u.Equals("null")||u.Equals("Null"))
{
return View();
}
return null;
}
catch (Exception ex){
}
and the view has
String buffer = " <table><tr><td id = 'UName' >" This user name already exists. Please select some other unser name.
buffer = buffer + "</td></tr></table>";
response.getWriter().println(buffer);
I also tried writing
Response.Clear();
Response.Write("UserName already exists. Please select another UserName");
Response.End();
instead of returning View.
But in both the cases, I didn't get any message that the username exists even though I typed a user name that was already present in the database.
The connection string work for inserting into the database, so I dont think there is a problem with that. Is there a problem with the URL that I have mentioned in the js file? Or is my entire approach wrong?
I am basically from java background so dont know much about asp.net. Please do help.
Thank you very much in advance.
I followed what was given in MSDN article How to: Implement Remote Validation in ASP.NET MVC
jQuery in Action is the most popular jQuery book
You're doing alright but you could make this a whole lot easier on yourself. If you are usinng MVC3 with Razor, your app already has jQuery installed.
Use the $.ajax() method to perform the calls to your controller action that checks names...
Bind the $.ajax() call "unobtrusively" which means instead of on your HTML control, bind the event to your control from the jquery/javascript.
Second, if you want a little fancy performance, you can bind it via the live() jquery function or keyup event, so that as you are typing the ajax call is made and you find out realtime.
Ultimately you will end up with a lot less javascript, and your JS stuff will be cleanly separated from your markup.
As far as your controller action is going, it looks fine for playing around and learning, but you'd want to think about either (a) putting your SQL statement as a stored procedure on the db server and calling that, or (b) writing a repository pattern class and then using LINQ to do your query work after the DB fetch.
Another possibility would be to use Entity Framework 4.1 via NuGet to eliminate both needs. It can have a bit of a learning curve, but there's lots of good stuff out there and your example would be fairly simple to get started with.
Let me know if you have any specific concerns with your code and I can provide a more detailed answer.

MVC.net session gets mixed between users

I am storing user objects in session, pulling them out in the controllers, and sometimes write some data into them. but when to users post at the same time, the sessions get mixed fro some reason.
Does anyone have any idea how that is possible ?
typical post:
[HttpPost]
public ActionResult Index(QuestionModel model, FormCollection collection)
{
var person = ((Person)Session["Person"]);
if (!ModelState.IsValid)
{
ModelState.Clear();
ModelState.AddModelError("", Global.Global.error);
return View(new QuestionModel(person.page, (CultureInfo)Session["culture"]));
}
person.page = model.Page;
while (person.Answers.Count > model.Page - 1)
{
person.Answers.RemoveAt(person.Answers.Count - 1);
}
var answer = new Answer() { answer = model.ChosenAnswer, Question = "Q" + person.page };
person.Answers.Add(answer);
if (!CheckForNextPage(person.page)) { person.hasFinishedQuestions = true; return RedirectToRoute("Result"); }
person.page++;
return View(new QuestionModel(person.page, (CultureInfo)Session["culture"]));
}
I echo the session id on every page, and when a couple of users are using the website they get each others session + sessionid ...
#update: 3 experienced developers have been looking for the problem for 2 days, still no solution. already removed about 95% off the code, still same issue. server posts back responses from another session
This is not possible.
So this is my guess:
You are testing this wrongly, you are using different tabs from the same browser.
Some people don't know that this doesn't create a different session.
Try testing this on 2 different browsers (i.e. firefox and chrome) as they will not share the session (as the session id is normally stored in a cookie).
Please report back if this was the case.
We "solved" it. We didn't actually solve it, but we copied all the sources to a new project, recompiled, and everything worked. Untill this day, we still don't know why, and how that error happened ...

symfony sfGuardUser hasCrendential live after update

I'm using symfony 1.4 and the sfGuardDoctrinePlugin, I've got it installed and setup fine but I have the following problem:
If I login as an admin and update the permissions for a user, that user must logout then login again before having the newly added credential/permission.
Is there a way around this?
I'm not sure how easy this would be to fix. When a user logs in I think their credentials are added to their session attributes there and then. So when the admin updates their credentials their session still holds the old credentials. This means any call to hasCredential isn't "live".
Thanks
This would add extra queries to each and every request to your application. You could force update of the credentials by $user->getSfGuardUser()->refresh(true), which would reload the entity and all its relations (and thus its permissions).
Thanks for your answer, I've modified the processForm function of the sfGuardUser module's actions class.
If I login and change my own permissions, the session is updated there and then.
My problem is that if I edit the user permissions of another user, I would need to edit their session data. To solve this I enabled database sessions, so I now have sessions saving there instead of to file. So my next problem is how to isolate the session for the other user.
The sessions database has the following columns: sess_id, sess_data, sess_time.
sess_data is serialized and that is what I would need to update.
But I think symfony updates the session ids quite often and it would be hard to always isolate the correct session for the other user.
I think that it would also be slow to try and unserialize, check user_id then reserialize the data. I would need a user_id column I think.
I know this is an old question, but I recently had this same problem and it took me way longer than it should have to find the answer (which was posted in Symfony's code snippet section). Paste this function in your myUser class and all problems go away:
/**
* Overridden method that actually reads the permission from DB
* instead of relying on data present when the user logs in.
*
* #param string permission name
*
* #return boolean true if the user has credential
*/
public function hasCredential($permission_name)
{
if (!$this->isAuthenticated()) {
return false;
}
$gu = $this->getGuardUser();
$groups = $gu->getGroups();
$permissions = $gu->getPermissions();
$permission_names = array();
foreach($permissions as $permission) {
$permission_names[] = $permission->getName();
}
foreach($groups as $group) {
$group_permissions = $group->getPermissions();
foreach($group_permissions as $group_permission) {
$permission_names = array_merge($permission_names, array($group_permission->getName()));
}
}
$permission_names = array_unique($permission_names);
return (in_array($permission_name, $permission_names)) ? true : false;
}

Where to store logged user information on ASP.NET MVC using Forms Authentication?

I'm using ASP.NET MVC and Forms Authentication on my application. Basically I use FormsAuthentication.SetAuthCookie to login and FormsAuthentication.SignOut to logout.
In the HttpContext.Current.User.Identity I have stored the user name but I need more info about the logged user. I don't want to store my entire User obj in the Session because it might be big and with much more infomation than I need.
Do you think it's a good idea to create like a class called LoggedUserInfo with only the attributes I need and then add it to the Session variable? Is this a good approach?
Or do you have better ideas?
I use this solution:
ASP.NET 2.0 Forms authentication - Keeping it customized yet simple
To summarize: I created my own IPrincipal implementation. It is stored in HttpContext.Current.Cache. If it is somehow lost, I have username from client side authorization cookie and can rebuild it. This solution doesn't rely on Session, which can be easily lost.
EDIT
If you want to use your principal in your controller and make it testable, you can do this:
private MyPrincipal _myPrincipal;
MyPrincipal MyPrincipal
{
get
{
if (_myPrincipal == null)
return (MyPrincipal)User;
return _myPrincipal;
}
set
{
_myPrincipal = value;
}
}
In your test, you will set object prepared for testing. Otherwise it will be taken from HttpContext. And now I started thinking, why do I use Ninject to do it?
Store it server side in the session.
Eg.
// Make this as light as possible and store only what you need
public class UserCedentials
{
public string Username { get; set; }
public string SomeOtherInfo { get; set; }
// etc...
}
Then when they sign in just do the following to save the users info:
// Should make typesafe accessors for your session objects but you will
// get the point from this example
Session["UserCredentials"] = new UserCredentials()
{ Username = "SomeUserName", SomeOtherInfo = "SomeMoreData" };
Then whenever you need it fetch it:
UserCredentials user = (UserCredentials)(Session["UserCredentials"]);
I have written a couple of question/answers regarding doing custom authorization in MVC:
How to implement authorization checks in ASP.NET MVC based on Session data?
How does the Authorize tag work? - Asp.net Mvc
I actually like to use a CustomPrincipal and CustomIdentity which I set in the logon action method like
if (!String.IsNullOrEmpty(username) && !String.IsNullOrEmpty(password) && _authService.IsValidLogin(username, password))
{
User objUser = _userService.GetUserByName(username);
if (objUser != null)
{
//** Construct the userdata string
string userData = objUser.RoleName + "|" + objUser.DistrictID + "|" + objUser.DistrictName + "|" + objUser.ID + "|" + objUser.DisplayName;
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(username, rememberMe.GetValueOrDefault());
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);
return RedirectToAction("Index", "Absence");
}
else
{
return RedirectToAction("LogOn", "Account");
}
}
else
{
return RedirectToAction("LogOn", "Account");
}
Then in the custom principal you can have methods that access specific information you passed in to the constructor like
((CustomIdentity)((CustomPrincipal)HttpContext.Current.User).Identity).DisplayName;
where the DisplayName property is declared in the CustomIdentity class.
Well you will have to store these somewhere. Two main possible places though:
The server
You can either put them into Session. I suggest you do create a separate class that will hold only data that you actually need to avoid of wasting too much memory. Or you can also store into Cache that can end up in having many DB calls when there are huge amounts of concurrent users.
The client
In this case if you can limit the amount of data with a separate class, to that and use whatever way to serialize it and send it to the client. Either in a cookie or in URI (if length permits and cookies are disabled)...
Outcome of these thoughts:
the main thing here would be to create a separate class if you gain much memory resources this way. So that's the first thing you should do.

Resources