Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4999042
  • 博文数量: 921
  • 博客积分: 16037
  • 博客等级: 上将
  • 技术积分: 8469
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-05 02:08
文章分类

全部博文(921)

文章存档

2020年(1)

2019年(3)

2018年(3)

2017年(6)

2016年(47)

2015年(72)

2014年(25)

2013年(72)

2012年(125)

2011年(182)

2010年(42)

2009年(14)

2008年(85)

2007年(89)

2006年(155)

分类: Python/Ruby

2013-06-24 16:45:19


我也是不久前刚开始自学python的,前不久刚写了个小Demo,Demo中用到了Twisted这一块,所以就自己随手记录了一下在Demo中的心得,希望对python新手有一定的帮助,同时如果在以下有讲的不对的地方,也希望博友们能指出,小弟会感激不尽。

python中对客户端和服务端的通信提供了很好的支持,Twisted封装了大量有关python通信技术。而通信时对用户的验证也是很有必要的,这样可以保证服务端的安全。twisted提供cred模块, 将用户校验和业务逻辑分开以降低系统的耦合性。例如邮件服务中的pop3和imap可以使用同一套的验证逻辑和不同的业务逻辑。在Twisted中, pop3, imap, ssh、ftp和PB服务都使用了twisted.cred来进行验证。

其中,twisted.cred验证最重要的三个模块为:Portal、checkers和credentials,下面我用Demo中的代码来进行分析和讲解。


首先必须导入twisted.cred模块

from twisted.cred import portal,checkers,credentials


Main:下面是服务端Main里面运行的几行代码


  1. p = portal.Portal(Realm()) # line 1
  2. p.registerChecker(UserChecker()) # line 2
  3. f = pb.PBServerFactory(p) # line 3
  4. reactor.listenTCP(8206, f) # line 4
  5. reactor.run() # line 5

Main中line 1 实例化了一个Portal对象,Portal作为入口,每一次用户服务都和Portal进行交互,portal.Portal()带了一个参数,该参数其实是一个类,该类继承了portal.IRealm接口,portal.IRealm接口其实就是一个对象认证系统,每次用户验证完成之后,都将会通过该接口将服务端协议返回给客户端,供客户端调用,下面有代码可以供参考


  1. class Realm:
  2.     implements(portal.IRealm) # 实现 portal中的IRealm接口 ,implements关键字由from zope.interface import implements导入
  3.     
  4.        def requestAvatar(self, user, mind, *interfaces): # 重写IRealm接口内的requestAvator方法,该方法有4个参数,第二个参数是由
  5.                                                             # checkers.ICredentialsChecker接口的requestAvatarId方法返回用于识别用户唯一性的ID,后面会讲
  6.                                                             # 到;第三个参数其实就是一个客户端对象,该客户端对象由客户端的pb.PbClientFactory的Login()方法
  7.                                                             # 传入,该对象必须继承了pb.Referenceable或者是pb.Avator协议,一旦验证通过,服务端就可以通过该
  8.                                                             # 对象协议与客户端通信,调用客户端方法;第四个参数是一个list, 用于决定返回的avatar类型, 通常
  9.                                                             # 只有一个元素pb.IPerspective
  10.         
  11.                 if pb.IPerspective not in interfaces: # 检测pb.IPerspective是否在list中,如果不在当中,就抛出异常
  12.             raise NotImplementedError

  13.         def remove(): del userlist[user.account]
  14.         user.client = mind # 将每次验证通过后的客户端协议保存在user对象中,后面可以对任意处于连接状态的客户端进行调用
  15.                 return pb.IPerspective, Persective(mind), remove # 该方法返回了一个三个元素的元祖,第一个元素为一个avator类型;第二个参数是一个协议对
  16.                                                                       # 象,该对象必须继承自pb.Refrenceable或者是pb.Avator协议,该对象返回至客户端,客户端
  17.                                                                       # 就可以通过该协议与服务端进行通信,调用服务器方法;第三个元素返回了一个回调函数,该
  18.                                                                       # 函数在客户端与服务端断开连接的时候被触发


以下是第二个参数Perspective类代码:


  1. # 该类远程调用客户端的方法
  2. class ClientAvator(pb.Referenceable): # 继承自 pb.Referenceable , 也可继承自 pb.Avator
  3.     def __init__(self,client):
  4.         self.client = client

  5.     def callSelfRemote(self,clientFunName): # 远程调用本次验证通过后的用户的客户端方法
  6.         self.client.callRemote(clientFunName)

  7.     def callUserRemote(self,clientFunName,user): # 远程调用其它验证通过后的用户的客户端方法
  8.         user.client.callRemote(clientFunName)

  9.     def popupUserOnlineDlg(self,user=None):
  10.         if user:
  11.             self.callUserRemote("popupUserOnlineDlg",user)
  12.         else:
  13.             self.callSelfRemote("popupUserOnlineDlg")



  1. #   该类的方法供客户端远程调用
  2. class Persective(ClientAvator): # 继承了ClientAvator,ClientAvator继承自 pb.Referenceable
  3.     def __init__(self,client):
  4.         ClientAvator.__init__(self,client=client)

  5.     def remote_NotifyOthserOnlineUsers(self): # 注意远程调用的方法前缀,如果是继承pb.Refrenceable协议,对应的前缀就为remote_,如果继承的是pb.Avator协
  6.                                                   # 议,前缀就是perspective_
  7.         for u in userlist.itervalues():
  8.             self.popupUserOnlineDlg(u)

Main中line 2就是向Portal里面注入一个用户登录时进行验证的凭据,也就是验证逻辑,UserChecker对象继承了checkers.ICredentialsChecker接口,该接口支持用户名/密码对、密钥等多种认证方式,其中的用户验证逻辑就可以通过重写接口内的 requestAvatarId方法实现,下面有代码可以供参考


  1. class UserChecker:
  2.     implements(checkers.ICredentialsChecker) # 继承了 checkers.ICredentialsChecker 接口
  3.     credentialInterfaces = (credentials.IUsernamePassword,credentials.IUsernameHashedPassword) # 指明认证方式,这里指明的是用户名/密码对的认证方式
  4.     
  5.         def requestAvatarId(self,credentials): ############### 重写 checkers.ICredentialsChecker接口的 requestAvatorId方法,该方法有2个参数,第二个参数
  6.                                                                  # 是由客户端pb.PBClientFactory 的Login() 方法传过来的参数,关于Login()方法,后面会详细的
  7.                                                                  # 为您讲解
  8.         
  9.                 accountPwd = credentials.username.split(',')
  10.         if len(accountPwd)!=2:
  11.             return defer.fail(u'非法的登录参数!')
  12.         account,pwd = accountPwd
  13.         if int(account) in userlist:
  14.             return defer.fail(u"帐号已在别处登录")

  15.         remarks,user = UserLogin(account,pwd)
  16.         if user:
  17.             userlist[user.account] = user
  18.             return defer.succeed(user) # 验证通过后,将user对象传递给IRealm的requestAvator方法处理
  19.         else:
  20.             return defer.fail(remarks) # 验证失败,IRealm的requestAvator方法不执行,直接将错误信息返回至客户端

3、4、5三行代码,在我的之前的博文当中已经有了详细讲解,不是很清楚的可以去看下。


Main 中 line 3 实例化了一个服务工厂PbServerFactory,该工程实例化时接受了一个Portal实例化后的对象

Main 中 line 4 设置了监听的工厂及监听端口

Main 中 line 5 开始监听



文章来自:http://blog.csdn.net/ld490832353/article/details/7839234



阅读(2085) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~