让CAS支持客户端自定义登陆页面——客户端篇

  • 格式:doc
  • 大小:46.50 KB
  • 文档页数:7

客户端实现目标客户端实现主要需要满足5个case:∙ 1. 用户未在中央认证服务器登陆,访问客户端受保护资源时,客户端重定向到中央认证服务器请求TGT认证,认证失败,转回客户端登陆页面,保证受保护资源URL信息不丢失∙ 2. 用户未在中央认证服务器登陆,访问客户端登陆页面时,客户端重定向到中央认证服务器请求TGT认证,认证失败,转回客户端登陆页面,此次登录页面不再受保护,允许访问∙ 3. 用户已在中央认证服务器登陆,访问客户端受保护资源时,客户端重定向到中央认证服务器请求TGT认证,认证成功,直接转回受保护资源∙ 4. 用户在客户端登陆页面提交用户名密码,客户端将用户名密码信息提交给服务器端,认证失败,转回客户端登陆页面,携带失败信息并保证转到登陆页面前受保护资源URL信息不丢失∙ 5. 用户在客户端登陆页面提交用户名密码,客户端将用户名密码信息提交给服务器端,认证成功,转回转到登陆页面前受保护资源对于case 1和case 3,普通的CAS客户端即可满足需求,但对于case 4和case 5,则需要我们定制自己的登陆页面。

对于case 2,主要是需要满足部分登陆页面希望在用户未登陆状态显示登陆框,在已登陆状态显示用户欢迎信息的需求,实现这个需求我们是通过让CAS客户端认证器满足一个排除约定,即当用户请求路径为登陆页面且带有validated=true的参数时,即不进行重定向TGT认证请求客户端修改方案远程客户端修改,对于任何一种客户端方案都可以实现,这里为了简单起见,我们给出的修改方案基于CAS官方提供的Java客户端3.1.3。

首先我们使用CAS Client 3.1.3搭建一个CAS客户端,具体搭建方法可以参考CAS官网:CAS Client for Java 3.1根据服务器流程修改方案,我们可以知道,所有的远程请求都必须携带有loginUrl参数信息以使得服务器端知道在认证失败后转向客户端登陆页面。

而在CAS客户端上,上一节的case 4和case 5,我们主要通过提交表单的方式传递loginUrl,而case 1, case 3则是依靠org.jasig.cas.client.authentication.AuthenticationFilter类进行的转向,但使用AuthenticationFilter转向时,是没有loginUrl信息的,因此我们首先需要重新实现一个自己的认证过滤器,以下是我们自己的认证过滤器的代码:/*** 远程认证过滤器.* 由于AuthenticationFilter的doFilter方法被声明为final,* 只好重新实现一个认证过滤器,支持localLoginUrl设置.** @author GuoLin**/public class RemoteAuthenticationFilter extends AbstractCasFilter {public static final String CONST_CAS_GATEWAY ="_const_cas_gateway_";/*** 本地登陆页面URL.*/private String localLoginUrl;/*** The URL to the CAS Server login.*/private String casServerLoginUrl;/*** Whether to send the renew request or not.*/private boolean renew = false;/*** Whether to send the gateway request or not.*/private boolean gateway = false;protected void initInternal(final FilterConfig filterConfig) throws ServletException {super.initInternal(filterConfig);setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));log.trace("Loaded CasServerLoginUrl parameter: " +this.casServerLoginUrl);setLocalLoginUrl(getPropertyFromInitParams(filterConfig, "localLoginUrl", null));log.trace("Loaded LocalLoginUrl parameter: " +this.localLoginUrl);setRenew(Boolean.parseBoolean(getPropertyFromInitParams(filte rConfig, "renew", "false")));log.trace("Loaded renew parameter: " + this.renew);setGateway(Boolean.parseBoolean(getPropertyFromInitParams(fil terConfig, "gateway", "false")));log.trace("Loaded gateway parameter: " + this.gateway);}public void init() {super.init();CommonUtils.assertNotNull(this.localLoginUrl, "localLoginUrl cannot be null.");CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");}public final void doFilter(final ServletRequest servletRequest,final ServletResponse servletResponse, final FilterChain filterChain)throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) servletRequest;final HttpServletResponse response = (HttpServletResponse) servletResponse;final HttpSession session = request.getSession(false);final String ticket =request.getParameter(getArtifactParameterName());final Assertion assertion = session != null ? (Assertion) session .getAttribute(CONST_CAS_ASSERTION) : null;final boolean wasGatewayed = session != null&& session.getAttribute(CONST_CAS_GATEWAY) != null;// 如果访问路径为localLoginUrl且带有validated参数则跳过URL url = new URL(localLoginUrl);final boolean isValidatedLocalLoginUrl =request.getRequestURI().endsWith(url.getPath()) &&CommonUtils.isNotBlank(request.getParameter("validated"));if (!isValidatedLocalLoginUrl && CommonUtils.isBlank(ticket) && assertion == null && !wasGatewayed) {log.debug("no ticket and no assertion found");if (this.gateway) {log.debug("setting gateway attribute in session");request.getSession(true).setAttribute(CONST_CAS_GATEW AY, "yes");}final String serviceUrl = constructServiceUrl(request, response);if (log.isDebugEnabled()) {log.debug("Constructed service url: " + serviceUrl); }String urlToRedirectTo = CommonUtils.constructRedirectUrl( this.casServerLoginUrl, getServiceParameterName(), serviceUrl, this.renew, this.gateway);// 加入localLoginUrlurlToRedirectTo += (urlToRedirectTo.contains("?") ? "&" : "?") + "loginUrl=" + URLEncoder.encode(localLoginUrl, "utf-8");if (log.isDebugEnabled()) {log.debug("redirecting to \"" + urlToRedirectTo + "\""); }response.sendRedirect(urlToRedirectTo);return;}if (session != null) {log.debug("removing gateway attribute from session");session.setAttribute(CONST_CAS_GATEWAY, null);}filterChain.doFilter(request, response);}public final void setRenew(final boolean renew) {this.renew = renew;}public final void setGateway(final boolean gateway) {this.gateway = gateway;}public final void setCasServerLoginUrl(final String casServerLoginUrl) {this.casServerLoginUrl = casServerLoginUrl;}public final void setLocalLoginUrl(String localLoginUrl) {this.localLoginUrl = localLoginUrl;}}以上粗体代码为修改部分,其余代码均拷贝自org.jasig.cas.client.authentication.AuthenticationFilter,可以看到我们为原有的认证过滤器增加了一个参数localLoginUrl。