2016-11-17 14 views
19

इस प्रश्न से पहले पूछा गया है और अभी भी एक जवाब की कमी है, जहां तक ​​मैं देख सकता हूं। इसलिए मैं इस सवाल का फिर से जवाब देने के लिए इस प्रश्न को फिर से पूछ रहा हूं। (यदि मैं गलत हूं तो कृपया मुझे उत्तर का यूआरएल दें।)उपयोगकर्ता के प्रत्येक चरित्र के लिए तारांकन मुद्रित करने के साथ पाइथन में पासवर्ड इनपुट कैसे किया जा सकता है?

समस्या: प्रोग्रामर उपयोगकर्ता चाहते हैं कि वे पासवर्ड इनपुट करें। गेटपास() फ़ंक्शन इस उद्देश्य के लिए अच्छा है, लेकिन इसके उपयोग में कमी है: पासवर्ड दर्ज करते समय stdout पर मुद्रित नहीं किया गया है।

प्रश्न: कैसे एक getpass() जबकि तारक एक उपयोगकर्ता द्वारा टाइप हर चरित्र के लिए मुद्रित कर रहे हैं लागू किया जा सकता? (बेशक बैकस्पेस - और आदर्श pos1 और अंत - देखभाल के हिसाब से लिया जाना चाहिए।)

प्रेरणा: समुदाय में किया गया है लोगों को समझ नहीं क्यों यह प्रश्न पूछा गया है। और उसके बाद गेटपास() को संदर्भित किया गया है) इस तरह से कार्य को अनदेखा कर रहा है और बी) इस बारे में सोचने के बिना कि संदर्भ प्रश्न का उत्तर नहीं देगा। कारण एसओ शायद उपयोगकर्ताओं की सुविधा के लिए मुद्रित तारांकन करना चाहते हैं: पासवर्ड इनपुट के दौरान उन्हें प्रत्यक्ष दृश्य प्रतिक्रिया मिलती है। इसलिए वे कुंजियों को दबाकर उलझन में नहीं आते हैं - और वहां आंखों के लिए - कुछ भी नहीं हो रहा है।

एक समाधान की दिशा में एक कदम:

मुझे एक समाधान यहाँ दिशा में पहले कदम को पेश करते हैं। वास्तविक समाधान में इसे विकसित करने के लिए कृपया मदद करें।

getch जो stdin से वर्ण दर वर्ण पढ़ने की अनुमति देने के लिए लगता है नाम के एक मॉड्यूल है। बैकस्पेस है - काफी अजीब - 127 के एक पूर्णांक मान पर मैप, लेकिन इस तरह के एक समाधान तो ऐसा दिखाई दे सकता:

def readLineWithAsterisks(): 
    sBuffer = '' 
    while True: 
     c = getch.getch() 
     if c == '\n': 
      return sBuffer 
     elif ord(c) == 127: 
      if len(sBuffer) > 0: 
       sys.stdout.write('\x08 \x08') 
       sys.stdout.flush() 
       sBuffer = sBuffer[0:-1] 
      continue 
     else: 
      sys.stdout.write('*') 
      sys.stdout.flush() 
      sBuffer += c 

लेकिन इस कोड कुछ कमियां हैं। सबसे पहले मैं सी के बारे में बहुत उलझन में हूं, तो 'b' नहीं होने पर s.o. बैकस्पेस दर्ज किया गया। संभावित हो। इसके लिए एक स्पष्टीकरण है? लिनक्स पर कम से कम ASCII वर्णों को संसाधित किया जाता है। मुझे विंडोज़ के बारे में पता नहीं है, लेकिन अगर ए-जेड 0 9 के अलावा कोई चरित्र दबाया जाता है, तो लाइन सी = getch.getch() एक अपवाद फेंक देगा। getch() कम से कम कुछ हद तक उमलॉट्स और अन्य प्रकार के पात्रों को संसाधित करने में सक्षम प्रतीत नहीं होता है।

समाधान इनपुट के लिए आते हैं निम्नलिखित मुद्दों को संबोधित किया जाना चाहिए:

  • कैसे stdin से पठन गैर- ASCII वर्ण के संबंध में वर्ण दर वर्ण किया जा कर सकते हैं?
  • प्लेटफ़ॉर्म स्वतंत्र तरीके से यह कैसे किया जा सकता है?
  • यह सुरक्षित तरीके से कैसे किया जा सकता है (सुरक्षा समस्याओं के बिना)?(getpass किसी भी तरह इस संबोधित करने के लिए लगता है, लेकिन मैं पूरी तरह से कैसे समझ में नहीं आता।)

हो सकता है कि कोई भी इस बारे में जानता है। मेरे ज्ञान के लिए इस तरह के प्रश्नों से पहले पूछा गया कि अनुत्तरित रहे। लेकिन हो सकता है कि समुदाय में कुछ सॉफ्टवेयर डेवलपर्स इस बारे में और जान सकें और यहां मदद कर सकते हैं? सफलता पर मैं गिटहब पर एक पाइथन मॉड्यूल के रूप में प्रदान किया गया समाधान प्राप्त कर सकता हूं।

उत्तर

-1

शायद टिंकर का उपयोग करना आसान है, हालांकि शायद सुरक्षित नहीं है, यह सबसे नज़दीकी है जो मैं आपसे पूछ रहा हूं।

from tkinter import * 
from tkinter import ttk 

root = Tk() 
parent = ttk.Frame(root) 
parent.grid() 

password = ttk.Entry(parent, show="*").grid()#shows each character as an asterix 

root.mainloop() 

क्षमा करें मैं और अधिक मदद नहीं कर सका।

0

आप यह नुस्खा के रूप में यह MSVCRT lib का उपयोग करता है अपने खुद के मंच स्वतंत्र समाधान
http://code.activestate.com/recipes/134892/

खिड़कियों के मामले में लिए एक प्रारंभिक बिंदु के रूप में उपयोगी मिल सकता है। आप यूनिकोड को संसाधित करने में सक्षम होने के लिए getwch() को getch() पर कॉल को प्रतिस्थापित कर सकते हैं।

ActivePython 2.7.10.12 (ActiveState Software Inc.) based on 
Python 2.7.10 (default, Aug 21 2015, 12:07:58) [MSC v.1500 64 bit (AMD64)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import msvcrt 
>>> msvcrt.getch() 
'j' 
>>> msvcrt.getch() 
'r' 
>>> msvcrt.getch() 
'?' 
>>> msvcrt.getwch() 
u'\u0432' 
1

नोट: मेरे अन्य जवाब को Python2 कोड काम कर रहा होता है मंच स्वतंत्र ढंग से ऐसा करने के लिए।

सुरक्षित प्लेटफॉर्म स्वतंत्र तरीका getpass.getpass() के समान सब कुछ सेट करेगा, इसलिए स्रोत (/usr/lib/python2.7/getpass.py मेरे लिए) देखें; यह बहुत सीधे आगे है।

सितारों गूंज के लिए के रूप में ...

win_getpass() पहले से ही चार से चार पढ़ रही है, सिर्फ इतना है कि पाश में कुछ * गूंज। आपको msvcrt.getch() के बजाय msvcrt.getwch() का उपयोग करने की आवश्यकता हो सकती है, लेकिन इसका मतलब यह होगा कि पाइथन getpass मॉड्यूल में एक बग है।

unix_getpass() ट्रिकियर है। टर्मिनल के लिए आपको cbreak सेटअप करने की आवश्यकता है जैसे ECHO पहले से अक्षम किया जा रहा है (https://utcc.utoronto.ca/~cks/space/blog/unix/CBreakAndRaw देखें)। आपको readline() के बजाय _raw_input() के बजाय एक लूप में read(1) का उपयोग करना होगा (win_getpass() के समान)।

एक बार जब आप बाइट द्वारा बाइट पढ़ रहे हैं, तो आप "अक्षर" का निर्धारण करने के दर्द के माध्यम से जा सकते हैं। यह एन्कोडिंग पर निर्भर करता है और लंबाई में भी परिवर्तनीय हो सकता है (यूटीएफ -8 के मामले में)।

+0

"यह बहुत सीधी-सपाट है" - नहीं, नहीं वास्तव में :-) क्षमा करें, लेकिन नहीं हर कोई TTYs और उनके सभी विशेषताओं के बारे में हर विस्तार जानता है :-) - और पढ़ने (1) कि उपयोगी नहीं है : जहां तक ​​मैंने पाइथन में एसटीडीआईएन सीखी है, लाइन द्वारा लाइन को संभाला जाता है। यह मौलिक समस्याओं में से एक है। फिर भी मैं आपके द्वारा दी गई अन्य जानकारी में एक नज़र डालेगा। इनमें से कुछ वास्तव में उपयोगी प्रतीत होता है। आपका बहुत बहुत धन्यवाद! –

+0

एसटीडीआईएन की लाइनवाई हैंडलिंग एक मौलिक पायथन समस्या नहीं है; टीटीई पारंपरिक रूप से लाइन-एडिटिंग क्लाइंट-साइड करने की अनुमति देने के लिए लाइन-बफर किए जाते हैं। साथ ही, पढ़ना (1) बेहद उपयोगी है जब आपको एक बाइट पढ़ने की आवश्यकता होती है। –

1

आप यह देखना चाहते हैं कि jupyter/ipython ने इसे कैसे कार्यान्वित किया। मुझे getpass() का उपयोग करके टाइप किए गए प्रत्येक वर्ण के लिए तत्काल प्रदर्शित एक डॉट मिल रहा है।

enter image description here

+0

धन्यवाद, मैं इसे देख लूंगा। –

+0

मुझे डॉट्स नहीं मिल रहा है, जबकि मैं उपरोक्त का उपयोग कर पाइथन में अपना पासवर्ड टाइप करता हूं ... –

+0

@ nabin-info आपके सेटअप में कुछ गलत है - मैं jupyter 4.2.3 का उपयोग कर रहा हूं। मैंने gif एनीमेशन के साथ अपना जवाब अपडेट किया। – denfromufa

0

मैं एक मॉड्यूल मोटे तौर पर वर्णन करने के लिए आप इसे कैसे मंच स्वतंत्र रूप से कर लिखा था।

#!/usr/bin/python2 

def _masked_input_unix(prompt="Password: ", mask="*"): 
    pw = "" 
    # save terminal settings 
    fd = sys.stdin.fileno() 
    old = termios.tcgetattr(fd) 
    new = termios.tcgetattr(fd) 
    # setup 'cbreak' mode 
    new[3] = new[3] & ~termios.ECHO 
    new[3] = new[3] & ~termios.ICANON 
    new[6][termios.VMIN] = '\x01' 
    new[6][termios.VTIME] = '\x00' 
    try: 
     termios.tcsetattr(fd, termios.TCSADRAIN, new) 
     print prompt, 
     # Read the password 
     while True: 
      c = sys.stdin.read(1) 
      # submit chars 
      if c == '\r' or c == '\n': 
       sys.stdout.write("%s" % (c)) 
       break 
      # delete chars 
      elif c == '\b' or c == '\x7f': 
       if len(pw) > 0: 
        pw = pw[:-1] 
        sys.stdout.write("%s" % ('\b \b')) 
      # password chars 
      else: 
       pw += c 
       sys.stdout.write("%s" % (mask)) 
    finally: 
     # ensure we reset the terminal 
     termios.tcsetattr(fd, termios.TCSADRAIN, old) 
    return pw 

def _masked_input_win(prompt="Password: ", mask='*'): 
    pw = "" 
    while True: 
     c = msvcrt.getch() 
     # submit chars 
     if c == '\r' or c == '\n': 
      while msvcrt.kbhit(): 
       msvcrt.getch() 
      print 
      break 
     elif c == '\x03': 
      raise KeyboardInterrupt 
     # delete chars 
     elif c == '\b' or c == '\x7f': 
      if len(pw) > 0: 
       pw = pw[:-1] 
       msvcrt.putch('\b') 
       msvcrt.putch(' ') 
       msvcrt.putch('\b') 
     # password chars 
     else: 
      pw += c 
      msvcrt.putch(mask) 
    return pw 

## initialize windows or posix function pointer 
masked_input = None 
try: 
    import msvcrt 
    masked_input = _masked_input_win 
except ImportError: 
    import sys, termios 
    masked_input = _masked_input_unix 

if __name__ == "__main__": 
    p = masked_input() 
    print "Password is:", p 

और यह एकल-बाइट एन्कोडिंग के लिए काम करता है। यूनिकोड समर्थन जोड़ना गैर-तुच्छ है। मुझे संदेह है कि यूनिकोड विंडोज पर getpass मॉड्यूल के साथ अच्छी तरह से काम नहीं करता है।

4

वहाँ पहले उत्तर देखें: (ध्यान दें यह यूनिकोड तार करने के लिए सब कुछ बदल रहा है और getwch() का उपयोग कर के रूप में सरल नहीं है):

What's the simplest way of detecting keyboard input in python from the terminal?

बस प्रिंट सितारों '*' या कुछ भी जब एक कुंजी दबाने ।

सभी क्रेडिट स्पष्ट रूप से शोध के लिए फिलीएडा जाते हैं।

1

यह लिनक्स केवल संस्करण है, पाइथन 2 और पायथन 3 में यूनिकोड समर्थन के साथ काम करता है।

यूनिकोड वर्ण लिखने के लिए, एक साथ Ctrl+Shift पकड़ और टाइप u और जारी Ctrl+Shift, अब कोडपॉइंट और <Enter> टाइप करें।

मैं विशेष रूप से os.read और os.write funcitons का उपयोग बाईपास (libc और पायथन आईओ) बफरिंग मुद्दों और कर्नेल से बाइट पढ़ने के लिए करता हूं।

टर्मिनल किल (^ यू), ईआरएसईई (एएससीआई डीएल उर्फ ​​Backspace कुंजी), ईओएफ (^ डी) और एएससीआई बीएस (\b) समर्थित हैं।

मैं पासवर्ड पढ़ने के दौरान SIGTSTP को अनदेखा करता हूं, क्योंकि पृष्ठभूमि टाइप किए गए वर्णों से पुन: शुरू होने पर प्रतिबिंबित किया जाता है।

import tty 
import os 
import sys 
import signal 
from array import array 

# disable (^Z) SIGTSTP 
signal.signal(signal.SIGTSTP, signal.SIG_IGN) 
stdin = sys.__stdin__.fileno() 
stream = sys.__stderr__.fileno() 
old = tty.tcgetattr(stdin) 
os.write(stream, b"Passwd: ") 
try: 
    tty.setcbreak(stdin) 
    passwd = array("u") 
    while True: 
     # UTF-8 is 4 octets (bytes) at max 
     c = os.read(stdin, 4) 
     # ERASE ascii DEL (0x7f) <Backspace> and ascii BS (0x08) <^H> 
     if c in (old[tty.CC][tty.VERASE], b"\b"): 
      if passwd: 
       os.write(stream, b"\b \b") 
       passwd.pop() 
     # KILL ascii NAK (0x15) <^U> 
     elif c == old[tty.CC][tty.VKILL]: 
      if passwd: 
       os.write(stream, b"\b \b" * len(passwd)) 
       passwd = array("u") 
     # ascii LF (0x0a) <^J>, CR (0x0d) <^M> and <Enter> and EOT (0x04) <^D> 
     elif c in (b"\n", old[tty.CC][tty.VEOF]): 
      break 
     else: 
      #c = c.decode('utf-8') 
      c = c.decode(sys.__stdin__.encoding) 
      passwd.append(c) 
      os.write(stream, b"*") 
finally: 
    # restore terminal settings 
    tty.tcsetattr(stdin, tty.TCSAFLUSH, old) 
    # enable (^Z) SIGTSTP 
    signal.signal(signal.SIGTSTP, signal.SIG_DFL) 
    os.write(stream, b"\n") 

print(passwd.tounicode()) 

टेस्ट;

$ # To input "Þàsswõrd" 
$ # U+00de, U+00e0, s,s, w, U+00f5, r, d 
$ python getpass.py 
$ Passwd: ******** 
Þàsswõrd 
संबंधित मुद्दे

 संबंधित मुद्दे