ibm tivoli

在现有的SharePoint Server和TAMeb集成中,存在一个已知问题,即基于WebSEAL的表单身份验证破坏了Microsoft Office产品的客户端集成功能。 这是Microsoft Office应用程序套件不支持SPNEGO或BA以外的身份验证类型的直接结果,并且进一步受到未在Internet Explorer和其他应用程序之间传递常规会话cookie的影响。

图1显示了与SharePoint Server集成的Tivoli Access Manager WebSEAL的体系结构的概述。

图1.使用Tivoli Access Manager WebSEAL的Tivoli Access Manager SharePoint Services集成的体系结构

上图显示了支持以下过程的集成体系结构:

  1. 通过WebSEAL提交对SharePoint Services的浏览器请求。
  2. WebSEAL会根据需要截取该请求,对用户进行认证和授权。
  3. WebSEAL将请求连同在HTTP头中称为iv-user的经过身份验证的用户标识一起转发到SharePoint Services。
  4. IIS对请求进行认证,并执行Tivoli Access Manager IIS模拟扩展。 该扩展读取iv-user HTTP标头并模拟标头中包含的用户ID。
  5. SharePoint Services根据模拟的用户ID返回请求的内容。
  6. 内容返回到浏览器。 WebSEAL执行适合于联结方法的过滤。

有关现有SharePoint和TAMeb集成的更多详细信息,可以在以下位置找到:

  • IBM Tivoli Access Manager Microsoft SharePoint Services集成适配器
  • IBM Tivoli Access Manager Microsoft IIS集成

注意:完成以上的Single Sign-On集成是本文其余部分的强制性先决条件。

在现有的集成中,当从启用了WebSEAL表单身份验证的SharePoint服务器打开Office文档时,Office应用程序将WebSEAL表单登录页面显示为文档内容(请参见图2 ),并且无法操纵表单来提交表单。认证信息。

图2. MicrosoftWord®文档中的表单身份验证。

当使用ActiveX控件来激活对应用程序的调用,并且通过该文件而不是通过MicrosoftWindows®InternetExplorer®下载文件时,就会发生这种情况。 使用Firefox或关闭客户端集成时,不会发生这种情况,因为会绕过ActiveX控件,并且仅通过浏览器会话下载文件,然后由应用程序从本地磁盘打开文件。

解决方案设计

为了使客户端集成在使用表单身份验证时起作用,必须实现以下组件:

  • WebSEAL外部认证C API组件
  • 会话管理应用程序
  • AJAX Cookie请求包装器

以下各节将讨论这些组件的详细信息, 图3中显示了它们之间的交互。

WebSEAL外部认证C API组件

WebSEAL CDAS组件使用WebSEAL认证C API将持久性会话密钥cookie转换为TAM用户身份。 它通过对运行在SharePoint Server上的后端会话管理器的HTTP请求进行此操作。 该组件已安装并在WebSEAL服务器上运行。

会话管理应用

会话管理应用程序负责会话密钥的管理。 它提供了一个HTTP接口,用于密钥的生成和使用。 密钥保存在数据库中,以实现快速有效的访问和高度的可伸缩性。 另外,为简化起见,会话管理应用程序是使用Active Server Page(ASP)技术实现的。 此组件已安装并在SharePoint Server上运行。

AJAX组件

AJAX组件是对调用Office应用程序ActiveX控件的现有JavaScript的包装。 它对ASP应用程序执行同步XMLHttpRequest,以请求一次使用持久会话Cookie。 该cookie通过Microsoft Cookie Jar提供给Office应用程序。 此组件安装在SharePoint Server上,并在客户端主机上运行。

图3.组件交互图

WebSEAL外部认证C API组件的实现

本节概述了使用外部身份验证C API来实现身份验证组件所需的步骤,该API提取并验证持久会话密钥cookie。

注意:

本文假定读者熟悉外部身份验证机制的实现。 有关外部认证C API的完整详细信息,请参考《 Tivoli Access Manager电子商务Web安全开发人员参考》。

本文的下载部分提供了此原型实现的完整源代码。

初始化

在身份验证服务初始化阶段,必须加载和初始化ASP应用程序路径。 初始化库所需的参数应传递给身份验证服务xauthn_initialize()函数。

清单1提供了一个示例代码段,说明了所需参数的收集和库初始化。

清单1. xauthn_initialize()函数的片段
xauthn_status_t
xauthn_initialize(int        argc,     /* in */const char **argv    /* in */)
{if (argc > 0) {CONSUME_COOKIE_URL = malloc(strlen(argv[0]));if (CONSUME_COOKIE_URL == NULL) {return XAUTHN_S_OUT_OF_MEMORY;}strcpy(CONSUME_COOKIE_URL, argv[0]);}else {printf("CDAS XAUTHN - Init Failed, No Cookie URL provided.\n", argc);return XAUTHN_S_FAILURE;}printf("\nCDAS XAUTHN - Init Complete\nUsing path: %s\n\n", CONSUME_COOKIE_URL);return XAUTHN_S_COMPLETE;
}

认证方式

服务验证功能是针对会话管理应用程序管理的会话数据库验证未经身份验证的请求中包含的持久性cookie的位置。 会话管理应用程序将与持久性cookie匹配的用户名返回到WebSEAL认证机制。

以下示例仅将持久性cookie的值添加到HTTP标头中,并使用libcURL发送请求。 为了正常工作,必须由WebSEAL访问libcURL库,并且必须使用C头文件来构建组件。

清单2提供了一个示例片段,说明了通过清单3中提供的getUsername()函数针对IIS Web应用程序验证会话密钥的身份验证阶段。

清单2. xauthn_authentication函数的片段
xauthn_status_t xauthn_authenticate(xnvlist_t         *authnInfo,xauthn_identity_t *ident)
{ ...if (authnInfo != NULL){    int     nCookieLength = COOKIE_BUFFER_LEN;char**  name = NULL;/* Init the Cookie variable */spsCookieValue = (char*)malloc(COOKIE_BUFFER_LEN);if (spsCookieValue == NULL){st = XAUTHN_S_OUT_OF_MEMORY;goto exception;}  memset (spsCookieValue, 0, sizeof(COOKIE_BUFFER_LEN));/* Get the value of the cookie */if ( XAUTHN_S_COMPLETE != (st = xnvlist_get(authnInfo, DEFAULT_COOKIE_NAME, &spsCookieValue, &nCookieLength)) ){printf ("Failed to get the value of the cookie.\n");goto exception;}printf("Sharepoint Cookie Value Found: %s\n", spsCookieValue);/* Convert the Cookie into A Username, and expire the Cookie in DB. */name = &ident->prin.data.dn;username = (char *)malloc(USERNAME_BUFFER_LEN);if (username == NULL){st = XAUTHN_S_OUT_OF_MEMORY;goto exception;}memset (username, 0, sizeof(username));/* Get the username from IIS server application */if (0 != strlen(spsCookieValue) && getUsername(username, spsCookieValue)){/* Name Retrieved */}else {printf ("Failed to get the value of the username.\n");goto exception;}printf("XAUTHN: Authenticated username: '%s'\n\n", username);/* Set the identities username */*name = (char*)username;ident->prin.prin_type = principalType;/* Set the result code to complete */st = XAUTHN_S_COMPLETE; }...}

清单3是使用libCURL访问初始化( 清单1 )中指定的会话管理应用程序以验证Cookie的代码片段。

清单3. getUsername函数的片段
int getUsername(char* username,         /* empty buffer for username */char* sessionValue      /* in */)
{CURL *     easyhandle = NULL;CURLcode    curl_rc = 0;char*       cookies;int         ret = 0;struct MemoryStruct chunk;chunk.memory    =   NULL; /* we expect realloc(NULL, size) to work */chunk.size      =   0;    /* no data at this point *//* Init CURL */curl_global_init(CURL_GLOBAL_ALL);easyhandle = curl_easy_init();if (easyhandle == NULL){printf("ERROR: Curl Handle didn't Init.\n");}/* Generate Cookie Values */cookies = (char*)malloc(COOKIE_BUFFER_LEN + DEFAULT_COOKIE_NAME_LENGTH + 3);if (cookies == NULL){printf("XAUTHN: ERROR - Cookie Malloc Failed\n");return 0;}  memset (cookies, 0, sizeof(COOKIE_BUFFER_LEN + DEFAULT_COOKIE_NAME_LENGTH + 3));strncpy(cookies, DEFAULT_COOKIE_NAME, COOKIE_BUFFER_LEN);strcat(cookies, "=");strcat(cookies, sessionValue);strcat(cookies, ";");/* Prepare Curl for request */if (CONSUME_COOKIE_URL == NULL) {printf("XAUTHN: ERROR - Curl Cookie URL is null.\n");return 0;}curl_easy_setopt(easyhandle, CURLOPT_URL, CONSUME_COOKIE_URL);curl_easy_setopt(easyhandle, CURLOPT_COOKIE, cookies);curl_easy_setopt(easyhandle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);curl_easy_setopt(easyhandle, CURLOPT_HEADER, 1);/* we pass our 'chunk' struct to the callback function */curl_easy_setopt(easyhandle, CURLOPT_WRITEDATA, (void *)&chunk);curl_rc = curl_easy_perform(easyhandle);curl_easy_cleanup(easyhandle);if (curl_rc == CURLE_OK){/* chunk.memory contains full response */ret = extractUsername(&chunk, username);if(chunk.memory)free(chunk.memory);}else{printf("XAUTHN: ERROR - cURL Request, Error Code %d. See curl.h.\n", curl_rc);}return ret;}

配置WebSEAL环境

注意:

从WebSEAL 6.0 Fixpack 03起,可以使用Cookie认证。

本部分概述了配置解决方案环境以允许WebSEAL接受和处理持久性cookie所需的过程。

下载libcURL

注意:

此组件基于Access Manager Web安全应用程序开发工具包(ADK)中提供的示例。 在构建提供的源代码示例之前,必须已经安装了ADK。 使用ADK中提供的说明来构建此组件,并确保将libcURL C标头包含在构建中。 Windows Server 2003的Makefile已包含在指南中。

该组件将cURL库用于HTTP请求,您必须从cURL网站http://curl.haxx.se/下载库二进制文件。 如果要使用提供的源来构建组件,则还需要头文件,并且应将它们提取到<build_directory>/include/curl 。 libcURL二进制文件应放在WebSEAL的路径中。

构建组件

安装了Web Security ADK后,将提供的源代码(请参阅“存档”子目录“ xauthn”中的可下载资源)提取到计算机上的目录中。 遵循ADK中的指示,将包含libcURL C标头的组件构建到构建中。

在WebSEAL中启用HTTP标头认证。

为了使WebSEAL从HTTP请求中提取会话cookie,应该为HTTP标头认证配置WebSEAL。

会话超时:

为了防止WebSEAL会话在编辑文档时变得无效,非活动会话超时必须大于缺省更新轮询间隔。 默认情况下,此设置为更新“始终”,并且间隔为10分钟,因此,通过将会话非活动超时设置为大于此时间,则会话应保持活动状态。 如果您的用户在Office应用程序中修改这些值,则应相应地修改超时间隔。

执行以下操作为HTTP标头认证配置WebSEAL:

  1. 打开WebSEAL配置文件。 例如,对于默认安装的WebSEAL,配置文件位于WebSEAL_root / etc / webseald-default.conf中。
  2. 找到[http-headers]节。
  3. 将参数timeout的值设置为0。
  4. 将参数inactive-timeout的值设置为大于10分钟(> 600秒)。
  5. 找到[http-headers]节。
  6. 指定网络环境中要支持的协议,例如“ http”,“ https”或“ both”。
  7. 创建一个名为[auth-cookies]的新节。
  8. 在新的节中创建一个名为cookie的新参数。
  9. 将新参数的值设置为SPS-SSO-SU
  10. 找到[preserve-cookie-names]节。
  11. 在节中创建一个名为name的新参数。
  12. 将新参数的值设置为SPS-SSO-SU
  13. [authentication-mechanisms]节中,找到http-request parameter
  14. 将http-request参数设置为身份验证服务的值,确保正确传递该参数,包括:
    • 一个。 认证服务二进制
    • b。 Cookie使用的URL(配置IIS应用程序后,您可能需要稍后添加。)

      看起来像这样: <path to xauthn library> & <URL for Cookie Consumption>
      示例如下:
      http-request = C:\PROGRA~1\Tivoli\PDWebRTE\pdxauthn_adk\example\xauthn.dll & http://www.yourserver.com/whoami/consumeCookie.aspx

  15. 保存更改并重新启动WebSEAL。

使用ASP实现会话管理应用程序

配置了WebSEAL环境后,我们现在必须创建用于生成和使用持久性cookie的ASP页面。 这些页面还需要访问后端数据库,在本示例中,我们将使用SQL Server2005。在您的环境中,可能使用与SharePoint Server相同的安装。 确保可以从SharePoint服务器及其ASP页访问它。

将新的应用程序添加到您的IIS SharePoint Server实例。

为了确保Office应用程序通过连接发送持久性cookie,生成cookie的应用程序必须与SharePoint Server在同一主机上。 因此,我们应该在相同的IIS“网站”下创建一个新的虚拟目录, 如图4所示。 按照向导提示,将其映射到SharePoint Server主机上的空目录。

图4.添加一个新的IIS应用程序

在这个新的虚拟目录中,我们需要创建cookie创建和cookie使用所需的页面。

获取Cookie ASP页面

打开Office文档之前,将通过AJAX标注调用此页面。 在getCookie.aspx页面中,我们需要生成一个会话密钥,将其映射到iv-user标头中显示的用户ID,然后将其与响应页面一起返回。 cookie和会话密钥应具有较短的超时时间,这样,如果不消耗它们,则可以减少持久性cookie被破坏的窗口。 在清单4的示例中,数据库使用2分钟的到期时间。 数据库操作功能全部包含在getCookie.aspx.cs文件中,该文件可以在本文的下载部分中找到。

清单4. getCookie.aspx ASP页面
<%@ Page Language="C#" AutoEventWireup="true"  Debug="true" CodeFile="getCookie.aspx.cs" Inherits="com.ibm.tivoli.am.getCookie"  %><%Response.Cache.SetCacheability(HttpCacheability.NoCache);String error ="";com.ibm.tivoli.am.getCookie ops = new com.ibm.tivoli.am.getCookie();com.ibm.tivoli.am.Cookie cookie = new com.ibm.tivoli.am.Cookie();error = Request.Headers["iv-user"];if (error != null && !error.Equals("")){cookie = ops.generateCookie(error);if (cookie.Equals("")){error = "Session Key Generation Failed";}else{Response.Cookies["SPS-SSO-SU"].Value = cookie.sessionid;Response.Cookies["SPS-SSO-SU"].Expires = cookie.expiry;}}else{error = "iv-user Not Found, Make sure you are authenticated with WebSEAL";}%>
<html>
<body>
WEBTEXT<br />
<%= error %><br />
</body>
</html>

消费Cookie ASP页面

当外部身份验证组件使用cURL验证持久性cookie时,将调用此页面。 它应该从HTTP标头中提取值,然后将其与会话数据库中的值进行比较。 如果存在并且尚未到期,那么将相应的用户标识返回到WebSEAL。 清单5包含一个代码示例。

清单5. ConsumerCookie.aspx ASP页面
<%@ Page Language="C#" AutoEventWireup="true"  Debug="true" CodeFile="getCookie.aspx.cs" Inherits="com.ibm.tivoli.am.getCookie" %><%Response.Cache.SetCacheability(HttpCacheability.NoCache);com.ibm.tivoli.am.getCookie ops = new com.ibm.tivoli.am.getCookie();String username = "";if (Request.Cookies["SPS-SSO-SU"] != null){username = ops.consumeCookie(Request.Cookies["SPS-SSO-SU"].Value);if (username != null && !username.Equals("")){Response.AppendHeader("am-user-id", username);}else{username = "'Cookie invalid'";}}else{username = "'No Cookie Found'";}%>
<html>
Authenticated as <%=username %>
</html>
</code>

准备SQL Server环境

通过ASP页面对数据库的访问是通过在IIS应用程序目录的web.config文件中设置的连接字符串指定的。 还有一个选项可以配置直到cookie过期的分钟数-当前设置为2分钟。

在此原型中,应用程序使用其自己的数据库和自定义表进行会话跟踪。 必须在运行此应用程序之前创建它们。 清单6中找到了使用的命令。

清单6.数据库命令
C:\ sqlcmd -S <servername>\<sessioninstance> -U <userid> -P <password>
1>create database sessiondb;
2>go
1>use sessiondb
2>go
Changed database context to 'sessiondb'.
1>create table sessionmap
2>(
3>username VARCHAR (50) NOT NULL,
4>session VARCHAR (48) NOT NULL,
5>expiry datetime NOT NULL,
6>PRIMARY KEY (session)
7>);
8>GO
1>exit
C:\

测试ASP组件

注意:

在此示例中,作者使用到SharePoint Server的虚拟主机联结配置了WebSEAL。

配置了SQL服务器并在SharePoint服务器上安装了应用程序之后,我们可以测试它是否正常运行。 在SharePoint Server上,访问ASP页getCookie.aspx的URL。 例如,在虚拟目录配置为“ whoami”的主机“ testserver.com”上,URL可能类似于:

http://www.testserver.com/whoami/getCookie.aspx

这将产生类似于图5所示的响应。

图5. ASP应用程序测试1

这是因为没有通过WebSEAL访问服务器,而是通过每个HTTP请求提供TAM用户名。

通过已认证的WebSEAL会话访问页面应生成如图6所示的响应(spsuser应该映射到已认证的用户名)。

图6. ASP应用程序测试2

这还应该在您的浏览器缓存中创建一个cookie: SPS-SSO-SU ,其值为48个base64字符,并在2分钟内到期(或在ASP应用程序的web.config文件中配置的另一个值)。

如果在此cookie仍然有效的情况下,然后浏览至“ consumeCookie.aspx”页面,例如:

http://www.testserver.com/whoami/consumeCookie.aspx

该页面应使用cookie并返回与其关联的用户ID, 图7中显示了一个示例。

图7. ASP应用程序测试3

如果cookie在主机上已过期或没有请求cookie,它将不会与HTTP请求一起发送,并且将显示图8所示的页面。

图8. ASP应用程序测试4

并且,如果在使用完cookie之后但过期之前再次访问该页面,则会显示图9所示的页面。

图9. ASP应用程序测试5

集成完成后,可以使用网络监视程序跟踪这些响应,以对Office应用程序与SharePoint服务器之间的通信进行故障排除。

AJAX Cookie请求包装器

为了在打开Office文档之前收集cookie,有必要修改JavaScript以发出同步AJAX HTTP请求以收集cookie。

这意味着将JavaScript(如清单7所示)添加到通过ActiveX控件打开Office文档的任何链接。

清单7. AJAX包装器
var cookieRequest = false;
try {cookieRequest = new XMLHttpRequest();
} catch (trymicrosoft) {try {cookieRequest = new ActiveXObject("Msxml2.XMLHTTP");} catch (othermicrosoft) {try {cookieRequest = new ActiveXObject("Microsoft.XMLHTTP");} catch (failed) {cookieRequest = false;}}
}if (!cookieRequest)alert("Error initializing XMLHttpRequest!");var url = "/whoami/getCookie.aspx";
cookieRequest.open("GET", url, false);
cookieRequest.send(null);if (cookieRequest.status != 200)
{alert("ERROR: Single-Signon Cookie Request Failed!, Application may not load Document");
}

需要添加的显着位置在两个功能开头的SharePoint Server的CORE.JS文件中:

function DispEx(
function createNewDocumentWithProgIDCore(

在默认的SharePoint安装中,该文件位于:

C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\CORE.JS

如果使用非标准布局模板,则这些路径可能会不同。

测试与结论

在所有这三个组件都准备就绪的情况下,我们现在已经可以很好地测试这种集成。 按照介绍中提供的用例,现在应该成功打开位于受WebSEAL保护的服务器上的Office文档,该WebSEAL配置了“表单认证”。 所有客户端集成功能都应该起作用,并且用户应该能够将文档直接保存到服务器, 如图10所示。 如果在前台运行WebSEAL,则由WebSEAL外部认证组件生成的任何调试信息都将输出到WebSEAL的日志或命令控制台。

图10.客户端集成功能-工作

最后考虑

  • 任何未使用的过期会话密钥将保留在SQL数据库中。 应该运行适当SQL语句来定期清除这些过期的会话密钥。
  • 会话密钥当前设置为48个字节。
  • WebSEAL会话上的会话超时应设置为足够长的时间,以防止在编辑Office文档时超时。 如果会话没有超时,则Office应用程序将无法正常处理此超时。 有关更多信息,请参见会话超时 。
  • 如果长时间的会话超时在整个WebSEAL环境中不合适,则您可以考虑仅对Microsoft Office SharePoint Server联结使用单独的实例,以实现更好的自定义。
  • 在Microsoft Windows Internet Explorer外部或不使用ActiveX控件(例如Web文件夹)打开文档时,可能不会检索到持久cookie,并且可能会返回WebSEAL表单。

本文介绍了在激活客户端集成的情况下使用表单身份验证时如何将WebSEAL与Microsoft Office SharePoint Server集成。 它使用WebSEAL的外部认证C API,一次使用持久性会话cookie,并通过Active Server Pages进行了验证。


翻译自: https://www.ibm.com/developerworks/tivoli/library/t-soscitam/index.html

ibm tivoli

ibm tivoli_使用表单认证通过Tivoli Access Manager电子商务WebSEAL启用Microsoft Office Sharepoint Server客户机集成相关推荐

  1. ibm tivoli_IBM Tivoli Access Manager:WebSEAL Kerberos连接

    ibm tivoli 总览 IBM®Tivoli®Access Manager(TAM)v6.1引入了WebSEAL的Kerberos联结的概念. Kerberos联结可用于对已启用Kerberos身 ...

  2. 通过了微软的SharePoint认证考试(70-542: Microsoft Office SharePoint Server 2007 - Application Development)...

    不知不觉使用MOSS2007已经2年有余了,由于公司马上就要上MOSS2010了,所以趁这个间隙先把MOSS2007的认证考了,苦于题库没有更新,只好啃了一遍SDK.结果还好,807分低空掠过,惊险惊 ...

  3. ibm tivoli_在Tivoli Access Manager v6.1 / WebSEAL和Tivoli Integrated Portal v1.1.x之间配置单点登录...

    本文包含集成Tivoli Access Manager(TAM)版本6.1和Tivoli Integrated Portal(TIP)版本1.1.x的优点. 详细的指示信息向您显示如何使用Tivoli ...

  4. ibm tivoli_在Tivoli Access Manager v6.1 / WebSEAL和Tivoli Integrated Portal v1.1.x之间配置单点登录

    ibm tivoli 本文包含集成Tivoli Access Manager(TAM)版本6.1和Tivoli Integrated Portal(TIP)版本1.1.x的优点. 详细的指示信息向您显 ...

  5. ibm tivoli_Tivoli Security,将Tivoli Access Manager用于带有HTTPS的电子商务(仅用于认证)

    ibm tivoli 存档日期:2019年5月17日 | 上次更新时间:2007年7月19日 | 首次发布:2005年11月16日 在IBM®Tivoli®Access Manager的电子商务的In ...

  6. ibm tivoli_在Tivoli Access Manager上为电子商务编写外部认证接口服务器

    ibm tivoli 自1995年以来,IBM专家Ori Pomerantz就一直致力于保护计算机网络的安全(并向其他人展示了如何做到这一点).Pomerantz于2003年加入IBM,从那时起,他就 ...

  7. ibm tivoli_在没有用户注册表的情况下使用Tivoli Access Manager for eBusiness WebSEAL

    ibm tivoli 必备知识 本文假定您基本熟悉: Tivoli Access Manager for eBusiness WebSEAL WebSEAL外部认证接口(EAI) Tivoli Fed ...

  8. ibm tivoli_使用适用于操作系统的Tivoli Access Manager保护DB2资源

    ibm tivoli 存档日期:2019年5月16日 | 首次发布:2010年4月22日 了解如何使用Tivoli®Access Manager for Operating Systems(TAMOS ...

  9. ibm tivoli_使用IBM Tivoli Access Manager实施密码到期提醒

    ibm tivoli 存档日期:2019年5月15日 | 上次更新时间:2007年3月26日 | 首次发布:2006年6月26日 公司的安全策略可能包括密码到期要求,例如密码到期提醒. 尽管IBM®T ...

最新文章

  1. TCP/IP详解--第一章
  2. android输出log,Android开发 Release情况下也能输出log
  3. jquery easy ui 1.3.4 数据表格(DataGrid)(8)
  4. Java程序员如何在5年内从小白晋升为高手?
  5. mvc:default-servlet-handler标签的作用
  6. 运行错误:Application Error - The connection to the server was unsuccessful
  7. Server2012R2 ADFS3.0 The same client browser session has made '6' requests in the last '13'seconds
  8. linux软件安装非系统盘,linux操作系统可不可以像安装windows软件一样在windows系统下的硬盘上安装...
  9. ignite mysql_redis、ignite、mysql memory 内存数据库性能测试对比
  10. js、jQuery实现文字上下无缝轮播、滚动效果
  11. 用caffe训练测试自己的图片
  12. 曼昆:宏观经济学简史(转)
  13. windbg拦截驱动加载
  14. 使用python打开多台IMAGINGSOURCE工业相机
  15. 安卓平板微信和手机微信同时登陆_如何查看手机上的微信登陆记录
  16. css中button宽高大小不包含boder问题和文字不居中问题
  17. diy nas配置推荐2020_NAS的DIY配置
  18. MVP模式基本用例开发
  19. 力扣刷题1、7、9(小小白亲测,Bug你准没我的多,hhh)
  20. “菩提本无树,明镜亦非台,本来无一物,何处惹尘埃”的典故

热门文章

  1. 理解和使用Promise.all和Promise.race
  2. Redis面试题-Redis底层数据结构
  3. i春秋网鼎杯网络安全大赛advanced题目writeup
  4. 怎样搭建后缀是.gitee.io的网站?如何免费在码云Gitee中部署个人静态网站?(或者个人博客)如何建立免费网站?
  5. java重载tostring_什么时候不希望在Java中实现toString()?
  6. python--真气网监测站点数据的抓取
  7. socks5 转 http 代理
  8. illumina 双末端测序
  9. 淘宝商品详情API接口文档调用说明
  10. springboot实验课程辅助管理系统 毕业设计-附源码191113