2010-07-22 22 views
8

Mô-đun pwd Python cung cấp quyền truy cập vào getpwnam(3) API POSIX, có thể được sử dụng để nhận thư mục chính cho một người dùng cụ thể theo tên người dùng, cũng như xác định xem tên người dùng có hợp lệ hay không. pwd.getpwnam sẽ tăng ngoại lệ nếu được gọi với tên người dùng không tồn tại.Tương đương với Windows của pwd.getpwnam (tên người dùng) .pw_dir là gì?

Lúc đầu, có vẻ như kết quả tương tự có thể đạt được theo cách đa nền tảng qua os.path.expanduser('~username'). Tuy nhiên, có vẻ như với Python 2.6 trên Windows XP, điều này sẽ không thực sự tạo ra lỗi cho một tên người dùng không tồn tại. Hơn nữa, trên Python 2.5 trên Windows XP, nó dường như thất bại ngay cả đối với người dùng hợp lệ.

Thông tin này có thể nhận được đáng tin cậy trên Windows không? Làm sao?

+1

Luôn yêu một "Python trên Windows" câu hỏi hay. Càng sớm chúng tôi mang đến sự khai ngộ cho nền tảng đó (nếu có thể), thì tốt hơn cho tất cả mọi người. –

+0

'~ user' không được phép làm việc trên 2.5, nó được thực hiện trong 2.6+ nhưng theo cách _broken_ - xem câu trả lời của tôi dưới đây để thực hiện làm việc. Có, đã phải nhìn trộm trong registry tôi sợ. –

Trả lời

4

Đọc 2.6 documentation cho thấy os.path.expanduser() được chia trên Windows:

Trên Windows, HOME và USERPROFILE sẽ được sử dụng nếu được đặt, nếu không, kết hợp của HOMEPATH và HOMEDRIVE sẽ được sử dụng. Người dùng ~ ban đầu được xử lý bằng cách tước thành phần thư mục cuối cùng từ đường dẫn người dùng được tạo ra ở trên được tạo ra ở trên .

Nói whaat? Điều này giả định tất cả các nhà người dùng phải ở trong cùng một thư mục cha. Nuh-ugh!

Đó là một chút khó khăn để đào nhưng đây là một giải pháp mà sẽ tìm kiếm một người dùng cục bộ theo tên đưa ra:

from win32security import LookupAccountName, ConvertSidToStringSid 
from _winreg import OpenKey, QueryValueEx, HKEY_LOCAL_MACHINE 

def getUserDir(userName): 
    ssid = ConvertSidToStringSid(LookupAccountName(None, userName)[0]) 
    key = OpenKey(HKEY_LOCAL_MACHINE, r'SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\\' + ssid) 
    return QueryValueEx(key, 'ProfileImagePath')[0] 
+1

điều này chỉ mang lại kết quả cho người dùng địa phương? – akira

+0

chỉ để làm rõ. – akira

+1

GetUserDir này có vẻ đầy hứa hẹn. Tôi đã thử nó trên vấn đề của tôi nhưng tiếc là ngay lập tức chạy vào một vấn đề mà mã của tôi đang chạy như một dịch vụ mà dường như không được ánh xạ tới một người dùng (bằng cách nào đó), vì vậy một trong các cuộc gọi không thành công (với một ngoại lệ phàn nàn về việc thiếu một bản đồ như vậy). Hiện tại tôi đã dừng lại ở đó, nhưng có lẽ tôi sẽ xem lại điều này tại một thời điểm nào đó. Có lẽ khi tôi thiết lập bất kỳ bản đồ nào là bắt buộc, chức năng này sẽ đáp ứng các yêu cầu. –

0

bạn có thể sử dụng tuyến đường win32api.GetUserName() (chỉ người dùng hiện tại) hoặc win32net.NetUserGetInfo() (bất kỳ người dùng nào trên máy chủ, máy chủ lưu trữ cục bộ). sau này có thể hơi chậm vì có thể mất chút thời gian để lấy lại thông tin này từ hệ điều hành.

import win32net 

    def userDir(username): 
     return win32net.NetUserGetInfo(None, username, 1).get("home_dir") 

cách khác bạn có thể mở rộng môi trường biến USERPROFILE trên cửa sổ hoặc HOME trên unix để có được thông tin về các hiện đang đăng nhập sử dụng:

def userDir(): 
     if os.platform.system() == 'Windows': 
      return os.environ['USERPROFILE'] 
     elif os.platform.system() == 'Linux': 
      return os.environ['HOME'] 
     else: 
      return None 
+0

Sẽ không hoạt động - thao tác này sẽ chỉ trả lại thông tin cho người dùng * hiện tại *. Câu hỏi là về * bất kỳ *, 'cụ thể' người dùng. –

+0

@Nas Banov: đúng, nhưng chỉ cho phần thứ hai của câu trả lời của tôi. win32api.NetUserGetInfo() truy xuất thông tin cho bất kỳ người dùng nào. – akira

+0

@Akira: Nghe hay nhưng sao? 'win32net.NetUserGetInfo (None, userName, 4))' returns ''home_dir': u''', tức là vô dụng –

0

này có vẻ là chỉ áp dụng đối với người sử dụng hiện tại, nhưng trên tôi (winxp), os.path.expanduser('~') trả về thư mục chính của tôi.

3

Tôi mới sử dụng bảo mật Windows ... nhưng đọc MSDN và một số blog có vẻ như với cách mà MS muốn chúng tôi xử lý dữ liệu cụ thể của người dùng khác bằng cách nhận mã thông báo người dùng.

Đã từng có một wiki tốt đẹp của Keith Brown Net phát triển Hướng dẫn về Windows Security ... bạn vẫn có thể tìm thấy nó trong bộ nhớ cache của Google cho "Pluralsight keith.guidebook"

Trường hợp 1: Nếu bạn don Không có mật khẩu người dùng:

Đối với tài khoản cục bộ, bạn có thể thử đọc đăng ký Windows như Nas Banov đã đề xuất và có một số công thức nấu ăn khác trên SO hoặc Internet.

Tôi không chắc chắn các phiên bản Windows khác nhau hoạt động như thế nào để tạo người dùng ... những người chưa bao giờ thực hiện đăng nhập phiên tương tác ... nó có tự động tạo đăng ký, thư mục chính và dữ liệu tiểu sử của họ không? Tôi đã thực hiện một số kiểm tra trên Windows XP và các khóa đăng ký không có sau khi tạo tài khoản cục bộ ... nhưng trong trường hợp này bạn có thể thử đoán dựa trên giá trị đăng ký Tất cả người dùng ... hoặc chỉ thất bại :)

Đối với các ứng dụng dành cho máy tính để bàn, khi ứng dụng đang chạy với tư cách là người dùng đã đăng nhập, tôi đang sử dụng một cái gì đó như thế này để nhận thư mục chính .... và để có được tương đương ~/.local Tôi đang sử dụng CSIDL_APPDATA, cho hồ sơ chuyển vùng hoặc chỉ là CSIDL_LOCAL_APPDATA.

from win32com.shell import shell, shellcon 
# See microsoft references for further CSIDL constants 
# http://msdn.microsoft.com/en-us/library/bb762181(VS.85).aspx 
folder_name = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, 0, 0) 

bài viết Reading Keith Brown "How To Get A Token For A User" .. bạn có thể tìm kiếm một số cách khác để nhận được một token của user mà không có một mật khẩu ...

Trường hợp 2: Nếu bạn có mật khẩu người dùng:

Đọc MSDN Tôi đã gây ấn tượng rằng nếu tôi có mã thông báo người dùng, tôi có thể nhận các thư mục bằng cách gọi một cái gì đó giống như mã bên dưới ... nhưng nó không hoạt động đối với tôi. (không chắc chắn lý do tại sao)

token = win32security.LogonUser(
      username, 
      None, # we uses UPN format for username 
      password, 
      win32security.LOGON32_LOGON_NETWORK, 
      win32security.LOGON32_PROVIDER_DEFAULT, 
      ) 
folder_name = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, token, 0) 

Đây là lý do tại sao tôi kết thúc bằng mã này ... không hoàn hảo do thực tế là nó yêu cầu tên người dùng và mật khẩu.

token = win32security.LogonUser(
      username, 
      None, # Here should be the domain ... or just go with default values 
      password, 
      win32security.LOGON32_LOGON_NETWORK, 
      win32security.LOGON32_PROVIDER_DEFAULT, 
      ) 
win32security.ImpersonateLoggedOnUser(token) 
folder_name = shell.SHGetFolderPath(0, shellcon.CSIDL_PROFILE, 0, 0) 
win32security.RevertToSelf() 

Câu hỏi này được bằng cách nào đó liên quan: How to find the real user home directory using python?

Các vấn đề liên quan