vb.net Visual Basic 密码生成器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41459165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Visual Basic Password Generator
提问by Tim Hannah
I have been tasked with creating a visual basic random password generator. I have come up with the below which works however its a bit crude with its password criteria. I would like each password it generates to have at least 1 number, uppercase and lowercase in it. However how I have coded this it will generate a random combination which quite often results in one of the criteria being missed out.
我的任务是创建一个可视化的基本随机密码生成器。我想出了下面的方法,但是它的密码标准有点粗糙。我希望它生成的每个密码至少有 1 个数字,大写和小写。但是,我如何编码它会生成一个随机组合,这通常会导致错过其中一个标准。
I have had a play myself and I was going to have three strings, one with uppercase, one with lower case and a third with numbers. Once it has one of each it will then generate the rest of the password using my code. This doesn't sound very clean and I have been having problems doing this.
我自己玩过一出戏,我将有三根弦,一根大写,一根小写,第三根带数字。一旦它拥有其中之一,它将使用我的代码生成其余的密码。这听起来不是很干净,我在这样做时遇到了问题。
Can anyone help point me in the right direction or assist with the code below. Passwords must be between 6 and 20 characters in length.
任何人都可以帮助我指出正确的方向或协助以下代码。密码长度必须在 6 到 20 个字符之间。
Thanks in advance
提前致谢
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
TextBox2.Text = GenerateCode()
End Sub
Private Function GenerateCode() As Object
Dim intRnd As Object
Dim intStep As Object
Dim strName As Object
Dim intNameLength As Object
Dim intLength As Object
Dim strInputString As Object
strInputString = "1234567890ABCDEFGHIJKLMEOPQRSTUWXYZabcdefghijklmnopqrstuvwxyz"
intLength = Len(strInputString)
Randomize()
strName = ""
'Check for valid numeric entry
If Integer.TryParse(TextBox1.Text, intNameLength) And intNameLength >= 6 And intNameLength <= 20 Then
For intStep = 1 To intNameLength
intRnd = Int((intLength * Rnd()) + 1)
strName = strName & Mid(strInputString, intRnd, 1)
Next
GenerateCode = strName
Else
TextBox1.Text =("Please enter a valid password length")
End If
End Function
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
My.Computer.Clipboard.SetText(TextBox2.Text)
End Sub
Private Sub TextBox1_Enter(sender As Object, e As EventArgs) Handles TextBox1.Enter
TextBox1.Text = ""
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
End Class
========== UPDATE ==========
========== 更新 ==========
Right I have changed my code a little so I have now got three strings with the different characters in, 1 for uppers, one for lowers and one for numbers.
是的,我稍微改变了我的代码,所以我现在得到了三个包含不同字符的字符串,1 个代表大写,一个代表小写,一个代表数字。
This enables me to have a checkbox functionality in the form which is a plus. I have played around with the code and it now generates passwords depending on what I select with the checkboxes which as I say is awesome however I cant always guarantee that if I select, number, upper and lower I will get a password that contains all three, and sometimes the password will only contain numbers even though all three boxes are checked.
这使我能够在表单中拥有一个复选框功能,这是一个加分项。我已经使用了代码,现在它会根据我选择的复选框生成密码,正如我所说的很棒,但是我不能总是保证如果我选择数字、上限和下限,我将获得包含所有三个的密码,有时即使选中所有三个框,密码也只会包含数字。
In guessing this is something to do with the fact I'm just asking it to generate random password using the characters I give it, and there is no verification that it has used all three of the options.
猜测这与我只是要求它使用我给它的字符生成随机密码的事实有关,并且没有验证它是否使用了所有三个选项。
Any help on this would be awesome. I am trying and I'm not just posting and hoping someone will do the work for me. If someone can point me in the right direction would be great.
对此的任何帮助都会很棒。我正在尝试,我不只是发帖并希望有人为我完成这项工作。如果有人能指出我正确的方向,那就太好了。
Here is my new code.
这是我的新代码。
Public Function GenerateCode()
Dim intRnd As Integer
Dim intStep As Integer = Nothing
Dim strname As String
Dim intlength As Integer
Dim strinputstring As String = ""
Dim Numbers As String = "12345678901234567890"
Dim Lower As String = "abcdefghijklmnopqrstuvwxyzyz"
Dim Upper As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZYZ"
Dim intnamelength As Integer = 1
If CheckBox1.Checked Then strinputstring &= Lower
If CheckBox2.Checked Then strinputstring &= Numbers
If CheckBox3.Checked Then strinputstring &= Upper
intlength = Len(strinputstring)
Integer.TryParse(NumericUpDown1.Text, intnamelength)
Randomize()
strname = ""
For inStep = 1 To intnamelength
intRnd = Int(Rnd() * intlength) + 1
strname = strname & Mid(strinputstring, intRnd, 1)
Next
Return strname
End Function
回答by ??ssa P?ngj?rdenlarp
This doesn't rely on UI controls, nor does it use the legacy pre-NET VB functions. Instead, variables are passed to the generator so it is UI independent. It also does not use As Objectbecause strings are strings.
这不依赖于 UI 控件,也不使用旧的 pre-NET VB 函数。相反,变量被传递给生成器,因此它是独立于 UI 的。它也不使用,As Object因为字符串是字符串。
<Flags>
Private Enum PasswordParts
Upper = 1
Lower = 2
Numerals = 4
All = 7
End Enum
Private Shared RNG As New Random()
Private Shared Numerals As String = "0123456789"
Private Shared Upper As String = "ABCDEFGHIJKLMNPQRSTUVWXYZYZ"
Private Shared Lower As String = "abcdefghijkmnopqrstuvwxyzyz"
Private Function GeneratePassword(length As Int32,
Optional pwparts As PasswordParts = PasswordParts.All) As String
Dim PWCharPool As String = ""
Dim PW As New List(Of String)()
' check the requested length
If length < 6 Then length = 6
If length > 20 Then length = 20
' build the pool and add the first of required characters
' for assure minimum conformance
If pwparts.HasFlag(PasswordParts.Lower) Then
PW.Add(Lower(RNG.Next(0, Lower.Length)))
PWCharPool &= Lower
End If
If pwparts.HasFlag(PasswordParts.Upper) Then
PW.Add(Upper(RNG.Next(0, Upper.Length)))
PWCharPool &= Upper
End If
If pwparts.HasFlag(PasswordParts.Numerals) Then
PW.Add(Numerals(RNG.Next(0, Numerals.Length)))
PWCharPool &= Numerals
End If
' pick the rest of the elements
For n As Int32 = PW.Count To length - 1
PW.Add(PWCharPool(RNG.Next(0, PWCharPool.Length)))
Next
' shuffle the result so that the
' first 1-3 chars are not predictable
Shuffle(PW, RNG)
' create a string from the result
Return String.Join("", PW)
End Function
- Note that there is no lower case
Lor upper caseO. Users willconfuse these with0and1, so either remove them or the0and1(or both) - If the requirements for at least 1 upper, lower and numeral are hard, then there is no real need for the
Ifstatements (not blocks): just always pick one from each list before you add them to the pool. You also would not need theEnumor param. I left them based on the code in the question- Note that you should add code to handle when they click nocheckboxes before calling this method.
- A
StringBuildercould be used in place of theList(of String), but the strings are so short that it really doesn't save any time until you run it in a loop many, many times and even then the time saved is minuscule.
- 请注意,没有小写
L或大写O。用户会混淆这与0和1,所以将其删除或0和1(或两者) - 如果对至少 1 个 upper、lower 和 numeric 的要求很严格,那么就没有真正需要
If语句(不是块):在将它们添加到池中之前,总是从每个列表中选择一个。您也不需要Enumor 参数。我根据问题中的代码离开了它们- 请注意,在调用此方法之前,您应该添加代码以处理当他们没有单击复选框时。
StringBuilder可以使用A代替List(of String),但是字符串太短了,它真的不会节省任何时间,直到您在循环中多次运行它,即使这样节省的时间也是微不足道的。
Testing it:
测试它:
Dim enumValues = [Enum].GetValues(GetType(PasswordParts)).Cast(Of Int32)()
For n As Int32 = 1 To 1000
Dim style = CType(enumValues(RNG.Next(0, 4)), PasswordParts)
Dim pwLen = RNG.Next(6, 21)
Dim PW = GeneratePassword(pwLen, style)
' get riled up if the length does not match
Debug.Assert(PW.Length = pwLen)
Console.WriteLine("style: {0} pw: '{1}' (len={2})", style, PW, PW.Length)
Next
Sample output:
示例输出:
style: Upper pw: 'QFHGPLIEEYPRP' (len=13)
style: All pw: 'Z9Y3CoW' (len=7)
style: Lower pw: 'tyghanjzudhhorfmvjr' (len=19)
style: All pw: 'XyY3q10N6S' (len=10)
style: Upper pw: 'IOZGTTQTPCYLKGEFRZ' (len=18)
style: All pw: '7t5CNMUM0GdWb' (len=13)
style: Upper pw: 'YIFXHRKEICOHXEUX' (len=16)
样式:上密码:'QFHGPLIEEYPRP'(len=13)
样式:所有密码:'Z9Y3CoW'(len=7)
样式:下密码:'tyghanjzudhhorfmvjr'(len=19)
样式:所有密码:'XyY3q10N6S'(len= 10)
样式:上密码:'IOZGTTQTPCYLKGEFRZ'(len=18)
样式:所有密码:'7t5CNMUM0GdWb'(len=13)
样式:上密码:'YIFXHRKEICOHXEUX'(len=16)
Then, the helper to shuffle (which is somewhat optional):
然后,洗牌的助手(这在某种程度上是可选的):
' Standared FY shuffle for List(Of T)
Public Sub Shuffle(Of T)(items As List(Of T), rnd As Random)
Dim temp As T
Dim j As Int32
For i As Int32 = items.Count - 1 To 0 Step -1
' Pick an item for position i.
j = rnd.Next(i + 1)
' Swap them.
temp = items(i)
items(i) = items(j)
items(j) = temp
Next i
End Sub
The big problem is that no one can remember such passwords, so they get taped to the monitor or bottom of the keyboard. A better method is to let the user pick the PW and just verify that it conforms to whatever rules by checking the string they choose for length and content. This would allow my~MuffyDoodle123or some such that the user can remember. Perhaps force them to change it periodically and maybe add a TrashCanto store old PWs by user so they cannot reuse the same one within 6 or 9 months.
最大的问题是没有人能记住这样的密码,所以它们被贴在显示器或键盘底部。更好的方法是让用户选择 PW 并通过检查他们选择的字符串的长度和内容来验证它是否符合任何规则。这将允许my~MuffyDoodle123或一些使得用户可以记住。也许迫使他们定期更改它,也许添加一个TrashCan用户存储旧 PW,以便他们无法在 6 或 9 个月内重复使用相同的 PW。
A way to auto-generate memorable PWs is using words. Create a list of several thousand adjectives and adverbs and another list of a few thousand nouns (easier than it sounds - there are online generators), you can create alliterative combinations plus a special character:
一种自动生成令人难忘的 PW 的方法是使用单词。创建一个包含数千个形容词和副词的列表以及另一个包含数千个名词的列表(比听起来容易 - 有在线生成器),您可以创建头韵组合加上一个特殊字符:
Rancid3Rain
Withered$Whisper
Creamy/Cotton
Enduring/Empire
Maximum7Mist
Greasy/Glory
Vaporized_Vision
Toxic!Tears
Angry!Abacus
Rancid3Rain
枯萎$耳语
奶油/棉
持久/帝国
Maximum7Mist
油腻/荣耀
Vaporized_Vision
有毒!泪
愤怒!算盘
The "hard" part is to use a centralized list and discard words as they are used so there can be no repeated words in generated passwords. Only when one of the queues is getting low do you start over.
“难”部分是使用集中列表并在使用时丢弃单词,因此生成的密码中不会有重复的单词。只有当其中一个队列变少时,您才能重新开始。
回答by TGamer
Try:
尝试:
Here is the basic idea. If you want upper and lower case letters, then add the lower case letters to the string s.
这是基本思想。如果需要大写和小写字母,则将小写字母添加到字符串 s 中。
Sub Main()
Dim s As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
Dim r As New Random
Dim sb As New StringBuilder
For i As Integer = 1 To 8
Dim idx As Integer = r.Next(0, 35)
sb.Append(s.Substring(idx, 1))
Next
Console.WriteLine(sb.ToString())
Console.ReadKey()
End Sub
And this should replace all your old code
这应该替换你所有的旧代码
回答by Hannington Mambo
Below is my shot at it. It works well for me so I believe it will for you, too. It ensures your password has a mix of the 4 categories, ie:
下面是我的拍摄。它对我很有效,所以我相信它也适用于你。它确保您的密码混合了 4 个类别,即:
- Upper case
- Lower case
- Numeric
- Special Characters
- 大写
- 小写
- 数字
- 特殊的角色
Minimum password length is 6 characters.
最小密码长度为 6 个字符。
The first section picks a character from each of the 4 categories. Then the loop runs for the rest of the remaining number of characters required. Since the first 4 will be in the order of the listed categories, there is a shuffle code added after generating the password that performs random shuffling, therefore improving the randomness of the password.
第一部分从 4 个类别中的每个类别中选择一个字符。然后循环运行剩余所需的剩余字符数。由于前4个会按照列出的类别排序,所以在生成密码后添加了shuffle code进行随机shuffle,从而提高了密码的随机性。
Public Function GeneratePassword(Optional ByVal Len As Integer = 8)
If Len < 6 Then
MsgBox("Minimum password length is 6 characters", MsgBoxStyle.OkOnly, "Minimum Length Reset")
Len = 6
End If
Dim pass As String = String.Empty
Dim nums As String() = "2 3 4 5 6 7 8 9".Split(" ") 'Omit 1 & 0
Dim lettU As String() = "A B C D E F G H J K L M N P Q R S T U V W X Y Z".Split(" ") 'Omit i,I,o & O
Dim lettL As String() = "A B C D E F G H J K M N P Q R S T U V W X Y Z".ToLower.Split(" ") 'Omit i,I,l, L,o & O
Dim chars As String() = "(-) @ # $ % * {-} [-] - _ ^ < > + = ~ /\".Split(" ") 'omit ? / \ ( ) ' " . , ; : &
Dim passRan() As Array = {nums, lettU, lettL, chars}
Dim min As Integer = 0
Dim max As Integer = passRan.Length 'this will include the length
Dim rnd As Integer = 0
Dim sb As New List(Of String)
For l As Integer = 0 To Len - passRan.Length - 1
'select the set to pick from ensuring you have a character from each set
If l = 0 Then
For p As Integer = 0 To passRan.Length - 1
'pick a random position in the selected set
max = passRan(p).Length
rnd = GetRandom(min, max)
sb.Add(passRan(p)(rnd))
Next
End If
'select the set to pick from by random
max = passRan.Length
rnd = GetRandom(min, max)
For p As Integer = 0 To passRan.Length - 1
'pick a random position in the selected set
If p = rnd Then
max = passRan(p).Length
rnd = GetRandom(min, max)
sb.Add(passRan(p)(rnd))
Exit For
End If
Next
Next
'shuffle the result
Dim R As New List(Of String)
R = sb.ToList
For Int As Integer = 0 To Len - 1
Dim curr As Integer = GetRandom(min, R.Count)
pass &= R(curr)
R.RemoveAt(curr)
Next
Return pass
End Function
Public Function GetRandom(ByVal Min As Integer, ByVal Max As Integer) As Integer
Static Generator As System.Random = New System.Random()
Return Generator.Next(Min, Max)
End Function
NB: To increase the number of available special characters, and complexity, I have used (-), [-] and {-} because they are difficult to read on their own, but may also be difficult if combined without a space in between. I also usually prefer to omit OoiIlL01 from my passwords to reduce confusion.
注意:为了增加可用特殊字符的数量和复杂性,我使用了 (-)、[-] 和 {-},因为它们本身很难阅读,但如果组合起来没有空格,也可能很困难. 我通常也喜欢从我的密码中省略 OoiIlL01 以减少混淆。

