Будет ли показ первичного ключа к общественности потенциальной угрозой безопасности? - PullRequest
3 голосов
/ 28 мая 2010

Ну, вопрос не требует пояснений. Еще одна вещь: если это угроза безопасности, приведите пример того, что может сделать пользователь. В этом случае первичный ключ будет выглядеть примерно так: «Идентификатор продукта»

Спасибо!

Ответы [ 5 ]

9 голосов
/ 28 мая 2010

Не более, чем показ любых других данных. Если вы уязвимы для атак с использованием SQL-инъекций, то показ первичного ключа, вероятно, меньше всего вас беспокоит.

Подумайте об этом так, если кто-то может выполнить произвольный sql против вашего db, что принесет больше вреда: delete from users where id = 100 или delete from users where surname = 'smith'?

5 голосов
/ 28 мая 2010

Я не думаю, что существует риск раскрытия поля первичного ключа, но я не вижу преимуществ в рекламе этого как такового. (Я знаю, что, возможно, я читаю глубже в ваш вопрос, чем вы рассчитывали)

Если у вас есть ProductId, который позволяет вашему клиенту идентифицировать какой-либо продукт, это нормально для отображения. Риск безопасности минимален, ИМО. Я просто не стал бы раскрывать тот факт, что вы использовали ProductId в качестве первичного ключа - детали реализации должны быть скрыты даже при показе контента.

2 голосов
/ 28 мая 2010

Не обязательно. Но если вы когда-нибудь захотите изменить типы первичных ключей (или поставщики баз данных вообще требуют изменений), хорошая идея абстрагировать ваши первичные ключи от разработчиков на уровне приложений. Что вы делаете, это создаете интерфейс, который абстрагирует первичный ключ на этом уровне, но уровень данных знает об этом через его реализацию. Вот пример:

namespace Aesop.DataAccess
{
    // System namespaces
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Xml.Serialization;

    /// <summary>
    /// Represents an object's unique key in order to abstract out the
    /// underlying key generation/maintenance mechanism.
    /// </summary>
    /// <typeparam name="T">The type the key is representing.</typeparam>
    [ServiceContract]
    public interface IModelIdentifier<T> : ISerializable, IXmlSerializable
    {
        /// <summary>
        /// Gets a string representation of the domain the model originated
        /// from.
        /// </summary>
        string Origin
        {
            [OperationContract]
            get;
        }

        /// <summary>
        /// The model instance identifier for the model object that this
        /// <see cref="IModelIdentifier{T}"/> refers to.  Typically, this
        /// is a database key, file name, or some other unique identifier.
        /// </summary>
        /// <typeparam name="TKeyDataType">The expected data type of the
        /// identifier.</typeparam>
        /// <returns>The unique key as the data type specified.</returns>
        [OperationContract]
        TKeyDataType GetKey<TKeyDataType>();

        /// <summary>
        /// Performs an equality check on the two model identifiers and returns
        /// <c>true</c> if they are equal; otherwise <c>false</c> is returned.
        /// All implementations must also override the equal operator.
        /// </summary>
        /// <param name="obj">The identifier to compare against.</param>
        /// <returns>
        ///   <c>true</c> if the identifiers are equal; otherwise
        ///   <c>false</c> is returned.
        /// </returns>
        [OperationContract]
        bool Equals(IModelIdentifier<T> obj);
    }
}

А вот реализация "стандартного" первичного ключа int:

namespace Aesop.DataAccess
{
    // System namespaces
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Runtime.Serialization;
    using System.Security.Permissions;
    using System.Xml;
    using System.Xml.Schema;
    using System.Xml.Serialization;

    /// <summary>
    /// Represents an abstraction of the database key for a Model Identifier.
    /// </summary>
    /// <typeparam name="T">The expected owner data type for this identifier.
    /// </typeparam>
    [DebuggerDisplay("Integer Identifier={id}, Origin={Origin}")]
    [Serializable]
    public sealed class IntegerIdentifier<T> : IModelIdentifier<T> where T : class, ISerializable, IXmlSerializable
    {
        /// <summary>
        /// The unique ID.
        /// </summary>
        private int id;

        /// <summary>
        /// Initializes a new instance of the <see cref="IntegerIdentifier&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="id">The unique ID.</param>
        public IntegerIdentifier(int id)
        {
            this.id = id;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="IntegerIdentifier&lt;T&gt;"/> class.
        /// </summary>
        /// <param name="info">The
        /// <see cref="T:System.Runtime.Serialization.SerializationInfo"/> from
        /// which to retrieve the data.</param>
        /// <param name="context">The source (see
        /// <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for
        /// this deserialization.</param>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        private IntegerIdentifier(
            SerializationInfo info,
            StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }

            this.id = info.GetInt32("id");
        }

        /// <summary>
        /// Prevents a default instance of the <see cref="IntegerIdentifier&lt;T&gt;"/> class from being created.
        /// </summary>
        private IntegerIdentifier()
        {
        }

        /// <summary>
        /// Gets a string representation of the domain the model originated
        /// from.
        /// </summary>
        public string Origin
        {
            get
            {
                return this.GetType().Namespace;
            }
        }

        /// <summary>
        /// Implements the operator ==.
        /// </summary>
        /// <param name="integerIdentifier1">The first Model Identifier to
        /// compare.</param>
        /// <param name="integerIdentifier2">The second Model Identifier to
        /// compare.</param>
        /// <returns>
        ///   <c>true</c> if the instances are equal; otherwise
        ///   <c>false</c> is returned.
        /// </returns>
        public static bool operator ==(
            IntegerIdentifier<T> integerIdentifier1,
            IntegerIdentifier<T> integerIdentifier2)
        {
            return object.Equals(integerIdentifier1, integerIdentifier2);
        }

        /// <summary>
        /// Implements the operator !=.
        /// </summary>
        /// <param name="integerIdentifier1">The first Model Identifier to
        /// compare.</param>
        /// <param name="integerIdentifier2">The second Model Identifier to
        /// compare.</param>
        /// <returns>
        ///   <c>true</c> if the instances are equal; otherwise
        ///   <c>false</c> is returned.
        /// </returns>
        public static bool operator !=(
            IntegerIdentifier<T> integerIdentifier1,
            IntegerIdentifier<T> integerIdentifier2)
        {
            return !object.Equals(integerIdentifier1, integerIdentifier2);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is
        /// equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with
        /// the current <see cref="T:System.Object"/>.</param>
        /// <returns>true if the specified <see cref="T:System.Object"/> is
        /// equal to the current <see cref="T:System.Object"/>; otherwise,
        /// false.</returns>
        /// <exception cref="T:System.NullReferenceException">The
        /// <paramref name="obj"/> parameter is null.</exception>
        public override bool Equals(object obj)
        {
            return this.Equals(obj as IModelIdentifier<T>);
        }

        /// <summary>
        /// Serves as a hash function for a particular type.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        public override int GetHashCode()
        {
            return this.id.GetHashCode();
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            return this.id.ToString(CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// The model instance identifier for the model object that this
        /// <see cref="IModelIdentifier{T}"/> refers to.  Typically, this is a
        /// database key, file name, or some other unique identifier.
        /// </summary>
        /// <typeparam name="TKeyDataType">The expected data type of the
        /// identifier.</typeparam>
        /// <returns>The unique key as the data type specified</returns>
        public TKeyDataType GetKey<TKeyDataType>()
        {
            return (TKeyDataType)Convert.ChangeType(
               this.id,
               typeof(TKeyDataType),
               CultureInfo.InvariantCulture);
        }

        /// <summary>
        /// Performs an equality check on the two model identifiers and
        /// returns <c>true</c> if they are equal; otherwise <c>false</c>
        /// is returned.  All implementations must also override the equal
        /// operator.
        /// </summary>
        /// <param name="obj">The identifier to compare against.</param>
        /// <returns>
        ///   <c>true</c> if the identifiers are equal; otherwise
        ///   <c>false</c> is returned.
        /// </returns>
        public bool Equals(IModelIdentifier<T> obj)
        {
            if (obj == null)
            {
                return false;
            }

            return obj.GetKey<int>() == this.GetKey<int>();
        }

        /// <summary>
        /// Populates a
        /// <see cref="T:System.Runtime.Serialization.SerializationInfo"/> with
        /// the data needed to serialize the target object.
        /// </summary>
        /// <param name="info">The
        /// <see cref="T:System.Runtime.Serialization.SerializationInfo"/> to
        /// populate with data.</param>
        /// <param name="context">The destination (see
        /// <see cref="T:System.Runtime.Serialization.StreamingContext"/>) for
        /// this serialization.</param>
        /// <exception cref="T:System.Security.SecurityException">The caller
        /// does not have the required permission. </exception>
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
        public void GetObjectData(
            SerializationInfo info,
            StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }

            info.AddValue("id", this.id);
        }

        /// <summary>
        /// This method is reserved and should not be used. When implementing
        /// the IXmlSerializable interface, you should return null (Nothing in
        /// Visual Basic) from this method, and instead, if specifying a custom
        /// schema is required, apply the
        /// <see cref="T:System.Xml.Serialization.XmlSchemaProviderAttribute"/>
        /// to the class.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Xml.Schema.XmlSchema"/> that describes the
        /// XML representation of the object that is produced by the
        /// <see cref="M:System.Xml.Serialization.IXmlSerializable.WriteXml(System.Xml.XmlWriter)"/>
        /// method and consumed by the
        /// <see cref="M:System.Xml.Serialization.IXmlSerializable.ReadXml(System.Xml.XmlReader)"/>
        /// method.
        /// </returns>
        public XmlSchema GetSchema()
        {
            return null;
        }

        /// <summary>
        /// Generates an object from its XML representation.
        /// </summary>
        /// <param name="reader">The <see cref="T:System.Xml.XmlReader"/>
        /// stream from which the object is deserialized.</param>
        public void ReadXml(XmlReader reader)
        {
            if (reader != null)
            {
                this.id = Convert.ToInt32(
                    reader.GetAttribute("id"),
                    CultureInfo.InvariantCulture);
            }
        }

        /// <summary>
        /// Converts an object into its XML representation.
        /// </summary>
        /// <param name="writer">The <see cref="T:System.Xml.XmlWriter"/>
        /// stream to which the object is serialized.</param>
        public void WriteXml(XmlWriter writer)
        {
            if (writer != null)
            {
                writer.WriteAttributeString(
                    "id",
                    this.id.ToString(CultureInfo.InvariantCulture));
            }
        }

        /// <summary>
        /// Generates an object from its string representation.
        /// </summary>
        /// <param name="value">The value of the model's type.</param>
        /// <returns>A new instance of this class as it's interface containing
        /// the value from the string.</returns>
        internal static IModelIdentifier<T> FromString(string value)
        {
            int id;

            if (int.TryParse(
                value,
                NumberStyles.None,
                CultureInfo.InvariantCulture,
                out id))
            {
                return new IntegerIdentifier<T>(id);
            }

            return null;
        }

        /// <summary>
        /// Generates an object from its XML representation.
        /// </summary>
        /// <param name="reader">The <see cref="T:System.Xml.XmlReader"/>
        /// stream from which the object is deserialized.</param>
        /// <returns>A new instance of this class as it's interface containing
        /// the value from the XmlReader.</returns>
        internal static IModelIdentifier<T> FromXml(XmlReader reader)
        {
            if (reader != null)
            {
                return new IntegerIdentifier<T>(Convert.ToInt32(
                    reader.GetAttribute("id"),
                    CultureInfo.InvariantCulture));
            }

            return null;
        }
    }
}
1 голос
/ 28 мая 2010

, если он содержит читаемую информацию для некоторого элемента конфиденциальной информации, тогда да.

0 голосов
/ 28 мая 2010

Очевидно, что это зависит от того, какую информацию содержит ключ. Вполне возможно, что он может быть чувствительным (возможно, номер счета). Возможно, идентификатор продукта является сентиментальной информацией в вашем приложении, но я не понимаю, почему тот факт, что он является первичным ключом, должен в большей или меньшей степени представлять угрозу безопасности.

...