原文链接地址: http://lsz1023-126-com.iteye.com/blog/2098973
实现原理:
一、 逻辑
客户端修改CAS Authentication Filter过滤器,该过滤器会判断用户是否登录,如果没有登录则跳转到自身配置的登录界面;
用户输入正确的信息,登录时,会被提交到服务端的登录流程中;
服务端通过新增一个remoteLogin处理类,专门处理客户端自定义登录业务;
该remoteLogin处理类与原始的login处理极为类似,只是修改了获取用户名与密码的方式;
如果用户名与密码不匹配,校验失败,会通过remoteCallbackView.jsp界面将错误提示与service一并响应给客户端的登录界面,接收之后将错误提示显示到界面上;
如果用户名与密码匹配,校验成功,会直接重定向到客户端的service页面,这时CAS Authentication Filter过滤器与CAS Validation Filter过滤器分别校验用户是否登录与ticket票据是否正确,完成最后的校验,否则要求用户重新登录。
二、 修改点
客户端
1. 修改web.xml,修改原先的CAS Authentication Filter过滤器
2. 新增RemoteAuthenticationFilter过滤器
3. 新增login.jsp
服务端
1. 修改web.xml,给cas过滤器添加remoteLogin servlet-mapping映射
2. 新增RemoteLoginAction登录处理类与AuthenticationViaFormAction表单处理类
3. 新增remoteLogin-webflow.xml自定义登录webflow流程文件
4. 修改cas-servlet.xml配置文件,新增一些bean配置
5. 新增remoteCallbackView.jsp响应界面,校验错误时用来通知客户端登录界面。
客户端篇:
1.替换原来过滤器org.jasig.cas.client.authentication.AuthenticationFilter,改成自己的过滤器RemoteAuthenticationFilter.java,这个过滤器可以自己随便放到哪个包中,保证web.xml能够正确引用到就行:
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(filterConfig, "renew", "false"))); log.trace("Loaded renew parameter: " + this.renew); setGateway(Boolean.parseBoolean(getPropertyFromInitParams(filterConfig, "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_GATEWAY, "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); // 加入localLoginUrl urlToRedirectTo += (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; } }
2.web.xml中配置:
旧配置
CAS Authentication Filter org.jasig.cas.client.authentication.AuthenticationFilter casServerLoginUrl https://localhost:8443/cas/login serverName http://localhost:8080 renew false gateway false
修改成这样,注:其它路径mapping不用改。
CAS Authentication Filter org.demo.user.common.RemoteAuthenticationFilter localLoginUrl http://localhost:8080/app/mylogin.jsp casServerLoginUrl https://localhost:8443/cas/remoteLogin serverName http://localhost:8080
3.加上你自己定义的登录界面,注:我修改了一些网上介绍的代码:
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%>APP1客户端登录 APP1客户端登录