Why AspNetUser create a string id? Id string is method safe? - asp.net-mvc

can someone explain me this please? It's about AspNetUser, when we create a table, it generates an id in string, but how good is it? Isn't it bad in terms of security? Because if I want to show something only with one user, I need to compare my id (int) with id (string), I know it's simple and possible but I just need to convert the int to string, but is this method safe?
I was trying this and it worked but i'm comparing a string.
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var plans = _unitOfWork.Games.GetAll().Where(p => p.UserId.Equals(userId));
return View(plans);

The AspNetUser is a part of ASP.NET Identity, which is a framework that provides authentication and authorization services. The Id column of the AspNetUser table is typically generated as a string (GUID) to ensure that it is unique across all users. Comparing the user ID as a string with another string value (such as the value from ClaimTypes.NameIdentifier) is not a security issue. The string comparison is a simple and efficient way to retrieve the data for a specific user. Converting the user ID to an integer would not provide any additional security benefits, but it may impact performance if the integer comparison involves a large number of operations.
Refrence link:
https://learn.microsoft.com/en-us/dotnet/api/system.identitymodel.claims.claimtypes.nameidentifier?view=netframework-4.8.1
Also :
What are the best practices for using a GUID as a primary key, specifically regarding performance?

Related

How to map auto increment Id from domain model to entity model in Entity Framework ASP.NET Web API

I am trying to follow DDD for my current project. My question is specifically regarding POST request that contains values for my domain model. To simplify, let's say following is my domain model:
class Person
{
public int Id {get, set};
public string name {get, set};
}
And below is the entity model backing above domain:
class PersonEF
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id {get, set};
public string name {get, set};
}
Now when I receive a POST request to create a new Person it doesn't contain the Id as it's supposed to be generated by the database. I first map Person to PersonEF using AutoMapper which sets the Id to 0 in PersonEF and hence the INSERT in database fails. So to fix these my options are:
Name Id as something else in Person. If I do this then I would have to write custom mapping just for Id for GET requests.
Make Id nullable (int?) in both Person and PersonEF and this way auto increment will work, but having key as nullable int doesn't sound like a good idea in itself.
So please suggest the best way to do this.
EDIT
My bad. Code was missing context.SaveOrUpdate(). I added that and it's working as expected.
It's hard to say for sure, as the code of most importance, that you should have posted, would be that of your controller action where the mapping and saving occurs. However, I can tell you that the 0 is the default value for an int. This is not due to AutoMapper, or mapping in general, per se. The entity, freshly created, without any other interaction, would still have 0 as the id.
As a result, this should not be causing a problem with saving the entity, or else you'd never be able to save any entity that had an int PK. However, depending on what Entity Framework thinks you're trying to do with the entity, it might cause problems. Namely, you need to make sure that Entity Framework is aware that you're wanting to create this entity and not just update it. Usually, that's achieved by simply adding it to the DbSet:
db.PersonEFs.Add(personEF);
Not sure why you would need to go any farther than that, but if that's not working for some reason, you can be a bit more explicit:
db.Entry(personEF).State = EntityState.Added;
However, really, if you need to do that, there's something else going on that you'd just be masking.

what is the best way to store a user filtered query params in a database table?

I have an ASP.NET MVC website. In my backend I have a table called People with the following columns:
ID
Name
Age
Location
... (a number of other cols)
I have a generic web page that uses model binding to query this data. Here is my controller action:
public ActionResult GetData(FilterParams filterParams)
{
return View(_dataAccess.Retrieve(filterParams.Name, filterParams.Age, filterParams.location, . . .)
}
which maps onto something like this:
http://www.mysite.com/MyController/GetData?Name=Bill .. .
The dataAccess layer simply checks each parameter to see if its populated to add to the db where clause. This works great.
I now want to be able to store a user's filtered queries and I am trying to figure out the best way to store a specific filter. As some of the filters only have one param in the queryString while others have 10+ fields in the filter I can't figure out the most elegant way to storing this query "filter info" into my database.
Options I can think of are:
Have a complete replicate of the table (with some extra cols) but call it PeopleFilterQueries and populate in each record a FilterName and put the value of the filter in each of field (Name, etc)
Store a table with just FilterName and a string where I store the actual querystring Name=Bill&Location=NewYork. This way I won't have to keep adding new columns if the filters change or grow.
What is the best practice for this situation?
If the purpose is to save a list of recently used filters, I would serialise the complete FilterParams object into an XML field/column after the model binding has occurred. By saving it into a XML field you're also giving yourself the flexibility to use XQuery and DML should the need arise at a later date for more performance focused querying of the information.
public ActionResult GetData(FilterParams filterParams)
{
// Peform action to get the information from your data access layer here
var someData = _dataAccess.Retrieve(filterParams.Name, filterParams.Age, filterParams.location, . . .);
// Save the search that was used to retrieve later here
_dataAccess.SaveFilter(filterParams);
return View(someData);
}
And then in your DataAccess Class you'll want to have two Methods, one for saving and one for retrieving the filters:
public void SaveFilter(FilterParams filterParams){
var ser = new System.Xml.Serialization.XmlSerializer(typeof(FilterParams));
using (var stream = new StringWriter())
{
// serialise to the stream
ser.Serialize(stream, filterParams);
}
//Add new database entry here, with a serialised string created from the FilterParams obj
someDBClass.SaveFilterToDB(stream.ToString());
}
Then when you want to retrieve a saved filter, perhaps by Id:
public FilterParams GetFilter(int filterId){
//Get the XML blob from your database as a string
string filter = someDBClass.GetFilterAsString(filterId);
var ser = new System.Xml.Serialization.XmlSerializer(typeof(FilterParams));
using (var sr = new StringReader(filterParams))
{
return (FilterParams)ser.Deserialize(sr);
}
}
Remember that your FilterParams class must have a default (i.e. parameterless) constructor, and you can use the [XmlIgnore] attribute to prevent properties from being serialised into the database should you wish.
public class FilterParams{
public string Name {get;set;}
public string Age {get;set;}
[XmlIgnore]
public string PropertyYouDontWantToSerialise {get;set;}
}
Note: The SaveFilter returns Void and there is no error handling for brevity.
Rather than storing the querystring, I would serialize the FilterParams object as JSON/XML and store the result in your database.
Here's a JSON Serializer I regularly use:
using System.IO;
using System.Runtime.Serialization.Json;
using System.Text;
namespace Fabrik.Abstractions.Serialization
{
public class JsonSerializer : ISerializer<string>
{
public string Serialize<TObject>(TObject #object) {
var dc = new DataContractJsonSerializer(typeof(TObject));
using (var ms = new MemoryStream())
{
dc.WriteObject(ms, #object);
return Encoding.UTF8.GetString(ms.ToArray());
}
}
public TObject Deserialize<TObject>(string serialized) {
var dc = new DataContractJsonSerializer(typeof(TObject));
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(serialized)))
{
return (TObject)dc.ReadObject(ms);
}
}
}
}
You can then deserialize the object and pass it your data access code as per your example above.
You didn't mention about exact purpose of storing the filter.
If you insist to save filter into a database table, I would have following structure of the table.
FilterId
Field
FieldValue
An example table might be
FilterId Field FieldValue
1 Name Tom
1 Age 24
1 Location IL
3 Name Mike
...
The answer is much more simple than you are making it:
Essentially you should store the raw query in its own table and relate it to your People table. Don't bother storing individual filter options.
Decide on a value to store (2 options)
Store the URL Query String
This id be beneficial if you like open API-style apps, and want something you can pass nicely back and forth from the client to the server and re-use without transformation.
Serialize the Filter object as a string
This is a really nice approach if your purpose for storing these filters remains entirely server side, and you would like to keep the data closer to a class object.
Relate your People table to your Query Filters Table:
The best strategy here depends on what your intention and performance needs are. Some suggestions below:
Simple filtering (ex. 2-3 filters, 3-4 options each)
Use Many-To-Many because the number of combinations suggests that the same filter combos will be used lots of times by lots of people.
Complex filtering
Use One-To-Many as there are so many possible individual queries, it less likely they are to be reused often enough to make the extra-normalization and performance hit worth your while.
There are certainly other options but they would depend on more detailed nuances of your application. The suggestions above would work nicely if you are say, trying to keep track of "recent queries" for a user, or "user favorite" filtering options...
Personal opinion
Without knowing much more about your app, I would say (1) store the query string, and (2) use OTM related tables... if and when your app shows a need for further performance profiling or issues with refactoring filter params, then come back... but chances are, it wont.
GL.
In my opinion the best way to save the "Filter" is to have some kind of json text string with each of the "columns names"
So you will have something in the db like
Table Filters
FilterId = 5 ; FilterParams = {'age' : '>18' , ...
Json will provide a lot of capabilities, like the use of age as an array to have more than one filter to the same "column", etc.
Also json is some kind of standard, so you can use this "filters" with other db some day or to just "display" the filter or edit it in a web form. If you save the Query you will be attached to it.
Well, hope it helps!
Assuming that a nosql/object database such as Berkeley DB is out of the question, I would definitely go with option 1. Sooner or later you'll find the following requirements or others coming up:
Allow people to save their filters, label, tag, search and share them via bookmarks, tweets or whatever.
Change what a parameter means or what it does, which will require you to version your filters for backward compatibility.
Provide auto-complete functions over filters, possibly using a user's filter history to inform the auto-complete.
The above will be somewhat harder to satisfy if you do any kind of binary/string serialization where you'll need to parse the result and then process them.
If you can use a NoSql DB, then you'll get all the benefits of a sql store plus be able to model the 'arbitrary number of key/value pairs' very well.
Have thought about using Profiles. This is a build in mechanism to store user specific info. From your description of your problem its seems a fit.
Profiles In ASP.NET 2.0
I have to admit that M$ implementation is a bit dated but there is essentially nothing wrong with the approach. If you wanted to roll your own, there's quite a bit of good thinking in their API.

Storing Sha256 Hashed Passwords with Nhibernate

I have a simple web app that has a login page, the front end domain has a simple model with:
string username {get;set;}
string password {get;set;}
However it is encrypted with sha256 before it is sent over to the data domain object, originally the data domain was:
string username {get;set;}
string password {get;set;}
So I would take the password from the ui, encrypt it then using the Encoding.GetString() method, get back a string for persisting. However when I try to persist the data it just seems to give an exception, which I believe to be down to the characters in the string not being valid.
After looking around some people have recommended storing it as a varbinary(32) and using a byte[] password {get;set;} within the data layer, however I couldn't get Nhibernate to map it correctly.
So can anyone tell me the best practise on storing hashed passwords with Nhibernate and SqlServer or MySql. (The app supports both dbs)
You shouldn't use Encoding.GetString() on a SHA value since it will produce text that may not store correctly, or worse, give an exception. Rather use something like Convert.ToBase64String.

Incorporate Membership in ASP.NET MVC

I have been wondering on how to use ASP.NET Membership together with MVC. The basic setup is very simple, but if I want to use extra fields like address, nickname etc, should I then use ProfileCommon or should I create a separate table which contains the extra data and link to the UserId in Aspnet_users?
I have an issue where I have changed the name in Membership to use the email, and I then need the extra fields (address, nickname etc.). If I use ProfileCommon I can receive the object by
public static ProfileCommon GetProfile(string username)
{
return ((ProfileCommon)(ProfileBase.Create(username)));
}
The problem is I save the UserId in different tables, and I can't figure out how to receive the ProfileCommon object by UserId instead of username (which in my case is the email)?
I could then either change the relation in the different tables to use the email, but this would be a very slow implementation, or I could create a separate table with the extra fields.
Is there perhaps a third and better option?
You could simply join the user table in order to receive the email.
Generally it does not seem to be a good idea to use two different fields as the id.
I chose to create the separate table, since I would not be limited by the ProfileBase class.

How are foreign keys and Guids dealt with in LINQ to Entities?

Just using this as an example...
Here are the columns in my UserProfile table:
ProfileID (Primary key)
UserID (Foreign key)
Address
PhoneNumber
now, when I want to add a new user to the database using LINQ to Entities, here is what I'm doing:
UserProfile profileToAdd;
profileToAdd.ProfileID = 0;
profileToAdd.Address = "123 MyStreet";
profileToAdd.PhoneNumber = "123-4567";
/* How do I add in the UserID here? */
_myDB.AddToUserProfiles(profileToAdd);
A few questions...
Is there anything special about dealing with Foreign keys that I need to know, or can I assign it just as I did with Address or PhoneNumber?
The UserId is a Guid, and I need to retrieve it from the current user's UserId. I can't seem to get access to Membership class or User class (This is a C# Library so I'm guessing it needs a reference somehow, but my project is already referencing my Library so I can't reference back or I'll have a circular dependancy)
I don't quite understand how to deal with Guids. When implementing getProfileByUserName(string userName), here's my problem...
first off I can't retrieve the UserID, here's what I tried:
Guid currUser = (Guid)from user in _ myDB.aspnet_Users
where user.UserName == userName
select new { user.UserId };
But it says I can't cast it to a Guid for some reason.
If you can provide any insight to any of these questions I would greatly appreciate it!
Thanks,
Matt
If the database contains the proper constraints for the foreign key relationship, there should be a member in your UserProfile class, that points to a User object. The name might be a little weird, such as UserProfileUser or something like that.
However, you can change this name in the diagram. Just set a pointer to the user entity object and the framework will assign the correct id for you.

Resources