说明
关于Sharepoint表单登录自定义页面网上有好多,这里也就不重复说了,我也是从网上找的代码,使用网上的代码正常登录是没有问题的,都是很正常的,但是有一点小细节,就是都是默认记住密码的。
这个也是客户提出来的,他们希望用户登录之后,每次关闭浏览器之后登录凭据就应该过期,让用户重新登录,网上的代码实现不了。
解决方法
这个问题应该怎么解决呢,Form认证一般都是把验证信息存在Cookie中,让Cookie在浏览器关闭的时候过期就可以了,我记得以前在做Asp.Net开发的时候是可以这么做的,现在都忘了,隐约记得应该是保存在Session中,可以实现关闭浏览器过期效果,方向有了,是不是在代码中可以设置把凭据保存到Session中呢?
网上找了好长时间也没有关于sharepoint登录关闭浏览器过期怎么做。突然想到Sharepoint默认页面有一个Rember Me这个东西,我就想是不是和这个东西有关系。
找到Sharepoint的DLL,反编译一下看看代码:默认登录的代码在”Microsoft.SharePoint.IdentityModel.DLL”中。
SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current;
fam.SetPrincipalAndWriteSessionToken(_SecurityToken)
SetPrincipalAndWriteSessionToken方法有两个重载:
public void SetPrincipalAndWriteSessionToken(SecurityToken securityToken); public void SetPrincipalAndWriteSessionToken(SessionSecurityToken sessionToken, bool isSession);
一般时候网上提供的都是第一个,我们可以看出,第二个方法提供了是否使用Session来保存凭据,那么好了找到方向了。直接使用第二个重载就可以了。
当我写到“SessionSecurityToken”这个参数的时候,问题又来了,我们办法得到这个参数,参考微软的代码:
/// <summary> /// 获取SessionToken /// </summary> /// <param name="_SecurityToken"></param> /// <returns></returns> private static SessionSecurityTokenCreatedEventArgs GetSessionToken(SecurityToken _SecurityToken) { GenericXmlSecurityToken genericXmlSecurityToken = _SecurityToken as GenericXmlSecurityToken; if (genericXmlSecurityToken != null) { _SecurityToken = GetSecurityToken(genericXmlSecurityToken); } IClaimsPrincipal claimsPrincipal = AuthenticateUser(_SecurityToken); SessionSecurityTokenCreatedEventArgs sessionSecurityTokenCreatedEventArgs = new SessionSecurityTokenCreatedEventArgs(new SessionSecurityToken(claimsPrincipal, null, new DateTime?(tk.ValidFrom), new DateTime?(tk.ValidTo)) { IsPersistent = false }); return sessionSecurityTokenCreatedEventArgs; } /// <summary> /// 微软方法,获取SecurityToken,不清楚微软为什么这么做 /// </summary> /// <param name="token"></param> /// <returns></returns> internal static SecurityToken GetSecurityToken(GenericXmlSecurityToken token) { if (token == null) { throw new ArgumentNullException("token"); } SecurityToken result = null; SecurityTokenHandlerCollection securityTokenHandlerCollection = SecurityTokenHandlerCollection.CreateDefaultSecurityTokenHandlerCollection(); using (XmlNodeReader xmlNodeReader = new XmlNodeReader(token.TokenXml)) { result = securityTokenHandlerCollection.ReadToken(xmlNodeReader); } return result; } /// <summary> /// 获取声明 /// </summary> /// <param name="securityToken"></param> /// <returns></returns> internal static IClaimsPrincipal AuthenticateUser(SecurityToken securityToken) { if (securityToken == null) { throw new ArgumentNullException("securityToken"); } if (securityToken.SecurityKeys != null && securityToken.SecurityKeys.Count != 0) { throw new SecurityTokenException("Bearer token required."); } GenericXmlSecurityToken genericXmlSecurityToken = securityToken as GenericXmlSecurityToken; if (genericXmlSecurityToken != null) { securityToken = GetSecurityToken(genericXmlSecurityToken); } ServiceConfiguration serviceConfiguration = FederatedAuthentication.ServiceConfiguration; ClaimsIdentityCollection identityCollection = serviceConfiguration.SecurityTokenHandlers.ValidateToken(securityToken); string resourceName = null; if (HttpContext.Current != null) { resourceName = HttpContext.Current.Request.RawUrl; } return serviceConfiguration.ClaimsAuthenticationManager.Authenticate(resourceName, new ClaimsPrincipal(identityCollection)); }
最后正确调用方法:
SPFederationAuthenticationModule fam = SPFederationAuthenticationModule.Current; fam.SetPrincipalAndWriteSessionToken(sessionSecurityTokenCreatedEventArgs.SessionToken, true);
总结
要想实现关闭浏览器凭据过期我们需要把凭据存储在Session中,根据上面提供的代码获取SessionToken。
这个连接下的方法也不错。