基于ASP.NET 环境下的SSO Client包的资料:https://wiki.jasig.org/display/CASC/.Net+Cas+Client
在这个网站上可以下到编译过的dll文件,也可以下载源码进行研究和修改。
将dotnet-client-1.0-Bin.zip下载下来,解压以后,加载到自己的项目的bin中,然后,根据,dotnet-client-1.0-src.zip中的web.config.sample进行相应的参数修改,主要修改casServerLoginUrl,casServerUrlPrefix,serverName,loginUrl参数。
然后,连接本地的cas-server端,就可以成功地进行单点登录操作了。
但是,换成非本地的cas-server端进行调试的时候,出现了Authentication Failure的问题。查看DotNetCasClient.log,发现,在进行认证的时候,报了下面这个错误:
DotNetCasClient.Protocol Error: 3237 : Ticket validation error: DotNetCasClient.Validation.TicketValidationException: CAS ticket could not be validated. 在 DotNetCasClient.Validation.TicketValidator.Cas20ServiceTicketValidator.ParseResponseFromServer(String response, String ticket) 位置 E:/Test/DotNetCasClient/DotNetCasClient/Validation/TicketValidator/Cas20ServiceTicketValidator.cs:行号 144 在 DotNetCasClient.Validation.TicketValidator.AbstractUrlTicketValidator.Validate(String ticket) 位置 E:/Test/DotNetCasClient/DotNetCasClient/Validation/TicketValidator/AbstractUrlTicketValidator.cs:行号 167 在 DotNetCasClient.CasAuthentication.ProcessTicketValidation() 位置 E:/Test/DotNetCasClient/DotNetCasClient/CasAuthentication.cs:行号 739后来进行调试,发现,第一次进行跳转登录页面的时候,带的那个service参数,和之后,在进行验证时带的那个service参数不匹配。之后的那个参数中出现了多个ssoUrl拼接,导致了验证失败。
经过页面调试,最终发现是在DotNetCasClient/DotNetCasClient/Utils/UrlUtil.cs文件中的ConstructServiceUrl函数,在构建ServiceUrl时,进行了多次拼接。所以在ConstructServiceUrl函数中,在拼接url时,将ssoUrl这个参数直接remove掉,这样可以保证前后两个service参数的一致性,保证验证的成功。
不过本人认为,这只是一个治标不治本的办法,只能用来一时应急。应该还有更好的办法来解决这个问题。有兴趣的同道中人,可以一起讨论下。
修改过的ConstructServiceUrl函数如下:
/// <summary> /// Constructs a service URL using configured values in the following order: /// 1. if not empty, the value configured for Service is used /// - otherwise - /// 2. the value configured for ServerName is used together with HttpRequest /// data /// </summary> /// <remarks> /// The server name is not parsed from the request for security reasons, which /// is why the service and server name configuration parameters exist, per Jasig /// website. /// </remarks> /// <returns>the service URL to use, not encoded</returns> public static string ConstructServiceUrl(bool gateway) { CasAuthentication.Initialize(); HttpContext context = HttpContext.Current; HttpRequest request = context.Request; StringBuilder buffer = new StringBuilder(); if (!(CasAuthentication.ServerName.StartsWith("https://") || CasAuthentication.ServerName.StartsWith("http://"))) { buffer.Append(request.IsSecureConnection ? "https://" : "http://"); } buffer.Append(CasAuthentication.ServerName); EnhancedUriBuilder ub = new EnhancedUriBuilder(buffer.ToString()); ub.Path = request.Url.AbsolutePath; ub.QueryItems.Add(request.QueryString); ub.QueryItems.Remove(CasAuthentication.TicketValidator.ArtifactParameterName); ub.QueryItems.Remove("ssoUrl");//移除serviceurl中的ssoUrl参数 if (gateway) { ub.QueryItems.Set(CasAuthentication.GatewayParameterName, "true"); } else { ub.QueryItems.Remove(CasAuthentication.GatewayParameterName); } return ub.Uri.AbsoluteUri; }