利用pdo实现不同web应用的认证统一
pdo.net是我开发中的sso模块的一部分,它是兼容pdo统一接口的.net实现
简介
========================================
pdo规范由动易(powereasy),动网(dvbbs),oblog三方联合制订和维护,其目的在于为不同的WEB应用按照统一的规范开发用户通行接口,以便实现不同WEB应用之间的用户数据同步。对该规范感兴趣的人可以去http://www.powereasy.net/Soft/documents/86.html下载
优点
=========================================
每个整合的网站不需要修改自己的逻辑业务和数据结构
用户完全独立存储,不需要将用户集中在用一的结构中。
很适合两个用户库结构差异比较大的应用整合
还有不同语言 不同数据库的整合也是可以考虑的
原理
=========================================
不同的web应用通过把用户序列化为xml来传递用户对象,利用ServerXmlHttp 进行服务器和服务器之间的通讯来传递数据进行通讯
using System;
using System.Text;
using System.Xml;
namespace Boxi.Web.SSO
{
/**//// <summary>
/// 用户基本属性实体类
/// </summary>
public class User
{
私有变量#region 私有变量
private string _username;
private string _password;
private string _email;
private string _question;
private string _answer;
private string _savecookie;
private string _truename;
private string _gender;
private string _birthday;
private string _qq;
private string _msn;
private string _mobile;
private string _telephone;
private string _province;
private string _city;
private string _address;
private string _zipcode;
private string _homepage;
private string _userip;
private string _jointime;
private string _experience;
private string _ticket;
private string _valuation;
private string _balance;
private string _posts;
private string _userstatus;
private string _signature;
private string _occupation;
private string _interests;
#endregion
封装属性#region 封装属性
/**//// <summary>
/// 创建用户
/// </summary>
/// <param name="username">用户名</param>
public User(string username)
{
_username = username;
}
/**//// <summary>
/// 用户名
/// </summary>
public string username
{
get { return _username; }
set { _username = value; }
}
/**//// <summary>
/// 用户密码
/// </summary>
public string password
{
get { return _password; }
set { _password = value; }
}
/**//// <summary>
/// 电子邮件
/// </summary>
public string email
{
get { return _email; }
set { _email = value; }
}
/**//// <summary>
/// 密码提示问题
/// </summary>
public string question
{
get { return _question; }
set { _question = value; }
}
/**//// <summary>
/// 密码提示答案
/// </summary>
public string answer
{
get { return _answer; }
set { _answer = value; }
}
/**//// <summary>
/// cookies保存时间;0=不记录(默认),1=一周,2=一月,3=一年
/// </summary>
public string savecookie
{
get { return _savecookie; }
set { _savecookie = value; }
}
/**//// <summary>
/// 真实姓名
/// </summary>
public string truename
{
get { return _truename; }
set { _truename = value; }
}
/**//// <summary>
/// 性别:0=女,1=男,2=保密
/// </summary>
public string gender
{
get { return _gender; }
set { _gender = value; }
}
/**//// <summary>
/// 生日
/// </summary>
public string birthday
{
get { return _birthday; }
set { _birthday = value; }
}
/**//// <summary>
/// QQ号
/// </summary>
public string qq
{
get { return _qq; }
set { _qq = value; }
}
/**//// <summary>
/// MSN帐号
/// </summary>
public string msn
{
get { return _msn; }
set { _msn = value; }
}
/**//// <summary>
/// 移动电话
/// </summary>
public string mobile
{
get { return _mobile; }
set { _mobile = value; }
}
/**//// <summary>
/// 固定电话
/// </summary>
public string telephone
{
get { return _telephone; }
set { _telephone = value; }
}
/**//// <summary>
/// 省/直辖市
/// </summary>
public string province
{
get { return _province; }
set { _province = value; }
}
/**//// <summary>
/// 城市/区/县
/// </summary>
public string city
{
get { return _city; }
set { _city = value; }
}
/**//// <summary>
/// 通讯地址
/// </summary>
public string address
{
get { return _address; }
set { _address = value; }
}
/**//// <summary>
/// 邮政编码
/// </summary>
public string zipcode
{
get { return _zipcode; }
set { _zipcode = value; }
}
/**//// <summary>
/// 个人主页
/// </summary>
public string homepage
{
get { return _homepage; }
set { _homepage = value; }
}
/**//// <summary>
/// 用户IP地址
/// </summary>
public string userip
{
get { return _userip; }
set { _userip = value; }
}
/**//// <summary>
/// 注册日期
/// </summary>
public string jointime
{
get { return _jointime; }
set { _jointime = value; }
}
/**//// <summary>
/// 经验值
/// </summary>
public string experience
{
get { return _experience; }
set { _experience = value; }
}
/**//// <summary>
/// 可消费积分
/// </summary>
public string ticket
{
get { return _ticket; }
set { _ticket = value; }
}
/**//// <summary>
/// 贡献值
/// </summary>
public string valuation
{
get { return _valuation; }
set { _valuation = value; }
}
/**//// <summary>
/// 现金余额
/// </summary>
public string balance
{
get { return _balance; }
set { _balance = value; }
}
/**//// <summary>
/// 发表信息数
/// </summary>
public string posts
{
get { return _posts; }
set { _posts = value; }
}
/**//// <summary>
/// 用户状态:0=正常,1=锁定,2=屏蔽,3=禁止,4=待验证
/// </summary>
public string userstatus
{
get { return _userstatus; }
set { _userstatus = value; }
}
/**//// <summary>
/// 签名档
/// </summary>
public string signature
{
get { return _signature; }
set { _signature = value; }
}
/**//// <summary>
/// 职业
/// </summary>
public string occupation
{
get { return _occupation; }
set { _occupation = value; }
}
/**//// <summary>
/// 兴趣爱好
/// </summary>
public string interests
{
get { return _interests; }
set { _interests = value; }
}
#endregion
/**//// <summary>
/// 获取用户扩展属性对应的xml
/// </summary>
/// <returns></returns>
public string ToXML()
{
StringBuilder sb = new StringBuilder();
组装xml#region 组装xml
if (!String.IsNullOrEmpty(_username))
{
sb.Append("<username>");
sb.Append(_username);
sb.Append("</username>");
}
if (!String.IsNullOrEmpty(_password))
{
sb.Append("<password>");
sb.Append(_password);
sb.Append("</password>");
}
if (!String.IsNullOrEmpty(_email))
{
sb.Append("<email>");
sb.Append(_email);
sb.Append("</email>");
}
if (!String.IsNullOrEmpty(_question))
{
sb.Append("<question>");
sb.Append(_question);
sb.Append("</question>");
}
if (!String.IsNullOrEmpty(_answer))
{
sb.Append("<answer>");
sb.Append(_answer);
sb.Append("</answer>");
}
if (!String.IsNullOrEmpty(_savecookie))
{
sb.Append("<savecookie>");
sb.Append(_savecookie);
sb.Append("</savecookie>");
}
if (!String.IsNullOrEmpty(_truename))
{
sb.Append("<truename>");
sb.Append(_truename);
sb.Append("</truename>");
}
if (!String.IsNullOrEmpty(_gender))
{
sb.Append("<gender>");
sb.Append(_gender);
sb.Append("</gender>");
}
if (!String.IsNullOrEmpty(_birthday))
{
sb.Append("<birthday>");
sb.Append(_birthday);
sb.Append("</birthday>");
}
if (!String.IsNullOrEmpty(_qq))
{
sb.Append("<qq>");
sb.Append(_qq);
sb.Append("</qq>");
}
if (!String.IsNullOrEmpty(_msn))
{
sb.Append("<msn>");
sb.Append(_msn);
sb.Append("</msn>");
}
if (!String.IsNullOrEmpty(_mobile))
{
sb.Append("<mobile>");
sb.Append(_mobile);
sb.Append("</mobile>");
}
if (!String.IsNullOrEmpty(_telephone))
{
sb.Append("<telephone>");
sb.Append(_telephone);
sb.Append("</telephone>");
}
if (!String.IsNullOrEmpty(_province))
{
sb.Append("<province>");
sb.Append(_province);
sb.Append("</province>");
}
if (!String.IsNullOrEmpty(_city))
{
sb.Append("<city>");
sb.Append(_city);
sb.Append("</city>");
}
if (!String.IsNullOrEmpty(_address))
{
sb.Append("<address>");
sb.Append(_address);
sb.Append("</address>");
}
if (!String.IsNullOrEmpty(_zipcode))
{
sb.Append("<zipcode>");
sb.Append(_zipcode);
sb.Append("</zipcode>");
}
if (!String.IsNullOrEmpty(_homepage))
{
sb.Append("<homepage>");
sb.Append(_homepage);
sb.Append("</homepage>");
}
if (!String.IsNullOrEmpty(_userip))
{
sb.Append("<userip>");
sb.Append(_userip);
sb.Append("</userip>");
}
if (!String.IsNullOrEmpty(_jointime))
{
sb.Append("<jointime>");
sb.Append(_jointime);
sb.Append("</jointime>");
}
if (!String.IsNullOrEmpty(_experience))
{
sb.Append("<experience>");
sb.Append(_experience);
sb.Append("</experience>");
}
if (!String.IsNullOrEmpty(_ticket))
{
sb.Append("<ticket>");
sb.Append(_ticket);
sb.Append("</ticket>");
}
if (!String.IsNullOrEmpty(_valuation))
{
sb.Append("<valuation>");
sb.Append(_valuation);
sb.Append("</valuation>");
}
if (!String.IsNullOrEmpty(_balance))
{
sb.Append("<balance>");
sb.Append(_balance);
sb.Append("</balance>");
}
if (!String.IsNullOrEmpty(_posts))
{
sb.Append("<posts>");
sb.Append(_posts);
sb.Append("</posts>");
}
if (!String.IsNullOrEmpty(_userstatus))
{
sb.Append("<userstatus>");
sb.Append(_userstatus);
sb.Append("</userstatus>");
}
if (!String.IsNullOrEmpty(_signature))
{
sb.Append("<signature>");
sb.Append(_signature);
sb.Append("</signature>");
}
if (!String.IsNullOrEmpty(_occupation))
{
sb.Append("<occupation>");
sb.Append(_occupation);
sb.Append("</occupation>");
}
if (!String.IsNullOrEmpty(_interests))
{
sb.Append("<interests>");
sb.Append(_interests);
sb.Append("</interests>");
}
#endregion
return sb.ToString();
}
public void LoadXML(XmlDocument xdoc)
{
XmlNode xbody = xdoc.SelectSingleNode("/root/body[1]");
if (xbody!=null)
{
LoadXml(xbody);
}
else
{
LoadXml(xdoc.SelectSingleNode("/root[1]"));
}
}
public void LoadXml(XmlNode xnod)
{
foreach (XmlNode o in xnod.ChildNodes)
{
switch(o.Name)
{
case "username":
{
_username = o.Value;
}
break;
case "password":
{
_password = o.Value;
}
break;
case "email":
{
_email = o.Value;
}
break;
case "question":
{
_question = o.Value;
}
break;
case "answer":
{
_answer = o.Value;
}
break;
case "gender":
{
_gender = o.Value;
}
break;
case "truename":
{
_truename = o.Value;
}
break;
case "birthday":
{
_birthday = o.Value;
}
break;
case "qq":
{
_qq = o.Value;
}
break;
case "msn":
{
_msn = o.Value;
}
break;
case "mobile":
{
_mobile = o.Value;
}
break;
case "telephone":
{
_telephone = o.Value;
}
break;
case "province":
{
_province = o.Value;
}
break;
case "address":
{
_address = o.Value;
}
break;
case "zipcode":
{
_zipcode = o.Value;
}
break;
case "homepage":
{
_homepage = o.Value;
}
break;
case "userip":
{
_userip = o.Value;
}
break;
case "jointime":
{
_jointime = o.Value;
}
break;
case "experience":
{
_experience = o.Value;
}
break;
case "ticket":
{
_ticket = o.Value;
}
break;
case "valuation":
{
_valuation = o.Value;
}
break;
case "balance":
{
_balance = o.Value;
}
break;
case "posts":
{
_posts = o.Value;
}
break;
case "userstatus":
{
_userstatus = o.Value;
}
break;
case "signature":
{
_signature = o.Value;
}
break;
case "occupation":
{
_occupation = o.Value;
}
break;
case "interests":
{
_interests = o.Value;
}
break;
}
}
}
}
}
我们需要做什么?
=========================================
配置一些参数: 配置通讯需要的令牌和需要同步的网站的信息
实现一个接口: 为了让其它网站发送同步信息时更够用自己的方法去修改自己的用户数据
调用一些方法: 在注册 登陆 注销 更新时调用Ping方法 向其它需要同步的网站发送同步请求
配置一些参数
--------------------------
1、增加一个配置节
<configSections>
<section name="PDO" type="System.Configuration.NameValueSectionHandler"/>
</configSections>
<PDO>
<!--令牌使用的关键字-->
<add key="key" value="Test"/>
<!--当前应用的名称-->
<add key="appid" value="web1" />
<!--每次需要actionPing时需要同步的地址列表,用|分隔-->
<add key="ping" value="http://localhost/WebSite2/PDOPing.aspx"/>
<!--本站使用的action_Prvider-->
<add key="PDOAction_Provider" value="Boxi.Web.SSO.PDO.DefaultPDOAction,Boxi.Web.SSO.PDO"/>
</PDO>
2、添加httpHandler用来供其它网站Ping
<add verb="*" path="PDOPing.aspx" type="Boxi.Web.SSO.HttpHandler.PDOPingHttpHandler,Boxi.Web.SSO"/>
</httpHandlers>
实现一个接口
-----------------------
根据自己的逻辑业务 实现自己的方法
public interface IPDOAction
{
bool checkname(string name, string email);
bool reguser(User user);
bool login(User user);
bool update(User user);
bool delete(User user);
User getinfo();
}
调用一些方法
----------------------
1、在自己的页面的登陆和注销中额外发起一个客户端http请求
//这部分正在寻找更好的解决方法
//这是为了保证每个站点均操作cookies
2、在注册、更新、删除、获取用户资料时使用ping中提供的方法
reguser(User user); 注册用户
update(User user); 更新用户
delete(User user);删除用户
User getinfo();//获取用户信息
protected void Button1_Click(object sender, EventArgs e)
{
string username = TextBox1.Text;
string password = TextBox2.Text;
//先实现自己的用户注册
.
//然后再通过ping向其它网站注册
Boxi.Web.SSO.User _user = new User(TextBox1.Text);
_user.password = TextBox2.Text;
PDOPing _ping=new PDOPing();
string[] result = _ping.reguser(_user);
for (int i = 0; i < result.Length;i++ )
{
//将所有站点注册的结果写到页面
Response.Write(result[i]);
Response.Write("<br/>");
}
}