首页 > 技术文章 > 最简单好用的SSO - 能经得起几万并发用户的SSO 组件使用方法介绍

hnsongbiao 2015-01-22 22:02 原文

项目中使用了通用权限管理系统,该系统集成了单点登录功能,下面我来介绍下该单点登录实现的一些细节。

首先我们来看看其登录接口,系统本身支持各种登录方式:

1、公司名、用户名、密码

2、唯一账号、密码

3、手机号码、密码

5、Email、密码

接口已实现的部分功能:

C/S客户端登录还可以检测MAC地址,

B/S的可以对IP进行检查;

可在用户登录地址发生变化后进行手机验证后才能继续登录;

每次登陆都会记录登录日志;

。。。

另外,根据需要,可在登录接口扩展其它功能,我在项目中就增加了登录提醒功能,每次登陆都会发送提醒信息到用户的手机、微信或邮箱中。

登录后,会对应该用户生成一个OpenId,该OpenId是一个GUID,看看代码部分截图:

 

具体生成OPenId的地方,生成OpenID使用了一个线程,这样可加快登录接口的速度。

 

实现部分的功能代码

  1         public void UpdateVisitDateTask(object param)
  2         {
  3             var tuple = param as Tuple<BaseUserLogOnEntity, bool, string>;
  4             BaseUserLogOnEntity userLogOnEntity = tuple.Item1;
  5             bool createOpenId = tuple.Item2;
  6             string openId = tuple.Item3;
  7 
  8             // 2015-01-06 提高效率,写入缓存
  9             if (BaseSystemInfo.UserCenterDbType == CurrentDbType.Oracle)
 10             {
 11                 DotNet.Business.Utilities.SetUserOpenId(userLogOnEntity.Id, openId);
 12             }
 13 
 14             string sqlQuery = string.Empty;
 15             DateTime? openIdTimeout = DateTime.Now.AddHours(8);
 16 
 17             IDbHelper dbHelper = DbHelperFactory.GetHelper(BaseSystemInfo.UserCenterDbType, BaseSystemInfo.UserCenterDbConnection);
 18             // 是否更新访问日期信息
 19             List<IDbDataParameter> dbParameters = new List<IDbDataParameter>();
 20 
 21             // 若有一周没登录了,需要重新进行手机验证
 22             bool mobileValiated = false;
 23             if (userLogOnEntity.PreviousVisit.HasValue || userLogOnEntity.FirstVisit.HasValue)
 24             {
 25                 TimeSpan ts = new System.TimeSpan();
 26                 if (userLogOnEntity.LastVisit.HasValue)
 27                 {
 28                     ts = DateTime.Now.Subtract((DateTime)userLogOnEntity.LastVisit);
 29                     mobileValiated = (ts.TotalDays > 7);
 30                 }
 31                 else if (userLogOnEntity.FirstVisit.HasValue)
 32                 {
 33                     ts = DateTime.Now.Subtract((DateTime)userLogOnEntity.FirstVisit);
 34                     mobileValiated = (ts.TotalDays > 7);
 35                 }
 36                 if (mobileValiated)
 37                 {
 38                     sqlQuery = " UPDATE " + BaseUserContactEntity.TableName
 39                              + "    SET " + BaseUserContactEntity.FieldMobileValiated + " = 0 "
 40                              + "  WHERE " + BaseUserContactEntity.FieldId + " = '" + userLogOnEntity.Id + "' AND " + BaseUserContactEntity.FieldMobileValiated + " = 1 ";
 41                     dbHelper.ExecuteNonQuery(sqlQuery);
 42                 }
 43             }
 44 
 45             if (BaseSystemInfo.UpdateVisit)
 46             {
 47                 // 第一次登录时间
 48                 if (userLogOnEntity.FirstVisit == null)
 49                 {
 50                     sqlQuery = " UPDATE " + BaseUserLogOnEntity.TableName
 51                                 + "    SET " + BaseUserLogOnEntity.FieldPasswordErrorCount + " = 0 , "
 52                                 + "        " + BaseUserLogOnEntity.FieldUserOnLine + " = 1 "
 53                                 + ", " + BaseUserLogOnEntity.FieldFirstVisit + " = " + dbHelper.GetDbNow()
 54                                 + ", " + BaseUserLogOnEntity.FieldIPAddress + " = '" + userLogOnEntity.IPAddress + "'"
 55                                 + ", " + BaseUserLogOnEntity.FieldIPAddressName + " = '" + userLogOnEntity.IPAddressName + "'"
 56                                 + ", " + BaseUserLogOnEntity.FieldMACAddress + " = '" + userLogOnEntity.MACAddress + "'"
 57                                 + ", " + BaseUserLogOnEntity.FieldSystemCode + " = " + dbHelper.GetParameter(BaseUserLogOnEntity.FieldSystemCode);
 58                     dbParameters.Add(dbHelper.MakeParameter(BaseUserLogOnEntity.FieldSystemCode, userLogOnEntity.SystemCode));
 59 
 60                     if (createOpenId)
 61                     {
 62                         sqlQuery += "       , " + BaseUserLogOnEntity.FieldOpenId + " = '" + openId + "'";
 63                         sqlQuery += "       , " + BaseUserLogOnEntity.FieldOpenIdTimeout + " = " + dbHelper.GetParameter(BaseUserLogOnEntity.FieldOpenIdTimeout);
 64                         dbParameters.Add(dbHelper.MakeParameter(BaseUserLogOnEntity.FieldOpenIdTimeout, openIdTimeout));
 65                     }
 66 
 67                     sqlQuery = sqlQuery + "  WHERE (" + BaseUserLogOnEntity.FieldId + " = '" + userLogOnEntity.Id + "') AND " + BaseUserLogOnEntity.FieldFirstVisit + " IS NULL";
 68                     dbHelper.ExecuteNonQuery(sqlQuery, dbParameters.ToArray());
 69                 }
 70                 else
 71                 {
 72                     // 最后一次登录时间
 73                     sqlQuery = " UPDATE " + BaseUserLogOnEntity.TableName
 74                                 + "    SET " + BaseUserLogOnEntity.FieldPasswordErrorCount + " = 0 , "
 75                                 + BaseUserLogOnEntity.FieldPreviousVisit + " = " + BaseUserLogOnEntity.FieldLastVisit + " , "
 76                                 + BaseUserLogOnEntity.FieldUserOnLine + " = 1 , "
 77                                 + BaseUserLogOnEntity.FieldLastVisit + " = " + dbHelper.GetDbNow() + " , "
 78                                 + BaseUserLogOnEntity.FieldLogOnCount + " = " + BaseUserLogOnEntity.FieldLogOnCount + " + 1 "
 79                                 + ", " + BaseUserLogOnEntity.FieldSystemCode + " = " + dbHelper.GetParameter(BaseUserLogOnEntity.FieldSystemCode)
 80                                 + ", " + BaseUserLogOnEntity.FieldIPAddress + " = '" + userLogOnEntity.IPAddress + "'"
 81                                 + ", " + BaseUserLogOnEntity.FieldIPAddressName + " = '" + userLogOnEntity.IPAddressName + "'"
 82                                 + ", " + BaseUserLogOnEntity.FieldMACAddress + " = '" + userLogOnEntity.MACAddress + "'";
 83                     dbParameters.Add(dbHelper.MakeParameter(BaseUserLogOnEntity.FieldSystemCode, userLogOnEntity.SystemCode));
 84 
 85                     if (createOpenId)
 86                     {
 87                         sqlQuery += "       , " + BaseUserLogOnEntity.FieldOpenId + " = '" + openId + "'";
 88                         sqlQuery += "       , " + BaseUserLogOnEntity.FieldOpenIdTimeout + " = " + dbHelper.GetParameter(BaseUserLogOnEntity.FieldOpenIdTimeout);
 89                         dbParameters.Add(dbHelper.MakeParameter(BaseUserLogOnEntity.FieldOpenIdTimeout, openIdTimeout));
 90                     }
 91 
 92                     sqlQuery += "  WHERE (" + BaseUserLogOnEntity.FieldId + " = '" + userLogOnEntity.Id + "')";
 93                     dbHelper.ExecuteNonQuery(sqlQuery, dbParameters.ToArray());
 94                 }
 95             }
 96             else
 97             {
 98                 // 实现单点登录功能,每次都更换Guid
 99                 if (createOpenId)
100                 {
101                     sqlQuery = " UPDATE " + BaseUserLogOnEntity.TableName
102                              + "    SET " + BaseUserLogOnEntity.FieldPasswordErrorCount + " = 0 "
103                              + "       , " + BaseUserLogOnEntity.FieldSystemCode + " = " + dbHelper.GetParameter(BaseUserLogOnEntity.FieldSystemCode)
104                              + "       , " + BaseUserLogOnEntity.FieldOpenId + " = '" + openId + "'"
105                              + "       , " + BaseUserLogOnEntity.FieldOpenIdTimeout + " = " + dbHelper.GetParameter(BaseUserLogOnEntity.FieldOpenIdTimeout)
106                              + " WHERE (" + BaseUserLogOnEntity.FieldId + " = " + userLogOnEntity.Id + ")";
107                     // sqlQuery += " AND " + BaseUserEntity.FieldOpenId + " IS NULL ";
108                     dbParameters.Add(dbHelper.MakeParameter(BaseUserLogOnEntity.FieldSystemCode, userLogOnEntity.SystemCode));
109                     dbParameters.Add(dbHelper.MakeParameter(BaseUserLogOnEntity.FieldOpenIdTimeout, openIdTimeout));
110 
111                     dbHelper.ExecuteNonQuery(sqlQuery, dbParameters.ToArray());
112                 }
113             }
114         }

 

以上是登录部分功能的实现,其它系统登录时,根据OpenId进行登录。那么这里的Openid怎么调用呢?

如果是C/s系统,Openid是可以直接获取到的。在访问子系统时带上该OpenId,子系统再通过OpenId登录接口实现登录。

如果是B/S系统,有另外的实现方法,可在系统功能中找到。

下图是其它系通过通过OpenId登录的功能截图

 

Utilities.LogOnByOpenId(openId, true)
是通用权限管理系统底层已经实现好的方法,子系统直接调用DLL即可。

以上是通用权限系统实现的单点登录功能介绍,主要是通过OpenId进行的,可根据具体业务场景进行扩展,
对于此种方法实现的单点登录功能,大家有什么建议,欢迎交流。



 

推荐阅读