CAS之四--CAS客户端接入
CAS官方支持了JAVA、.NET和PHP客户端程序接入支持,其他语言如Python,可以找找非官方的支持。 本章节是编写最简单版本客户端接入。
接入的方式一般有两种:
1、旧系统接入CAS,根据CAS登录后的Ticket完成用户免登录
2、新系统接入CAS,使用全局拦截器进行CAS身份认证
本文使用的是第一种方式,可在不改动原有认证逻辑的基础上,接入单点登录,接入成本较低。
一、.Net客户端
.Net接入可以使用DotNetCasClient。
配置一
<configSections> <section name="casClientConfig" type="DotNetCasClient.Configuration.CasClientConfiguration, DotNetCasClient" /> </configSections>
<casClientConfig casServerLoginUrl="http://localhost:8080/cas/login" casServerUrlPrefix="http://localhost:8080/cas/" serverName="http://localhost:6858" cookiesRequiredUrl="~/CookiesRequired.aspx" redirectAfterValidation="true" gateway="false" renew="false" singleSignOut="true" ticketTimeTolerance="5000" ticketValidatorName="Cas20" serviceTicketManager="CacheServiceTicketManager" gatewayStatusCookieName="CasGatewayStatus" />
配置二
<system.web> <authentication mode="Forms"> <forms name=".DotNetCasClientAuth" loginUrl="http://localhost:8080/cas/login" cookieless="UseCookies" /> </authentication> <compilation debug="true" targetFramework="4.5" /> <httpRuntime targetFramework="4.5" /> <httpModules> <add name="DotNetCasClient" type="DotNetCasClient.CasAuthenticationModule,DotNetCasClient" /> </httpModules> </system.web>
编写CasClientHelper帮助类,当然也可以使用内置httpModules的方式进行全局验证
public class CasClientHelper { public static CasAuthenticationTicket GetCasAuthenticationTicket(HttpRequestBase request) { CasAuthenticationTicket casTicket = null; var ticketCookie = request.Cookies[FormsAuthentication.FormsCookieName]; if (ticketCookie != null && !string.IsNullOrWhiteSpace(ticketCookie.Value)) { var ticket = FormsAuthentication.Decrypt(ticketCookie.Value); if (ticket != null && CasAuthentication.ServiceTicketManager != null) { casTicket = CasAuthentication.ServiceTicketManager.GetTicket(ticket.UserData); } } return casTicket; } }
二、.NetCore客户端
项目引入GSS.Authentication.CAS.AspNetCore,在Startup文件中注入CAS配置
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme) .AddCAS<CasAuthenticationOptions, CasAuthenticationHandler>(CasDefaults.AuthenticationType, options => { options.CasServerUrlBase = Configuration["CASConfig:ServerUrlBase"]; // required for CasSingleLogoutMiddleware //options.SaveTokens = true; var protocolVersion = Configuration.GetValue("CASConfig:ProtocolVersion", 3); if (protocolVersion != 3) { options.ServiceTicketValidator = protocolVersion switch { 1 => new Cas10ServiceTicketValidator(options), 2 => new Cas20ServiceTicketValidator(options), _ => null }; } options.Events.OnCreatingTicket = context => { if (context.Identity == null) { return Task.CompletedTask; } var assertion = context.Assertion; context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, assertion.PrincipalName)); return Task.CompletedTask; }; options.Events.OnRemoteFailure = context => { var failure = context.Failure; if (!string.IsNullOrWhiteSpace(failure?.Message)) { ServiceProvideHelper.GetService<ILogger<Startup>>().LogError(failure, "{Exception}", failure.Message); } context.Response.Redirect("/Account/ExternalLoginFailure"); context.HandleResponse(); return Task.CompletedTask; }; });
编写登录控制器,自动跳转到CAS登录页,带上登录成功后的回调地址,CAS回调后,通过User.Claims获取返回的对应的UserID,实现自动免登录。
[AllowAnonymous] [HttpGet] public IActionResult LoginCAS(string returnUrl) { return Challenge(new AuthenticationProperties { RedirectUri = $"/api/Account/LoginCASCallBack?returnUrl={HttpUtility.UrlEncode(returnUrl)}" }, CasDefaults.AuthenticationType); }