Package com.github.ebnew.ki4so.client.web.filters

Source Code of com.github.ebnew.ki4so.client.web.filters.Ki4soClientFilter

package com.github.ebnew.ki4so.client.web.filters;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.github.ebnew.ki4so.common.utils.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import com.github.ebnew.ki4so.client.handler.AppClientLoginHandler;
import com.github.ebnew.ki4so.client.key.DefaultKeyServiceImpl;
import com.github.ebnew.ki4so.core.authentication.EncryCredential;
import com.github.ebnew.ki4so.core.authentication.EncryCredentialManagerImpl;
import com.github.ebnew.ki4so.core.key.KeyService;
import com.github.ebnew.ki4so.core.key.Ki4soKey;
import com.github.ebnew.ki4so.core.model.EncryCredentialInfo;
import com.github.ebnew.ki4so.web.utils.WebConstants;

/**
* ki4so客户端应用的过滤器,从而实现集成ki4so单点登录系统。
* 此过滤器必须安装或者自己实现。
* @author Administrator
*/
public class Ki4soClientFilter extends BaseClientFilter {
 
  private static Logger logger = Logger.getLogger(Ki4soClientFilter.class.getName());
 
  /**
   * 在客户端的session中的用户信息,避免频繁认证,提高性能。
   */
  public static final String USER_STATE_IN_SESSION_KEY = "ki4so_client_user_info_session_key";
 
 
 
  /**
   * ki4so服务器登录URL地址。
   */
  protected String ki4soServerLoginUrl = ki4soServerHost+"login.do";
 
  /**
   * ki4so服务器获取应用秘钥信息的URL地址。
   */
  protected String ki4soServerFetchKeyUrl = ki4soServerHost+"fetchKey.do";
 
  /**
   * 本应用在ki4so服务器上的应用ID值。
   */
  protected String ki4soClientAppId = "1001";
 
  /**
   * 登录本应用处理器类,由此类进行构造一个对象。
   */
  protected String appClientLoginHandlerClass = "com.github.ebnew.ki4so.app.custom.Ki4soAppClientLoginHandlerImpl";
 
 
  /**
   * 本应用对应的加密key.
   */
  protected Ki4soKey ki4soKey;
 
  /**
   * 秘钥获取服务。
   */
  protected KeyService keyService = null;
 
  /**
   * 凭据管理器。
   */
  protected EncryCredentialManagerImpl encryCredentialManager;
 
  /**
   * 登录本应用的处理器。
   */
  protected AppClientLoginHandler appClientLoginHandler;
 

  @Override
  public void doInit(FilterConfig filterConfig) throws ServletException {
    ki4soClientAppId = getInitParameterWithDefalutValue(filterConfig, "ki4soClientAppId", ki4soClientAppId);
    ki4soServerLoginUrl = getInitParameterWithDefalutValue(filterConfig, "ki4soServerLoginUrl", ki4soServerHost+"login.do");;
    ki4soServerFetchKeyUrl = getInitParameterWithDefalutValue(filterConfig, "ki4soServerFetchKeyUrl", ki4soServerHost+"fetchKey.do");
    appClientLoginHandlerClass = getInitParameterWithDefalutValue(filterConfig, "appClientLoginHandlerClass", appClientLoginHandlerClass);
    //构造key服务等相关对象。
    //构造登录本应用的处理器对象。
    if(!StringUtils.isEmpty(appClientLoginHandlerClass)){
      try{
        this.appClientLoginHandler = (AppClientLoginHandler)Class.forName(appClientLoginHandlerClass).newInstance();
      }catch (Exception e) {
        // TODO: handle exception
      }
    }
    keyService = new DefaultKeyServiceImpl(ki4soServerFetchKeyUrl, ki4soClientAppId);
    this.encryCredentialManager = new EncryCredentialManagerImpl();
    this.encryCredentialManager.setKeyService(keyService);
    logger.info("the ki4so sever is :"+this.ki4soServerHost+", please check this service is ok.");
  }

 
  @Override
  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain) throws IOException, ServletException {
    HttpServletResponse servletResponse = (HttpServletResponse)response;
    HttpServletRequest servletRequest = (HttpServletRequest)request;
    HttpSession session = servletRequest.getSession();
    try{
      //本地应用未登录。
      if(session.getAttribute(USER_STATE_IN_SESSION_KEY)==null){
        //查找参数中是否存在ki4so_client_ec值,若没有则重定向到登录页面。
        String ki4so_client_ec = getClientEC(servletRequest);
        if(StringUtils.isEmpty(ki4so_client_ec)){
          //跳转到Ki4so登录页面。
          servletResponse.sendRedirect(buildRedirectToKi4soServer(servletRequest));
          return;
        }
        //如果没有key,则重试获取一次。
        if(ki4soKey==null){
          try{
            ki4soKey = keyService.findKeyByAppId(ki4soClientAppId);
          }catch (Exception e) {
            logger.log(Level.SEVERE, "fetch ki4so key info error", e);
          }
        }
        //解密凭据信息。
        EncryCredentialInfo encryCredentialInfo = this.encryCredentialManager.decrypt(new EncryCredential(ki4so_client_ec));
        if(encryCredentialInfo!=null){
          //检查凭据合法性。
          boolean valid = this.encryCredentialManager.checkEncryCredentialInfo(encryCredentialInfo);
          //如果合法,则继续其它处理。
          if(valid){
            //设置登录状态到session中。
            session.setAttribute(USER_STATE_IN_SESSION_KEY, encryCredentialInfo);
            //触发登录本应用的处理。
            if(appClientLoginHandler!=null){
              //登录本应用。
              appClientLoginHandler.loginClient(encryCredentialInfo, servletRequest, servletResponse);
            }
           
            //重新定位到原请求,去除EC参数。
            String url = servletRequest.getRequestURL().toString();
            if(!StringUtils.isEmpty(url)){
              //如果请求中存在EC参数,则去除这个参数,重定位。
              if(url.contains(WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY)){
                url = url.substring(0, url.indexOf(WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY));
                //去除末尾的问号。
                if(url.endsWith("?")){
                  url = url.substring(0, url.length()-1);
                }
               
                //去除末尾的&符号。
                if(url.endsWith("&")){
                  url = url.substring(0, url.length()-1);
                }
              }
            }
            //登录成功后,写入EC到cookie中。
            writeEC(ki4so_client_ec, servletResponse);
           
            //重新定位请求,避免尾部出现长参数。
            servletResponse.sendRedirect(url);
            return;
          }
        }
        //否则凭据信息不合法,跳转到Ki4so登录页面。
        servletResponse.sendRedirect(buildRedirectToKi4soServer(servletRequest));
        return;
      }
     
      //若已经登录过,则直接返回,继续其它过滤器。
      chain.doFilter(request, response);
      return;
    }
    //处理异常信息。
    catch (Exception e) {
      removeCookeEC(servletRequest, servletResponse);
     
      //否则凭据信息不合法,跳转到Ki4so登录页面。
      servletResponse.sendRedirect(buildRedirectToKi4soServer(servletRequest));
      return;
    }
   
  }
 
  protected String buildRedirectToKi4soServer(HttpServletRequest servletRequest){
    StringBuffer sb = new StringBuffer(this.ki4soServerLoginUrl);
    if(this.ki4soServerLoginUrl.contains("?")){
      sb.append("&");
    }
    else{
      sb.append("?");
    }
    sb.append("service=").append(servletRequest.getRequestURL().toString());
    return sb.toString();
  }

  @Override
  public void destroy() {
    this.ki4soKey = null;
  }
 
 
  /**
   * 从客户端参数或者cookie中获取EC值。
   * @param request http请求对象。
   * @return EC值。
   */
  protected String getClientEC(HttpServletRequest request){
    String ec = null;
    if(request!=null){
      ec = request.getParameter(WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY);
      //再从cookie中获取值。
      if(StringUtils.isEmpty(ec)){
        Cookie cookie = getCookie(request, WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY);
        if(cookie!=null){
          ec = cookie.getValue().trim();
        }
      }
    }
    return ec;
  }
 
  /**
   * 将EC的值写入到服务器的cookie中。
   * @param ec EC值。
   * @param response Http响应对象。
   */
  protected void writeEC(String ec, HttpServletResponse response){
    //使用URL进行编码,避免写入cookie错误。
    try {
      ec = URLEncoder.encode(ec, "UTF-8");
      response.addCookie(new Cookie(
          WebConstants.KI4SO_CLIENT_ENCRYPTED_CREDENTIAL_COOKIE_KEY, ec));
    } catch (UnsupportedEncodingException e) {
      logger.log(Level.SEVERE, "encode with URL error", e);
    }
   
  }
 
}
TOP

Related Classes of com.github.ebnew.ki4so.client.web.filters.Ki4soClientFilter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.