4

暗号化されたDBに保存する必要があるユーザー名を持つユーザークラスがあります

public abstract class User
{
    public virtual int Id { get; protected set; }
    public virtual string Username
    {
        get
        {
            return _encryptionProvider.Decrypt(SecuredUsername);
        }
        protected set
        {
            SecuredUsername = _encryptionProvider.Encrypt(value);
        }
    }
    [Obsolete("Use the 'Username' property -- this property is only to be used by NHibernate")]
    protected virtual string SecuredUsername { get; set; }
}

User エンティティを次のようにマッピングしました。

public class UserMapping : ClassMap<User>
{
    public UserBaseMapping()
    {
        Id(user => user.Id).GeneratedBy.HiLo("100");
        Map(Reveal.Member<UserBase>("SecuredUsername")).Unique();
    }
}

LINQステートメントを書かなければならないまではうまくいきました。

User user = _session.QueryOver<User>().Where(x => x.Username == "Hamza").SingleOrDefault();

ここでの問題は、LINQ が上記のステートメントを SQL に変換すると、次のようになることです。 Select * from [dbo].[User] Where Username like 'Hamza'

お気づきかもしれませんが、テーブルには username という列はありませんが、secureusername と呼ばれる列はなく、暗号化された値が含まれています。だれでもこの問題の解決を手伝ってくれませんか。LINQ を使用してクエリを実行できるようにする必要があります。

4

3 に答える 3

1

カスタム タイプを使用してユーザー名を暗号化できます (User クラスで暗号化を行う代わりに、カスタム タイプで暗号化を行います) http://nhforge.org/blogs/nhibernate/archive/2009/02/22/を参照してくださいnhibernate.aspx の暗号化パスワードまたはその他の文字列

クエリを実行すると、完全一致のクエリしか実行できませんが、次のようなクエリを実行できます。

User user = _session.QueryOver<User>()
    .Where(x => x.Username == "Hamza")
    .SingleOrDefault();

大文字と小文字を区別しないで一致させたい場合は、カスタム型で値を大文字/小文字に変換できます。

LIKE 検索を実行したい場合は、他のタイプのインデックス作成を検討する必要があります。Lucene.NET と NHibernate.Search

于 2012-10-22T15:11:11.443 に答える
0

私は NHibernate を使用したことがありませんが、問題は Username の定義がデータベースではなくモデルにあることです。

基本的には 2 つの選択肢があり (NHibernate を実際に使用したことはなく、他のエンティティ フレームワーク/ORM を使用したことがないことに注意してください)、NHibernate の IQueryable の実装に応じて 3 つ目の選択肢がある可能性があります。

テーブル全体をメモリにロードします (テーブルが小さく、このクエリを頻繁に実行する場合、NHibernate にはスマート キャッシングがあると思いますが、これは役立つかもしれません):

User user = _session.QueryOver<User>().ToList().FirstOrDefault(x => x.Username == "Hamza");

2 つ目は、@Diode が提供する暗号化された文字列をチェックすることです。

// Resolve string, since we are using LINQ2SQSL in some form
var encName = _encryptionProvider.Encrypt("Hamza"); 
User user = _session.QueryOver<User>().FirstOrDefault(x => x.SecuredUsername == encName);

ラッピングの目的で IQueryable の特定のインスタンスを使用できる場合、それが 1 つの解決策になります。IQueryable の説明については、http://msdn.microsoft.com/en-us/library/bb351562.aspxを参照してください。

しかし、基本的に、暗号化はデータベースではなくサーバー上で行う必要があり、それによってオプションが制限されます。

編集: 「Hamz*」に一致するすべてのユーザーを検索します。メモリにロードしてチェックする必要があります。

var users = _session.QueryOver<User>().ToList().Where(x => x.Username.StartsWith("Hamz"));
于 2012-10-22T07:20:07.060 に答える
0

これはどう:

User user = _session.QueryOver<User>().Where(x => x.securedusername == _encryptionProvider("Hamza")).SingleOrDefault();

編集済み:上記のコメントで述べたように、クエリには問題があります。1 つのオプションは、(これは、ユーザー名が一意である場合にのみ実行できます。そうでない場合、競合が発生する可能性があります) 1. 各文字列値に一意のインデックスを作成する必要があります。例:

SAM = xyz(110111101)
SAMI = xyzk(110111101001)

このインデックスは、データベース内の顧客ごとに挿入する必要があります。

次に、次のように行くことができます:

`User user = _session.QueryOver<User>().Where(x => x.Index.Contains(IndexGenerator("Hamza"))).SingleOrDefault();//I do not know weather this Contains method exist in nhibernate`. But there should be. so find that :)

ただし、このクエリでは不要な値もいくつか返されますが、コーディングで復号化した後、実際のユーザー名を使用してさらにフィルタリングできます。これにより、正確な検索結果を得ることができます。

暗号化IndexGeneratorされている場合は、これを使用できます。_encryptionProvider

于 2012-10-22T06:51:39.773 に答える