有没有办法生成在C#中的URL中使用的唯一字母数字键(12位)?我有一组彼此独特的字符串,但不能直接使用它们,因为它们可能会更改,因此URL会中断。我有几种方法 -
a)使用数据库表本身的主键,该主键对应于具有上述字符串集的行,但这似乎是一个安全问题,因为它将公开数据库结构。
b)使用Guid,但是它再次不依赖于数据。
任何帮助将不胜感激。
答案 0 :(得分:3)
简答:否。
你正在尝试的是不可能的。 您必须跟踪已创建的ID 。这是数据库对增量索引列的作用。 I also understand that URL shortening tools take new keys from a pool of generated unique ones
所有这一切,something like this DotNetFiddle might work等可能是其他一些答案。
在小提琴中,我们在第一个例子中对主键进行哈希处理。由于只有完整哈希在计算上不可行而不是每个输入都是唯一的,并且因为我们使用哈希的子字符串,所以不保证唯一性,但它可能很接近。
以下是MSDN对哈希唯一性的看法。
加密散列函数具有以下特性:找到散列到相同值的两个不同输入在计算上是不可行的。
在第二个例子中,我们正在使用时间,据我所知,增加时间保证是唯一的,所以如果你可以依赖时间准确,这将有效。但是,如果您将依赖服务器时间等外部资源,那么您可能应该在数据库表或简单的平面文件中使用自动递增索引。
using System;
using System.Text;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
UseAHash();
UseTime();
}
public static void UseAHash()
{
var primaryKey = 123345;
HashAlgorithm algorithm = SHA1.Create();
var hash = algorithm.ComputeHash(Encoding.UTF8.GetBytes(primaryKey.ToString()));
StringBuilder sb = new StringBuilder();
for (var i = 0; i < 6; ++i)
{
sb.Append(hash[i].ToString("X2"));
}
Console.WriteLine(sb);
}
public static void UseTime()
{
StringBuilder builder = new StringBuilder();
// use universal to avoid daylight to standard time change.
var now = DateTime.Now.ToUniversalTime();
builder.Append(now.DayOfYear.ToString("D3"));
builder.Append(now.Hour.ToString("D2"));
builder.Append(now.Minute.ToString("D2"));
builder.Append(now.Second.ToString("D2"));
builder.Append(now.Millisecond.ToString("D3"));
Console.WriteLine("Length: " + builder.Length);
Console.WriteLine("Result: " + builder);
}
}
答案 1 :(得分:2)
您可以使用数据库中的密钥为随机生成器设定种子,并使用它来创建密钥:
int id = 42;
string chars = "2345679abcdefghjkmnpqrstuvwxyz";
Random rnd = new Random(id);
string key = new String(Enumerable.Range(0, 12).Select(n => chars[rnd.Next(chars.Length)]).ToArray());
注意:保证不是唯一的。我测试的值从1到10000000,并且没有重复。
答案 2 :(得分:0)
简单。创建一个新GUID,从数据库中为其分配一个实体,然后将其添加到数据库表中。
public class FooGuid
{
[Key] public Guid Url { get; set; }
public Foo Foo { get; set; }
}
Guid urlpart = ...
Foo foo = dbContext.FooGuids
.Where(f => f.Url == urlpart)
.Select(f => f.Foo)
.Single();