如何生成唯一的12位字母数字键以用于URL

时间:2015-03-29 19:32:01

标签: c# asp.net-mvc

有没有办法生成在C#中的URL中使用的唯一字母数字键(12位)?我有一组彼此独特的字符串,但不能直接使用它们,因为它们可能会更改,因此URL会中断。我有几种方法 -

a)使用数据库表本身的主键,该主键对应于具有上述字符串集的行,但这似乎是一个安全问题,因为它将公开数据库结构。

b)使用Guid,但是它再次不依赖于数据。

任何帮助将不胜感激。

3 个答案:

答案 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();