【ASP NET】UCenter实现多站点同步登录退出

394 阅读13分钟

利用UCenter实现discuz论坛和应用网站同步登录和退出功能 测试环境:Discuz! X3.2UCenter 1.6.Net Framework 4.0

进入Discuz 后台的UCenter应用管理页面

UCenter

添加新应用

安装方式选择自定义安装、应用类型为其他。通信密钥可以自定义。开启同步登录和通知

添加新应用

集成UCenter API For DotNet

UC配置信息

DS.Web.UCenter添加到项目中 修改项目App.Config配置信息: UC_KEY 添加新应用时填写的通信密钥 UC_API UCenter地址 UC_APPID 应用网站在UCenter中的id

配置完毕后将网站运行起来,刷新一下应用列表界面

通信成功

如果上述配置信息正确,就可以看到应用通信成功了。

调用UCenter API

以登录为例,实例化一个UcClient对象,调用UserLogin方法

IUcClient client = new UcClient();
var user = client.UserLogin("admin", "admin"); //登陆
if (user.Success) //判断是否登陆成功
{
    client.PmSend(0, 0, "公告", "测试公告", user.Uid); //给该用户发送系统消息
}

其他相关的API

using System.Collections.Generic;

namespace DS.Web.UCenter.Client
{
    ///<summary>
    /// UcApi客户端
    ///</summary>
    public interface IUcClient
    {
        /// <summary>
        /// 用户注册
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <param name="passWord">密码</param>
        /// <param name="email">Email</param>
        /// <param name="questionId">登陆问题</param>
        /// <param name="answer">答案</param>
        /// <returns></returns>
        UcUserRegister UserRegister(string userName, string passWord, string email, int questionId = 0, string answer = "");

        /// <summary>
        /// 用户登陆
        /// </summary>
        /// <param name="userName">用户名/Uid/Email</param>
        /// <param name="passWord">密码</param>
        /// <param name="loginMethod">登录方式</param>
        /// <param name="checkques">需要登陆问题</param>
        /// <param name="questionId">问题ID</param>
        /// <param name="answer">答案</param>
        /// <returns></returns>
        UcUserLogin UserLogin(string userName, string passWord, LoginMethod loginMethod = LoginMethod.UserName, bool checkques = false, int questionId = 0, string answer = "");

        /// <summary>
        /// 得到用户信息
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        UcUserInfo UserInfo(string userName);

        /// <summary>
        /// 得到用户信息
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        UcUserInfo UserInfo(int uid);

        /// <summary>
        /// 更新用户信息
        /// 更新资料需验证用户的原密码是否正确,除非指定 ignoreoldpw 为 1。
        /// 如果只修改 Email 不修改密码,可让 newpw 为空;
        /// 同理如果只修改密码不修改 Email,可让 email 为空。
        /// </summary>
        /// <returns></returns>
        UcUserEdit UserEdit(string userName, string oldPw, string newPw, string email, bool ignoreOldPw = false, int questionId = 0, string answer = "");

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        bool UserDelete(params int[] uid);

        /// <summary>
        /// 删除用户头像
        /// </summary>
        /// <param name="uid">Uid</param>
        void UserDeleteAvatar(params int[] uid);

        /// <summary>
        /// 同步登陆
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns>同步登陆的 Html 代码</returns>
        string UserSynlogin(int uid);

        /// <summary>
        /// 同步登出
        /// </summary>
        /// <returns>同步登出的 Html 代码</returns>
        string UserSynLogout();

        /// <summary>
        /// 检查 Email 格式
        /// </summary>
        /// <param name="email">Email</param>
        /// <returns></returns>
        UcUserCheckEmail UserCheckEmail(string email);

        /// <summary>
        /// 增加受保护用户
        /// </summary>
        /// <param name="admin">操作管理员</param>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        bool UserAddProtected(string admin, params string[] userName);

        /// <summary>
        /// 删除受保护用户
        /// </summary>
        /// <param name="admin">操作管理员</param>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        bool UserDeleteProtected(string admin, params string[] userName);

        /// <summary>
        /// 得到受保护用户
        /// </summary>
        /// <returns></returns>
        UcUserProtecteds UserGetProtected();

        /// <summary>
        /// 合并用户
        /// </summary>
        /// <param name="oldUserName">老用户名</param>
        /// <param name="newUserName">新用户名</param>
        /// <param name="uid">Uid</param>
        /// <param name="passWord">密码</param>
        /// <param name="email">Email</param>
        /// <returns></returns>
        UcUserMerge UserMerge(string oldUserName, string newUserName, int uid, string passWord, string email);

        /// <summary>
        /// 移除重名用户记录
        /// </summary>
        /// <param name="userName">用户名</param>
        void UserMergeRemove(string userName);

        /// <summary>
        /// 得到用户积分
        /// </summary>
        /// <param name="appId">应用程序Id</param>
        /// <param name="uid">Uid</param>
        /// <param name="credit">积分编号</param>
        /// <returns></returns>
        int UserGetCredit(int appId, int uid, int credit);

        /// <summary>
        /// 检查新消息
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        UcPmCheckNew PmCheckNew(int uid);

        /// <summary>
        /// 发送短消息
        /// </summary>
        /// <param name="fromUid">发件人用户 ID,0 为系统消息</param>
        /// <param name="replyPmId">回复的消息 ID,0:发送新的短消息,大于 0:回复指定的短消息</param>
        /// <param name="subject">消息标题</param>
        /// <param name="message">消息内容</param>
        /// <param name="msgTo">收件人ID</param>
        /// <returns></returns>
        UcPmSend PmSend(int fromUid, int replyPmId, string subject, string message, params int[] msgTo);

        /// <summary>
        /// 发送短消息
        /// </summary>
        /// <param name="fromUid">发件人用户 ID,0 为系统消息</param>
        /// <param name="replyPmId">回复的消息 ID,0:发送新的短消息,大于 0:回复指定的短消息</param>
        /// <param name="subject">消息标题</param>
        /// <param name="message">消息内容</param>
        /// <param name="msgTo">收件人用户名</param>
        /// <returns></returns>
        UcPmSend PmSend(int fromUid, int replyPmId, string subject, string message, params string[] msgTo);

        /// <summary>
        /// 删除短消息
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="folder">文件夹</param>
        /// <param name="pmIds">短消息ID</param>
        /// <returns>删除的数量</returns>
        int PmDelete(int uid, PmDeleteFolder folder, params int[] pmIds);

        /// <summary>
        /// 删除会话
        /// </summary>
        /// <param name="uid">发件人</param>
        /// <param name="toUids">收件人</param>
        /// <returns>删除的数量</returns>
        int PmDelete(int uid, params int[] toUids);

        /// <summary>
        /// 修改阅读状态
        /// </summary>
        /// <param name="uid">发件人</param>
        /// <param name="toUids">收件人</param>
        /// <param name="pmIds">短消息ID</param>
        /// <param name="readStatus">阅读状态</param>
        void PmReadStatus(int uid, int toUids, int pmIds = 0, ReadStatus readStatus = ReadStatus.Readed);

        /// <summary>
        /// 修改阅读状态
        /// </summary>
        /// <param name="uid">发件人</param>
        /// <param name="toUids">收件人数组</param>
        /// <param name="pmIds">短消息ID数组</param>
        /// <param name="readStatus">阅读状态</param>
        void PmReadStatus(int uid, IEnumerable<int> toUids, IEnumerable<int> pmIds, ReadStatus readStatus = ReadStatus.Readed);

        /// <summary>
        /// 获取短消息列表
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="page">当前页编号,默认值 1</param>
        /// <param name="pageSize">每页最大条目数,默认值 10</param>
        /// <param name="folder">短消息所在的文件夹</param>
        /// <param name="filter">过滤方式</param>
        /// <param name="msgLen">截取短消息内容文字的长度,0 为不截取,默认值 0</param>
        /// <returns></returns>
        UcPmList PmList(int uid, int page = 1, int pageSize = 10, PmReadFolder folder = PmReadFolder.NewBox, PmReadFilter filter = PmReadFilter.NewPm, int msgLen = 0);

        /// <summary>
        /// 获取短消息内容
        /// 本接口函数用于返回指定用户的指定消息 ID 的消息,返回的数据中包含针对这个消息的回复。
        /// 如果指定 touid 参数,那么短消息将列出所有 uid 和 touid 之间的短消息,daterange 可以指定返回消息的日期范围。
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="pmId">短消息ID</param>
        /// <param name="toUid">收件人ID</param>
        /// <param name="dateRange">日期范围</param>
        /// <returns></returns>
        UcPmView PmView(int uid, int pmId, int toUid = 0, DateRange dateRange = DateRange.Today);

        /// <summary>
        /// 获取单条短消息内容
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="type">类型</param>
        /// <param name="pmId">短消息ID</param>
        /// <returns></returns>
        UcPm PmViewNode(int uid, ViewType type = ViewType.Specified, int pmId = 0);

        /// <summary>
        /// 忽略未读消息提示
        /// </summary>
        /// <param name="uid">Uid</param>
        void PmIgnore(int uid);

        /// <summary>
        /// 得到黑名单
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        UcPmBlacklsGet PmBlacklsGet(int uid);

        /// <summary>
        /// 设置黑名单为禁止所有人(清空原数据)
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        bool PmBlacklsSetAll(int uid);

        /// <summary>
        /// 设置黑名单(清空原数据)
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="userName">黑名单用户名</param>
        /// <returns></returns>
        bool PmBlacklsSet(int uid, params string[] userName);

        /// <summary>
        /// 添加黑名单为禁止所有人
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        bool PmBlacklsAddAll(int uid);

        /// <summary>
        /// 增加黑名单
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="userName">黑名单用户名</param>
        /// <returns></returns>
        bool PmBlacklsAdd(int uid, params string[] userName);

        /// <summary>
        /// 删除黑名单中的禁止所有人
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <returns></returns>
        void PmBlacklsDeleteAll(int uid);

        /// <summary>
        /// 删除黑名单
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="userName">黑名单用户名</param>
        void PmBlacklsDelete(int uid, params string[] userName);

        /// <summary>
        /// 增加好友
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="friendId">好友ID</param>
        /// <param name="comment">备注</param>
        /// <returns></returns>
        bool UcFriendAdd(int uid, int friendId, string comment = "");

        /// <summary>
        /// 删除好友
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="friendIds">好友ID</param>
        /// <returns></returns>
        bool UcFriendDelete(int uid, params int[] friendIds);

        /// <summary>
        /// 获取好友总数
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="direction">方向</param>
        /// <returns>好友数目</returns>
        int UcFriendTotalNum(int uid, FriendDirection direction = FriendDirection.All);

        /// <summary>
        /// 好友列表
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="page">当前页编号</param>
        /// <param name="pageSize">每页最大条目数</param>
        /// <param name="totalNum">好友总数</param>
        /// <param name="direction">方向</param>
        /// <returns></returns>
        UcFriends UcFriendList(int uid, int page = 1, int pageSize = 10, int totalNum = 10, FriendDirection direction = FriendDirection.All);

        /// <summary>
        /// 积分兑换请求
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="from">原积分</param>
        /// <param name="to">目标积分</param>
        /// <param name="toAppId">目标应用ID</param>
        /// <param name="amount">积分数额</param>
        /// <returns></returns>
        bool UcCreditExchangeRequest(int uid, int from, int to, int toAppId, int amount);

        ///<summary>
        /// 修改头像
        ///</summary>
        ///<param name="uid">Uid</param>
        ///<param name="type"></param>
        ///<returns></returns>
        string Avatar(int uid, AvatarType type = AvatarType.Virtual);

        /// <summary>
        /// 得到头像地址
        /// </summary>
        /// <param name="uid">Uid</param>
        /// <param name="size">大小</param>
        /// <param name="type">类型</param>
        /// <returns></returns>
        string AvatarUrl(int uid,AvatarSize size,AvatarType type = AvatarType.Virtual);

        /// <summary>
        /// 检查头像是否存在
        /// </summary>
        /// <param name="uid"></param>
        /// <param name="size"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        bool AvatarCheck(int uid, AvatarSize size = AvatarSize.Middle, AvatarType type = AvatarType.Virtual);

        /// <summary>
        /// 获取标签数据
        /// </summary>
        /// <param name="tagName">标签名</param>
        /// <param name="number">应用程序ID对应的数量</param>
        /// <returns></returns>
        UcTags TagGet(string tagName, IEnumerable<KeyValuePair<string, string>> number);

        /// <summary>
        /// 添加事件
        /// </summary>
        /// <param name="icon">图标类型,如:thread、post、video、goods、reward、debate、blog、album、comment、wall、friend</param>
        /// <param name="uid">Uid</param>
        /// <param name="userName">用户名</param>
        /// <param name="titleTemplate">标题模板</param>
        /// <param name="titleData">标题数据数组</param>
        /// <param name="bodyTemplate">内容模板</param>
        /// <param name="bodyData">模板数据</param>
        /// <param name="bodyGeneral">相同事件合并时用到的数据:特定的数组,只有两项:name、link,保留</param>
        /// <param name="targetIds">保留</param>
        /// <param name="images">相关图片的 URL 和链接地址。一个图片地址,一个链接地址</param>
        /// <returns></returns>
        int FeedAdd(FeedIcon icon, int uid, string userName, string titleTemplate, string titleData, string bodyTemplate, string bodyData, string bodyGeneral, string targetIds, params string[] images);

        /// <summary>
        /// 得到Feed
        /// </summary>
        /// <param name="limit">数量限制</param>
        /// <returns></returns>
        UcFeeds FeedGet(int limit);

        /// <summary>
        /// 得到应用列表
        /// </summary>
        /// <returns></returns>
        UcApps AppList();

        /// <summary>
        /// 添加邮件到队列
        /// </summary>
        /// <param name="subject">标题</param>
        /// <param name="message">内容</param>
        /// <param name="uids">Uid</param>
        /// <returns></returns>
        UcMailQueue MailQueue(string subject, string message,params int[] uids);

        /// <summary>
        /// 添加邮件到队列
        /// </summary>
        /// <param name="subject">标题</param>
        /// <param name="message">内容</param>
        /// <param name="emails">目标Email</param>
        /// <returns></returns>
        UcMailQueue MailQueue(string subject, string message, params string[] emails);

        /// <summary>
        /// 添加邮件到队列
        /// </summary>
        /// <param name="subject">标题</param>
        /// <param name="message">内容</param>
        /// <param name="uids">Uid</param>
        /// <param name="emails">目标email</param>
        /// <returns></returns>
        UcMailQueue MailQueue(string subject, string message, int[] uids, string[] emails);

        /// <summary>
        /// 添加邮件到队列
        /// </summary>
        /// <param name="subject">标题</param>
        /// <param name="message">内容</param>
        /// <param name="fromMail">发信人,可选参数,默认为空,uc后台设置的邮件来源作为发信人地址</param>
        /// <param name="charset">邮件字符集,可选参数,默认为gbk</param>
        /// <param name="htmlOn">是否是html格式的邮件,可选参数,默认为FALSE,即文本邮件</param>
        /// <param name="level">邮件级别,可选参数,默认为1,数字大的优先发送,取值为0的时候立即发送,邮件不入队列</param>
        /// <param name="uids">Uid</param>
        /// <param name="emails">目标email</param>
        /// <returns></returns>
        UcMailQueue MailQueue(string subject,string message,string fromMail,string charset,bool htmlOn,int level,int[] uids,string[] emails);
    }
}

供UCenter调用的接口

在站点新建一个路径为/API/uc.ashx的文件 (文件夹名称要大写) 添加以下代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DS.Web.UCenter.Api;

namespace DS.Web.UCenter.Website.API
{
    /// <summary>
    /// Summary description for uc
    /// </summary>
    public class uc:UcApiBase
    {
        // 用户被删除
        public override ApiReturn DeleteUser(IEnumerable<int> ids)
        {
            throw new NotImplementedException();
        }

        // 修改了用户名
        public override ApiReturn RenameUser(int uid, string oldUserName, string newUserName)
        {
            throw new NotImplementedException();
        }

        public override UcTagReturns GetTag(string tagName)
        {
            throw new NotImplementedException();
        }

        // 同步登录
        public override ApiReturn SynLogin(int uid)
        {
            throw new NotImplementedException();
        }

        // 同步退出
        public override ApiReturn SynLogout()
        {
            throw new NotImplementedException();
        }

        // 密码更新
        public override ApiReturn UpdatePw(string userName, string passWord)
        {
            throw new NotImplementedException();
        }

        public override ApiReturn UpdateBadWords(UcBadWords badWords)
        {
            throw new NotImplementedException();
        }

        public override ApiReturn UpdateHosts(UcHosts hosts)
        {
            throw new NotImplementedException();
        }

        public override ApiReturn UpdateApps(UcApps apps)
        {
            throw new NotImplementedException();
        }

        public override ApiReturn UpdateClient(UcClientSetting client)
        {
            throw new NotImplementedException();
        }

        public override ApiReturn UpdateCredit(int uid, int credit, int amount)
        {
            throw new NotImplementedException();
        }

        public override UcCreditSettingReturns GetCreditSettings()
        {
            throw new NotImplementedException();
        }

        public override ApiReturn GetCredit(int uid, int credit)
        {
            throw new NotImplementedException();
        }

        public override ApiReturn UpdateCreditSettings(UcCreditSettings creditSettings)
        {
            throw new NotImplementedException();
        }
    }
}

这些是提供给UCenter调用的接口,例如当用户在discuz登录时,UCenter会发送一个通知(请求uc.ashx),把登录的用户uid等信息传递过来,我们要做的就是在自己的SynLogin中写登录的cookie或session等操作。 同时,在SynLogout中加上清除cookie和session的处理。就实现了同步登录和退出功能。

注意点

  • 添加应用时一定要勾选 开启同步登录接受通知
  • 需要正确填写UC各项必填的配置信息
  • 确保在bbs站点存在/uc_client/data/cache/apps.php文件,没有的话从/uc_server/data/cache/apps.php拷贝一份
  • 要将上述配置信息放到站点的Web.config

同步注册

如果你的网站还需要同步注册功能,请参考[【ASP.Net】UCenter实现多站点同步登录退出】(http://www.jianshu.com/p/1caa425ef24b)