问题是不言自明的。还有一件事是,如果是安全风险,请提供用户可以做的事情的示例。在这种情况下,主键类似于:“产品ID”
谢谢!
答案 0 :(得分:9)
仅显示任何其他数据。如果您容易受到SQL注入攻击,那么显示主键可能是您最不关心的问题。
以这种方式思考,如果有人可以对你的数据库执行任意的sql,这将造成更大的伤害:delete from users where id = 100
或delete from users where surname = 'smith'
?
答案 1 :(得分:5)
我不认为暴露主键字段存在固有的风险,但我认为没有任何优势来宣传它。 (我知道我可能会比你想要的更深入地阅读你的问题)
如果您的ProductId
允许您的客户识别某个产品,则可以显示。国际海事组织的安全风险很小。我只是不会暴露您使用ProductId
作为主键的事实 - 即使在公开内容时也应该隐藏实现细节。
答案 2 :(得分:2)
不一定。但是如果你一直在改变主键类型(或者数据库提供者完全需要更改),那么将主键抽象给应用程序级开发人员是一个好主意。您所做的是创建一个接口,该接口在该级别抽象主键,但数据层通过其实现了解它。这是一个例子:
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<T>"/> 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<T>"/> 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<T>"/> 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;
}
}
}
答案 3 :(得分:1)
如果它包含某些机密数据元素的可读信息,则为是。
答案 4 :(得分:0)
显然,这取决于密钥包含的信息。可以想象它可能是敏感的(也许是账号)。也许产品ID是您应用程序中的敏感信息,但我不明白为什么它是主键这一事实应该会使其产生更多或更少的安全风险。