Je validons le nom d'utilisateur (insensible à la casse-insensible) et le mot de passe (sensible à la casse) de la base de données
J'utilise l'entité Framework 5.0 pour interagir avec la base de données P>
dans le mot de passe de la base de données est p>
"0x11A46971FFFE1A2CA228CF592CA37DC77E7CCF759602D53629C22B693AEEE96CCD9F889D8E9A92C19391E9A92C19391E9A92C939E391ACDC939E391ACDC939B993C9D7F5D" P> BlockQuote>
Je m'attends à NULL en retour pour mon bloc de code suivant lorsque je change de cas de mot de passe pour abaisser I.E. P>
"0x11A46971FFFE1A2CA228CF592CA37DC77E7CCF759602D53629C22B693AEEE96CCD9F889D8E9A92C19391E9A92C19391E9A92C939E391ACDC939E391ACDC939B993C9D7F5D" P> blockquote>
mais cela ne échoue pas et renvoie une entité utilisateur appropriée. P>
xxx pré> null p>
xxx pré> c'est étrange? Pourquoi ça se passe? Comment rédiger une requête sensible à la casse à SQL de Linq? P> P>
6 Réponses :
Lorsque vous utilisez
var users = context.Users.ToList();
SQL n'est pas sensible à la casse. Si vous avez examiné le SQL généré, cela ressemblerait à ceci comme suit:
EXISTS(SELECT * FROM Users WHERE userName = 'foo' AND Password = '0x11a46971eff1e1a2ca228cf592ca37dc77e7ccf759602d53629c22b693aeee96ccd9f889d8e9a92c19391e6bd2dd07e741e9b7aa07e391acdc939b993c9d7f5d')
Je crois que vous pouvez rendre la casse SMSQL sensible en spécifiant une assiette sensible à la casse pour cette colonne.
Vous pouvez oui, vous modifiez la méthode de cette colonne de cette colonne. Ce n'est pas quelque chose que je recommanderais car si vous n'êtes pas au courant du changement, vous pouvez obtenir des résultats inattendus. blog.sqlauthority.com/2007/04/30 / ...
En outre, le mot de passe est en fait codé de manière à ne pas considérer la sensibilité au cas. 0xaa code> et
0xaa code> sont fonctionnellement équivalents.
La recherche SQL est insensible à la casse et lorsque vous faites le tolist code> vous finissez par faire une comparaison sensible à la casse. Mais le
tolist code> retournera tout de la DB. Au lieu de faire le
où code> sur la base de données db, puis une autre comparaison pour vous assurer que le mot de passe est le cas correct.
using (var context = new MyDbContext(ConnectionString))
{
var users = context.Users.Where(x => x.Name == userName && x.Password == password).ToList();
return users.FirstOrDefault(x => x.Password.Equals(password)));
}
Sauf si vous ne le jetez pas pour la liste, cela comparera de manière insensible à la casse. J'ai édité votre réponse en ajoutant .tolist (); à la fin du premier linq à SQL
Cela n'est pas possible dans mon scénario que deux utilisateurs ont le même nom d'utilisateur, il convient donc à la base de la base de données de requête avec le nom d'utilisateur et le mot de passe insensible à casse et vérifiez plus tard uniquement pour le mot de passe sensible à la casse.
Il y a une réponse plus détaillée à cela ici: P>
https://stackoverflow.com/a/3843382/933416 p>
Si vous en avez besoin, vous pouvez configurer la colonne pour être sensible à la casse du côté serveur. Mais dans votre cas, je ne vois pas pourquoi vous avez même besoin d'interroger le mot de passe. Il n'y a sûrement qu'un mot de passe pour chaque nom d'utilisateur et un nom d'utilisateur est censé être insensible à la casse - alors pourquoi pas seulement interroger le nom d'utilisateur, puis vérifier le mot de passe sur le résultat? P>
Ne laissez pas les détails de l'utilisateur de la boîte SQL sans vulnérabilité de sécurité authentifiée.
Comme @nmClean mentionné, c'est parce que votre base de données est configurée pour effectuer des comparaisons insensibles de cas. Le petit programme suivant montre comment EF ignore complètement les valeurs code> StringComParison code> transmettes à Il s'agit d'un concept impossible lorsque vous travaillez avec EF (et d'autres fournisseurs LINQ également). Votre requête tel qu'il est écrit looks em> comme le code .NET normal. Cependant, ce n'est pas! De nombreux fournisseurs traduisent le code à quelque chose de complètement différent, dans ce cas SQL (pour SQL Server, Transact-SQL). Seul un sous-ensemble des méthodes .NET disponibles fonctionnera du tout (c'est pourquoi, par exemple, vous ne pouvez pas utiliser où vous utilisez string.equals code>. Il montre également comment changer la collation de la colonne de base de données permet de réaliser ce dont vous avez besoin.
regex code> dans une requête EF), et ceux qui travaillent peuvent présenter un comportement subtilement différent. comparé à ce que vous attendez. p>
tolist () code> sur une requête, puis em> Appliquez votre filtre, vous utilisez réellement LINQ vers des objets , pas ef, pour appliquer le filtre. Linq aux objets est em> "réel" .NET, vous disposez donc de la gamme complète de fonctionnalités .NET à votre disposition. Bien sûr, vous perdez l'avantage d'avoir votre code exécuté sur le serveur SQL, ce n'est donc généralement pas une option. P>
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
namespace ConsoleApplication2
{
public class Initializer<T> : DropCreateDatabaseAlways<T> where T : DbContext
{
protected override void Seed(T context)
{
base.Seed(context);
// Comment out this line and note how the count changes.
context.Database.ExecuteSqlCommand("ALTER TABLE MyEntity ALTER COLUMN MyString nvarchar(MAX) COLLATE Latin1_General_CS_AS");
}
}
[Table("MyEntity")]
public class MyEntity
{
[Key]
public virtual int MyEntityId { get; set; }
[Required]
public virtual string MyString { get; set; }
}
public class MyContext : DbContext
{
public DbSet<MyEntity> Entities
{
get { return this.Set<MyEntity>(); }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var e = modelBuilder.Entity<MyEntity>();
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new Initializer<MyContext>());
using (MyContext context = new MyContext())
{
context.Entities.Add(new MyEntity { MyString = "aaa" });
context.Entities.Add(new MyEntity { MyString = "AAA" });
context.SaveChanges();
}
using (MyContext context = new MyContext())
{
var caseSensitiveQuery = from e in context.Entities
where e.MyString.Equals("aaa", StringComparison.Ordinal)
select e;
var caseInsensitiveQuery = from e in context.Entities
where e.MyString.Equals("aaa", StringComparison.OrdinalIgnoreCase)
select e;
// Note how the StringComparison parameter is completely ignored. Both EF queries are identical.
Console.WriteLine("Case sensitive query (count = {0}):\r\n{1}", caseSensitiveQuery.Count(), caseSensitiveQuery);
Console.WriteLine();
Console.WriteLine("Case insensitive query (count = {0}):\r\n{1}", caseInsensitiveQuery.Count(), caseInsensitiveQuery);
}
Console.ReadLine();
}
}
}
Vous pouvez oui, vous modifiez la méthode de cette colonne de cette colonne. Ce n'est pas quelque chose que je recommanderais car si vous n'êtes pas au courant du changement, vous pouvez obtenir des résultats inattendus. blog.sqlauthority.com/2007
@Imranrizvi - Je ne suis pas sûr d'être d'accord avec ça. Il est vrai que les collations sont souvent une source de confusion, mais elles existent pour une raison. La classement d'une colonne doit être sélectionnée en fonction du comportement de tri et de comparaison souhaité. Ususally une collation est appropriée pour une base de données ou serveur entière, mais ici il y a une bonne raison de s'écarter de cela. En ce qui concerne l'observation, "Vous pouvez obtenir des résultats inattendus", pourrait affirmer que vous obtenez déjà des résultats inattendus! Le changement de collation vous donnerait ce que vous espérez tout le long!
Comme tout le monde l'a déjà mentionné, la cause du problème est que SQL Server par défaut de non sensible à la casse et c # par défaut à la case sensible à la casse. p>
Vous pouvez modifier le champ de mot de passe de Pourquoi les votes anonymes en bas? En utilisant une chaîne pour stocker et comparer ce qui semble être une valeur de hachage de 64 octets n'est pas la meilleure approche. Il n'est pas nécessaire de fonder 64 encoder un hachage à stocker (sauf si l'entité framework ne peut pas le gérer?). P>
http://support.microsoft.com/kb/307020 - Comment calculer et comparer les valeurs de hachage En utilisant Visual C #
comparer les mots de passe de hachage p> varchar code> à
varbinaire code> pour contourner ce problème. p>
En effet! Et ef prend en charge varbinary code>; Il correspond à un .NET
octet [] code>.
Que se passe-t-il lorsque vous courez le SQL manuellement?
X.Authentification Secret.equals (mot de passe) code> vscode> x.password.equaux (mot de passe) code>
N'utilisez pas non plus
context.utilisateur.tolist (); code>, il itière sur tout le tableau.
@Ahmedkraiem qui était de type, édité la question s'il vous plaît voir.
@ Daniela.White Les deux requêtes reviennent true (j'ai eu que SQL est insensible à l'affaire)