网站用Django1.4,论坛用Discuz,用户系统共用Ucenter数据。
实现前台登录,到BBS上验证帐号,然后返回。成功,把信息存入django中!

给User models新增几个字段:

class UserProfile(models.Model):
    """
    用户信息
    """
    user = models.OneToOneField(User)
    uid = models.IntegerField(u'uid', unique=True, default=0)

然后再加个信号,这些官方doc中都有!

def create_user_profile(sender, instance, created, **kwargs):
    if created:
        UserProfile.objects.create(user=instance)
        
post_save.connect(create_user_profile, sender=User)

接下来是用户登录使用所使用的 View:

 1 def AuthViaBBS(username, password):
 2     """
 3     在BBS数据库中查找用户数据
 4     """
 5     HOST = '42.xx.xx.xx'
 6     USER = 'xxxx'
 7     PORT = 3306
 8     PASSWD = 'xxxxxxx'
 9     DBNAME = 'xxxxxx' 
10 
11     conn = ''
12     cursor = ''
13     try:
14         conn = MySQLdb.connect(host=HOST, port=PORT, passwd=PASSWD, user=USER, db=DBNAME )  
15         conn.set_character_set('utf8')  
16         cursor = conn.cursor()
17         sql = "SELECT uid, username, password, email, salt FROM pre_ucenter_members where username='%s' limit 1" % username
18         result = cursor.execute(sql)
19     except Exception, e:
20         logger.error(u'远程BBS数据库连接失败! '  +   str(e))
21     finally:
22         conn.close()
23     data = {} # 返回的结果集
24     if result: # 有用户存在
25         (data['uid'], data['username'], data['password'], data['email'], data['salt']) = cursor.fetchone()
26         logger.info(u'BBS 中的用户信息: uid:%s  username:%s  password:%s email:%s salt:%s' % (data['uid'], data['username'], data['password'], data['email'], data['salt']   ) )
27         if data['password'] and data['salt'] :
28             #验证密码 (md5(md5,salt))
29             inputPwd = md5.new( md5.new(password).hexdigest()+data['salt'] ).hexdigest()
30             print inputPwd
31             if inputPwd == data['password']:
32                 return data
33     return None
34 
35 
36 def isValid(str):
37     """
38     检查str是否含有非法字符: ' " \
39     """
40     for i in str:
41         if i in ['\'','"','\\']:
42             return 0 
43     return 1
44 
45 def checkLogin(request):
46     username = request.POST.get('username','')
47     password = request.POST.get('password','')
48     logger.info(username+ '  ' + password)
49     if isValid(username) and isValid(password):
50         data = AuthViaBBS(username, password)
51         if data:
52             # 与本地数据库同步, 更新uid , email, salt 到本地
53             user = authenticate(remote_user = username)
54             if user:
55                 user.email = data['email']
56                 user.save()
57                 profile = user.get_profile()
58                 profile.uid = data['uid']
59                 profile.save()
60                 login(request, user)
61                 return 'success'
62             else:
63                 return u'更新本地数据失败!'
64                 logger.error(u'更新本地数据失败! username:%s password:%s' % (username, password))
65         else:
66             return u'帐号或密码错误!'
67     else:
68         return '帐号 或 密码含有非法字符'

接下来就是对密码验证方法的重写,默认是 ModelBackend (具体源码在django/contrib/auth/backends.py),我们改成 RemoteUserBackend ,不过这里我们要重写下,因为默认情况下,新建了无法发送信号,导致UserProfile无法新建,我们来看看关键的代码:

def authenticate(self, remote_user):
     ...............
        if self.create_unknown_user:
            user, created = User.objects.get_or_create(username=username)
            if created:
                user = self.configure_user(user)
     ................

我们改写成这样:

 1 class DiscuzAuthBackend(RemoteUserBackend):
 2     def authenticate(self, remote_user):
 3         if not remote_user:
 4             return
 5         user = None
 6         username = self.clean_username(remote_user)
 7 
 8         if self.create_unknown_user:
 9             try:
10                 user = User.objects.get(username=username)
11             except User.DoesNotExist:
12                 user = User.objects.create(username=username)
13         else:
14             try:
15                 user = User.objects.get(username=username)
16             except User.DoesNotExist:
17                 pass
18         return user

这样新建在新用户登录后,本地mysql数据库里没有,就新建该用户,同时出发信号,新建UserProfile !

最后在 Settings.py 新增这么几句:

AUTH_PROFILE_MODULE = 'account.UserProfile'
AUTHENTICATION_BACKENDS = (
    'account.models.DiscuzAuthBackend', # 具体module位置看自己的项目
)