Comment générer une chaîne de caractères aléatoires en Ruby
Je suis en train de générer un 8-caractère pseudo-aléatoire en majuscules chaîne pour "A" .. "Z":
value = ""; 8.times{value << (65 + rand(25)).chr}
mais il n'a pas l'air propre, et il ne peut pas être passé comme argument car il n'est pas un état unique. Pour obtenir un casse mixte chaîne "a" .. "z" plus "A" .. "Z", je l'ai changé pour:
value = ""; 8.times{value << ((rand(2)==1?65:97) + rand(25)).chr}
mais il semble comme une poubelle.
Quelqu'un aurait-il une meilleure méthode?
- Je ne comprends pas pourquoi vous vous souciez que "comme il n'est pas un état unique, il ne peut pas être passé comme argument". Pourquoi ne pas simplement faire un utilitaire ou de la méthode d'assistance?
- Supposons qu'il existe une méthode pour réinitialiser le mot de passe et il a un argument pour le nouveau mot de passe. Je voudrais passer une chaine de caractère aléatoire, dans le code ci-dessus j'ai besoin d'une variable tmp, alors que dans la seule déclaration des exemples soufflet je peux faire la chose entière comme une seule ligne. Assurez-vous un utilitaire méthode pourrait être sympa dans le long terme, esp si je suis besoin de semblable ici et là, mais parfois vous voulez juste en place, un temps, fait.
- Non, vous n'avez pas à utiliser une variable temporaire. Essayez ceci:
reset_user_password!(random_string)
oùdef random_string; SecureRandom.urlsafe_base64(20) end
- 8 lettres est un honteusement mot de passe faible. Compte tenu de la somme md5 d'un PC moderne pourrait récupérer le mot de passe dans 30 secondes. Comment parler de quelque chose de plus
securerandom.urlsafe_base64
- Lol, ok qui a été posée en 2008, assurez-vous permet de bosse qui jusqu'à 15 ou plus.
- Pourquoi est-ce que avez tellement de nombreuses réponses? Pas qu'il n'est pas utile, mais je suis curieux de voir comment il a attiré l'attention.
- bien, mettre un webdesigner en face de VIM et de lui demander d'enregistrer et de sortie; Blagues à part.
require 'securerandom'; SecureRandom.hex(15)
devrait fonctionner correctement
Vous devez vous connecter pour publier un commentaire.
Je passe trop de temps au golf.
Et un dernier qui est encore plus déroutant, mais plus souple et les déchets, moins de cycles:
(0...8).map{(65+rand(25)).chr}.join
. épargné un char..('a'..'z').to_a.shuffle[0,8].join
. Remarque: vous aurez besoin de Ruby >=1,9 àshuffle
.SecureRandom
comme un exemple, dans les autres réponses.[].fill(0,l){rand(65..90).chr}.join
(35 caractères).fill
est plus rapide quemap
, mais pour de vrai la performance, la baisse de la golf et de pré-créer le tableau avec une bon utilisation desample
:chars=["A", "B", "C", "D", "E", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"];[].fill(0,l){chars.sample}.join
Qui n'est même pas significativement plus rapidement pour 8 caractères. Avec 8 caractères, pas de soucis. Rien de mouches. 😉 Voir mon indicateurs pour plus de détails.[*('a'..'z'),*('0'..'9')].shuffle[0,8].join
pour générer une chaîne de caractères aléatoires, avec à la fois des lettres et des chiffres.rand
est déterministe et prévisible. Ne pas l'utiliser pour générer des mots de passe! Utilisez l'une desSecureRandom
des solutions à la place.(0...50).map { [('a'..'z'),('A'..'Z')].flat_map(&:to_a).sample }.join
vous avez certainement n'ont pas passé aussi beaucoup de temps au golf xD(0..50).map { [*'a'..'z',*'A'..'Z'].sample }.join
RandomString
résumant les trois principales techniques mentionnées dans toutes les réponses: gist.github.com/jopotts/8706578shuffle
ne serait pas génial, comme ils avaient générer des chaînes de caractères avec la première occurrence d'un caractère ( de sorte chaîne telle que "gbalgqut" serait impossible - double "g" )('a'..'z')
est identique à(?a..?z)
; deux personnages sauvés.Pourquoi ne pas utiliser SecureRandom?
SecureRandom a aussi des méthodes pour:
voir: http://ruby-doc.org/stdlib-1.9.2/libdoc/securerandom/rdoc/SecureRandom.html
require 'securerandom'
pour obtenir cette soignéSecureRandom
helper 🙂SecureRandom.base64 => "7p0lfNClJwolM9BJcgG5lQ=="
comme vous le voyez, il y a=
en elle. Méthode hex ne renvoie0-9a-f
SecureRandom.random_number(36**12).to_s(36).rjust(12, "0")
va générer une chaîne de 0-9a-z (36 caractères) qui est TOUJOURS de 12 caractères de long. Changement de 12 à n'importe quelle longueur que vous souhaitez. Malheureusement aucun moyen de tout de A à Z à l'aide deInteger#to_s
.+fGH1
par le biais d'une URL, il vous suffit d'encoder avec elle comme vous le feriez pour n'IMPORTE quelle valeur qui va au moyen d'une URL:%2BfGH1
SecureRandom.hex.gsub(/\d/, "")[0..4]
- Je l'utiliser pour la génération aléatoire URL amicale des chaînes de caractères avec une garantie de longueur maximale:
Il génère aléatoirement des chaînes de lettres minuscules a-z et 0-9. Ce n'est pas très personnalisable, mais elle est courte et propre.
rand.to_s
; laid, mais il fonctionne.length
longueur, environ une fois tous les ~40(36**(length-1) + rand(36**length)).to_s(36)
. 36**(longueur-1) converti en base 36 10**(longueur-1), qui est la plus petite valeur qui a la longueur de chiffres que vous voulez.length
.(36**(length-1) + rand(36**length - 36**(length-1))).to_s(36)
NameError: undefined local variable or method
de la longueur pour les principales:l'Objet"while true do v = rand(36 ** 2); l = v.to_s(36).length; if l > 2 then puts v end end
Random.new.rand( 36**(length-1) ... 36**length ).to_s( 36 )
( rand * (36**length - 36**(length-1) ) + 36**(length-1) ).floor.to_s( 36 )
. Ce n'est pas aussi lisible, donc je voudrais le mettre dans une fonction. Probablement le plus simple serait de créer quelque chose qui est garanti pour être long, et puis de le tronquer.rand(36**11).to_s(36).upcase[0,6]
c'est à dire juste faire de la chaîne d'origine en toute sécurité assez longtemps et puis prendre tous les N caractères à partir de ceCette solution génère une chaîne de caractères facilement lisibles pour les codes d'activation; je ne veux pas que les gens confus 8 avec B, 1 avec I, 0 O, L, 1, etc.
charset.sample
au lieu decharset.to_a[rand(charset.size)
?SecureRandom.random_number(charset.size)
au lieu derand(charset.size)
%w{ A C D E F G H J K L M N P Q R T W X Y Z 2 3 4 6 7 9 ! @ # $ % ^ & * +}
et%w{ A D E F G H J L N Q R T Y a d e f h n r y 2 3 4 7 ! @ # $ % ^ & * }
(première liste n'inclut pas de casse, mais c'est plus long) Plutôt intéressant de voir comment ça a fonctionné.D'autres ont mentionné quelque chose de similaire, mais il utilise l'URL de la fonction de sécurité.
Le résultat peut contenir des A-Z, a-z, 0-9, “-” et “_”. “=” est également utilisé si le rembourrage est vrai.
La génération aléatoire de 8 chaîne de caractères (par exemple, NVAYXHGR)
La génération aléatoire de 8 caractères chaîne de caractères (par exemple 3PH4SWF2), exclut 0/1/I/O. Ruby 1.9
[*("A".."Z")]'
; ((pas unique qoutes))stub
ce pourrspec
à passer.Depuis ruby 2.5 vraiment facile avec
SecureRandom.alphanumeric
:Génère aléatoirement des chaînes contenant A-Z, a-z et 0-9 et devrait donc être applicable dans la plupart des cas d'utilisation. Et ils sont générés de manière aléatoire sécurisée, ce qui peut être un avantage, trop.
Edit: Un indice de référence à comparer avec la solution ayant le plus upvotes:
De sorte que le
rand
solution ne prend environ 3/4 du temps deSecureRandom
. Peut importe si vous générez vraiment beaucoup de chaînes, mais si vous venez de créer une certaine chaîne de caractères aléatoires de temps en temps j'avais toujours aller avec le plus d'assurer la mise en œuvre (puisqu'il est également plus facile d'appeler et de plus explicite).Je ne me souviens pas où j'ai trouvé ceci, mais il me semble que la meilleure et la moins intensives pour moi:
0
et1
etO
etI
été volontairement absente parce que ces personnages sont ambigus. Si ce genre de code est utilisé pour générer un jeu de caractères qu'un utilisateur a besoin de copier, il est préférable d'exclure des caractères qui peuvent être difficiles à distinguer de leur contexte.Random.new.bytes(9)
n=9 ; SecureRandom.urlsafe_base64(n)[0..n-1]
Si vous voulez une chaîne de caractères de longueur spécifiée, utilisez:
Il va générer une chaîne aléatoire de longueur
2n
contenant0-9
eta-f
n
, il génère une chaîne de 4/3 den
.Array.new(n){[*"0".."9"].sample}.join
,où n=8 dans votre cas.
Généralisée:
Array.new(n){[*"A".."Z", *"0".."9"].sample}.join
, etc. - à partir de cette réponseVoici une ligne de code simple pour chaîne aléatoire avec une longueur de 8
Vous pouvez également l'utiliser pour le mot de passe aléatoire ayant la longueur 8
j'espère que ça aidera et étonnant.
P(36, 8) / 36^8 = 0.4
du possible le caractère de l'espace pour 8 caractères (~2x plus facile à la force brute) ouP(36, 25) / 36^25 = 0.00001
de l'éventuel caractère d'espace pour les 25 caractères (~100.000 x plus facile à la force brute).Ruby 1.9+:
map
solution est vraiment sympa!#sample
pour la façon dont beaucoup d'éléments que vous le souhaitez. E. g.ALPHABET.sample(10).join
... ruby-doc.org/core-2.4.0/Array.html#method-i-samplesample(10)
vous donne 10 échantillons uniques. Mais vous voulez leur permettre de répéter. Mais je voudrais utiliserArray.new(10).map
pour la performanceArray.new
et son bloc de syntaxe.Array.new(20) { [*'0'..'9', *'a'..'z', *'A'..'Z'].sample }.join
Ici est un simple code de mot de passe aléatoire avec lenth 8
Espère que ça va aider.
Être conscient:
rand
est prévisible pour un attaquant et donc probablement d'insécurité. Vous devriez certainement utiliser SecureRandom si c'est pour générer des mots de passe. J'utilise quelque chose comme ceci:Une autre méthode, je tiens à utiliser
Ajouter ljust si vous êtes vraiment paranoïaque à propos de la bonne longueur de la chaîne:
Quelque chose de Concevoir
.tr('+/=lIO0', 'pqrsxyz')
?Je pense que c'est un bon équilibre de la concision, la clarté et la facilité de modification.
Facilement modifié
Par exemple, y compris les chiffres:
Majuscules hexadécimal:
Pour un impressionnant tableau de caractères:
Juste ajouter ma cents ici...
rand
vous pouvez utiliser
String#random
des Facettes de Ruby Gemfacets
:https://github.com/rubyworks/facets/blob/126a619fd766bc45588cac18d09c4f1927538e33/lib/core/facets/string/random.rb
il fait ceci:
Mon préféré est
(:A..:Z).to_a.shuffle[0,8].join
. Notez que shuffle nécessite Ruby > 1.9.Cette solution doit dépendance externe, mais semble plus jolie que l'autre.
Faker::Lorem.characters(10) # => "ang9cbhoa8"
Donné:
Simple expression, peut-être passé comme argument, permet à des personnages en double:
Je faisais quelque chose comme ça récemment pour générer de 8 octets chaîne de caractères aléatoires à partir de 62 caractères. Les personnages sont 0-9,a-z,A-Z, j'ai eu un tableau d'entre eux comme ce fut le bouclage 8 fois et choisir une valeur aléatoire de la matrice. C'était à l'intérieur d'une application rails.
str = ''
8.times {|i| str << ARRAY_OF_POSSIBLE_VALUES[rand(SIZE_OF_ARRAY_OF_POSSIBLE_VALUES)] }
La chose étrange est que j'ai eu bon nombre de doublons. Maintenant, au hasard, cela devrait assez bien ne jamais arriver. 62^8 est énorme, mais en dehors de 1200 codes de la bd, j'ai eu un bon nombre de doublons. J'ai remarqué qu'elles se sur-heure limites de chacune des autres. En d'autres termes, je pourrais voir un double à 12:12:23 2:12:22 ou quelque chose comme ça...vous ne savez pas si le temps est de la question ou non.
Ce code a été à l'avant de créer un activerecord objet. Avant la création de l'enregistrement de ce code s'exécuter et de générer l' 'unique' code. Les entrées dans la base de données ont toujours produit de manière fiable, mais le code (str dans la ligne ci-dessus) a été dupliqué beaucoup trop souvent.
J'ai créé un script à exécuter par le biais de 100000 itérations de cette ligne ci-dessus avec un peu de retard alors qu'il faudrait 3 à 4 heures dans l'espoir de voir une sorte de répétition du motif sur une base horaire, mais ne vit rien. Je n'ai aucune idée de pourquoi ce qui se passe dans mon application rails.
Mes 2 cents:
Je viens d'écrire un petit bijou
random_token
pour générer des jetons pour la plupart des cas d'utilisation, profitez de ~https://github.com/sibevin/random_token
Avec cette méthode, vous pouvez passer d'un abitrary longueur. Il est défini comme un défaut 6.
J'aime Radar de répondre le mieux, jusqu'à présent, je pense. Je voudrais modifier un peu comme ceci:
(CHARS*length).sample(length).join
?CHARS=['a','b']
ensuite votre méthode de générer"aa"
ou"bb"
seulement 33% du temps, mais"ab"
ou"ba"
67% du temps. Peut-être que ce n'est pas un problème, mais il en vaille la peine!Voici une autre méthode:
Besoins
require "securerandom"
essayer
J'aime les réponses du fil, ont été très utiles, en effet!, mais si l'on peut dire, aucun d'eux ne répond à ma voix pour, peut-être est le rand() la méthode. c'est juste ne semble pas bonne pour moi, depuis que nous avons obtenu le Tableau#choix de la méthode pour cette question.
Si vous êtes sur un UNIX, et vous devez toujours utiliser Ruby 1.8 (pas de SecureRandom) sans Rails, vous pouvez également utiliser cette:
Remarque cela engendre de nouveaux coquille, c'est très lent et il ne peut être recommandé pour les scripts.
Un autre truc qui fonctionne avec Ruby 1.8+ et est rapide est:
Il vous aléatoire chaîne hexadécimale. Même manière, vous devriez être en mesure de générer de la chaîne base64 ('M*').
De mon mieux, 2 solutions pour une chaîne aléatoire composé de 3 gammes de
Ceci est basé sur quelques autres réponses, mais il ajoute un peu plus de complexité:
Essentiellement, il assure un mot de passe qui est de 8 à 20 caractères, et qui contient au moins un chiffre et un caractère spécial.
Pour concevoir secure_validatable vous pouvez utiliser cette
(0...8).carte { ([65, 97].exemple de + rand(26)).chr }.push(rand(99)).rejoignez
random_ascii_character = -> { (33..126).to_a.sample.chr }; 8.times.map { random_ascii_character.call }.shuffle.join
La façon la plus simple est d'utiliser le string_pattern gem https://github.com/MarioRuiz/string_pattern
Par exemple pour générer 36 lettres aléatoires:
Aussi, vous pouvez utiliser des expressions régulières
Pour faire le premier dans une seule instruction:
Nous avons été à l'aide de notre code:
La longueur maximale prise en charge est de 25 (nous ne sommes que de l'utiliser avec la valeur par défaut de toute façon, ce n'est pas un problème).
Quelqu'un a mentionné que 'a'..'z' est sous-optimale si vous souhaitez éviter de générer les mots offensants. L'une des idées que nous avons eu a été de retirer les voyelles, mais vous avez encore jusqu'à la fin avec WTFBBQ etc.
Créer une chaîne vide ou un pré-corriger si besoin:
Utiliser ce code pour remplir la chaîne avec des nombres aléatoires:
Notes:
Il va générer des nombres aléatoires à partir de 48-91 (0,1,2..Y,Z)
Il est utilisé pour ignorer les caractères spéciaux (comme je ne suis pas intéressé à les inclure)
Il va générer un total de 12 caractères chaîne, y compris le préfixe.
Exemple De Sortie:
Voici une solution qui est flexible et permet de dup:
Exemple:
Vous pouvez également autoriser un certain caractère à apparaître plus fréquemment:
Explication:
La méthode ci-dessus prend les caractères d'une chaîne donnée et génère un assez grand tableau. Puis, il les mélange, prend les n premiers éléments, puis se joint à eux.
ou
Ici est d'améliorer de @Travis R réponse:
À @Travis R réponse caractères et les nombres étaient ensemble, donc parfois
random_string
pourrait revenir uniquement des chiffres ou que des personnages. Avec cette améliorer au moins la moitié derandom_string
sera caractères et le reste sont des nombres. Juste au cas où si vous avez besoin d'une chaîne de caractères aléatoires avec des numéros et des caractèresUtiliser 'SafeRandom" Gem GithubLink
Il fournira la meilleure façon de générer des valeurs aléatoires pour Rails2, Rails 3, Rails 4, Rails 5 compatible.
C'est presque aussi laid, mais peut-être l'étape dans la bonne direction?
En ruby 1.9, on peut utiliser la Matrice de choix de la méthode qui renvoie l'élément aléatoire à partir de la matrice de
Je ne sais pas ruby, donc je ne peux pas vous donner la syntaxe exacte, mais je voudrais définir une constante chaîne de caractères avec la liste des caractères acceptables, puis utilisez la sous-chaîne de l'opérateur de choisir un caractère aléatoire hors de lui.
L'avantage ici est que si la chaîne est censé être de l'utilisateur-enterable, alors vous pouvez exclure facile de confondre les personnages comme l et 1 et i, 0 et O, 5 et S, etc.