dp2library Login() API 用法详解
dp2library 服务器的 Login() API 有一些复杂的用法。本文试图介绍这些用法。
管理员代理读者登录
在不知道读者账户的密码的前提下,可以用一个权限足够的管理员账户,代表读者进行登录。登录后看起来和读者平时自己登录没有什么区别。
一般登录需要二元信息:用户名+密码。而管理员代理读者登录时需要三元信息:读者用户名+管理员用户名+管理员密码。其中“读者用户名”包括读者证条码号、姓名、身份证号等等可用的途径。
下面是一个样例代码片段:
string strUserName = "CN:B5C57074"; // 这里是一个读者的 CardNumber,即绑定的副卡卡号。可用的前缀可参考相关文档
string strParameters = "index=-1,type=reader,simulate=yes,libraryCode=" + LoginControl.GetLibraryCodeParam(strLibraryCode) + ",client=dp2OPAC|" + OpacApplication.ClientVersion;
string strPassword = app.ManagerUserName + "," + app.ManagerPassword; // 代理登录的需要
// return:
// -1 error
// 0 登录未成功
// 1 登录成功
// >1 有多个账户符合条件。
long lRet = channel.Login(strUserName,
strPassword,
strParameters,
out strError);
if (lRet == 1)
{
if (string.IsNullOrEmpty(channel.UserName) == true)
throw new Exception("SessionInfo.Login() this.Channel.UserName 为空 (此时 SessionInfo.m_strUserName 为 '" + this.m_strUserName + "')");
var user_id = channel.UserName; // 这里获得登录成功后服务器返回的实际用户 ID,对于读者账户来说这是“读者证条码号”
登录时获得 dp2library Token
有一些场合需要尽量避免存储和传递类似用户名、密码这样的敏感信息,可以使用(登录成功后) dp2library token 来代替。当前端需要重新登录的时候,用以前登录成功时获得的 token 来进行登录即可。
下面是一段样例代码,示范了如何在登录时获得 dp2library token 字符串。
long lRet = channel.Login(strUserName,
strPassword,
strParameters + ",gettoken=day",
out strError);
if (lRet == 1)
{
string currentUserRights = channel.Rights; // token 字符串包含在 rights 字符串中:...,token:xxxxxx,...
string token = GetCurrentAccountToken(currentUserRights);
......
......
// 获得当前登录账户的 token 字符串
public static string GetCurrentAccountToken(string currentUserRights)
{
if (currentUserRights == null)
return null;
string[] parts = currentUserRights.Split(new char[] { ',' });
foreach(string part in parts)
{
if (part.StartsWith("token:"))
{
return part.Substring("token:".Length);
}
}
return null;
}
用先前得到的 dp2library token 登录
dp2library token 代表了一个已经成功登录的用户身份,可以用它代替用用户名和密码来进行登录。注意 token 是有有效期的,分为 day month year 三种有效期。过了有效期 token 就失效了,需要重新获得 token。
string strUserName = "R0000001"; // 这是一个读者的证条码号。token 登录只允许使用读者证条码号
string strParameters = "index=-1,type=reader,simulate=yes,libraryCode=" + LoginControl.GetLibraryCodeParam(strLibraryCode) + ",client=dp2OPAC|" + OpacApplication.ClientVersion;
string strPassword = app.ManagerUserName + "," + app.ManagerPassword + "|||token:" + token; // 利用 token 登录
// return:
// -1 error
// 0 登录未成功
// 1 登录成功
// >1 有多个账户符合条件。
long lRet = channel.Login(strUserName,
strPassword,
strParameters,
out strError);
可以看出,利用 token 来登录,实际上也是一种代理登录(只是登录参数略有差别)。
那么为啥不直接用代理登录,而要用一种比一般代理登录略复杂一点的方式来登录呢?原因是,一般的代理登录只需要知道被代理的账户名(不需要知道被代理账户的密码)加上一个管理员身份即可登录,而利用 token 登录提高了要求,还需要知道 token,等于三元变成了四元,增强了安全性,降低了被仿冒的可能性。
dp2OPAC login.aspx 利用 token 登录
最新版 dp2OPAC 的 login.aspx 支持使用 token 字符串进行登录。例如:
http://localhost:8081/dp2OPAC/login.aspx?action=tokenlogin&id=R0000001&redirect=searchbiblio.aspx&token=GKOfRJsoxd63VNoRE0yxsCPfrFw|||20210203
其中 id 参数定义了读者证条码号,token 参数定义了 token 字符串,redirect 参数定义了登录后要跳转到的页面。
注意 URL 中的 token 参数内容要先用 UrlEncode() 函数转义处理
在TestRestLibrary工具第一次登录:获取token,正常
strUserName: R0000001
strPassword: supervisor,1
strParameters: simulate=true,type=reader,client=dp2OPAC|1.0,gettoken=day
返回结果
Rights:getreaderinfo,getbibliosummary,renew,reservation,search,getbiblioinfo,getiteminfo,getcommentinfo,getissueinfo,getorderinfo,setcommentinfo,setreaderinfo,changereaderpassword,getsystemparameter,listdbfroms,getres,searchbiblio,searchcharging,searchcomment,searchissue,searchitem,searchorder,patron,token:xv0MYpEV/s1ThB+LgQWkmYwO2NM|||20210207
UserName:R0000001
在TestRestLibrary工具第二次登录:用token登录,正常
strUserName: R0000001
strPassword: supervisor,1|||token:xv0MYpEV/s1ThB+LgQWkmYwO2NM|||20210207
strParameters: simulate=true,type=reader,client=dp2OPAC|1.0
返回结果
Rights:getreaderinfo,getbibliosummary,renew,reservation,search,getbiblioinfo,getiteminfo,getcommentinfo,getissueinfo,getorderinfo,setcommentinfo,setreaderinfo,changereaderpassword,getsystemparameter,listdbfroms,getres,searchbiblio,searchcharging,searchcomment,searchissue,searchitem,searchorder,patron
UserName:R0000001
在浏览器用token方式进入OPAC,是未登录的状态(有个人信息等菜单,但点进去是登录界面)
http://localhost:8081/dp2OPAC/login.aspx?action=tokenlogin&id=R0000001&redirect=searchbiblio.aspx&token=xv0MYpEV/s1ThB+LgQWkmYwO2NM|||20210207
https://github.com/DigitalPlatform/dp2/issues/260