java filter sso_src/com/xjj/sso/client/filter/SSOClientFilter.java · 新境界开源/xjj_sso_client - Gitee.co...

package com.xjj.sso.client.filter;

import java.io.IOException;

import java.io.PrintWriter;

import java.io.UnsupportedEncodingException;

import java.net.URLEncoder;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;

import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

import com.xjj.sso.client.pojo.RequestParameter;

import com.xjj.sso.client.rabbitmq.QueueConsumer;

import com.xjj.sso.client.session.SessionHandle;

import com.xjj.sso.client.user.SSOReceipt;

import com.xjj.sso.client.util.EncryptUtils;

import com.xjj.sso.client.SSOConstants;

import com.xjj.sso.client.util.SSOUtils;

public class SSOClientFilter implements Filter {

public static ConcurrentHashMap TICKET_SESSION_CACHE = new ConcurrentHashMap();

public static ConcurrentHashMap SESSION_TICKET_CACHE = new ConcurrentHashMap();

@Override

public void doFilter(ServletRequest req, ServletResponse resp,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpServletResponse response = (HttpServletResponse) resp;

String uri = request.getRequestURI();

String contextPath = request.getContextPath();

if(SSOUtils.isNotFilter(uri,contextPath))

{

chain.doFilter(request, response);

return;

}

String requestLogoutTicket = request.getParameter("requestLogout");

//如果是被动单点退出

if(SSOUtils.isNotBlank(requestLogoutTicket))

{

ssoLogout(requestLogoutTicket);

return;

}

//如果是客户端的单点登陆

if(uri.endsWith(SSOConstants.SSO_CLIENT_SSOLOGONURL))

{

ssoLogon(request,response);

return;

}

//如果已经登陆成功

Object receiptObj = request.getSession().getAttribute(SSOConstants.SSO_CLIENT_RECEIPT);

if(null != receiptObj)

{

chain.doFilter(request, response);

}else

{

//单点登陆验证

authentication(request, response, chain);

}

}

/**

* 单点登陆验证

* @param request

* @param response

* @throws IOException

* @throws ServletException

*/

private void authentication(HttpServletRequest request,HttpServletResponse response,FilterChain chain) throws IOException, ServletException

{

String ticket = request.getParameter("ticket");

//还没有ticket,说明还没有验证通过,去sso服务端去验证,并且记录当前请求的参数。

if(SSOUtils.isBlank(ticket))

{

Map pramMap = request.getParameterMap();

Map pramMapNew = new HashMap();

pramMapNew.putAll(pramMap);

String paramCode = null;

if(!pramMap.isEmpty())

{

String method = request.getMethod();

paramCode = RequestParameter.generateCode();

RequestParameter param = new RequestParameter();

param.setCode(paramCode);

param.setMethod(method);

param.setRequestPram(pramMapNew);

param.setAction(getService(request,null,false));

request.getSession().setAttribute("requestPram"+paramCode, param);

}

StringBuilder authUrl = new StringBuilder();

authUrl.append(SSOConstants.SSO_SERVER_AUTHENTICATION);

authUrl.append("?service=");

authUrl.append(getService(request,paramCode,true));

authUrl.append("&projectCode=");

authUrl.append(SSOConstants.SSO_CLIENT_PROJECTCODE);

System.out.println("=====================sso client authentication sendRedirect begin============================");

System.out.println("authUrl="+authUrl.toString());

System.out.println("=====================sso client authentication sendRedirect end==============================");

response.sendRedirect(authUrl.toString());

return;

}

else

{

//有ticket说明已经从服务端验证通过了,取得登陆信息,并且还原原来的请求场景

String ssoParamCode = request.getParameter("ssoParamCode");

String service = getService(request,ssoParamCode,false);

SSOReceipt receipt = SSOUtils.validateTicket(ticket, service);

System.out.println("---------------------sso client authentication validateTicket begin---------------------");

System.out.println("ticket="+ticket);

System.out.println("service="+service);

System.out.println("receipt="+receipt);

System.out.println("---------------------sso client authentication validateTicket end---------------------");

if(null == receipt)

{

StringBuilder authUrl = new StringBuilder();

authUrl.append(SSOConstants.SSO_SERVER_AUTHENTICATION);

authUrl.append("?service=");

authUrl.append(getService(request,null,true));

authUrl.append("&projectCode=");

authUrl.append(SSOConstants.SSO_CLIENT_PROJECTCODE);

//没有验证通过,再去重新验证。

response.sendRedirect(authUrl.toString());

return;

}

SessionHandle handle;

try {

handle = (SessionHandle) (Class.forName(SSOConstants.SSO_CLIENT_SESSIONHANDLE).newInstance());

handle.handle(request, receipt);

} catch (Exception e) {

e.printStackTrace();

}

TICKET_SESSION_CACHE.put(ticket, request.getSession());

SESSION_TICKET_CACHE.put(request.getSession().getId(), ticket);

//如果没有参数

if(SSOUtils.isBlank(ssoParamCode))

{

chain.doFilter(request, response);

}else

{

Object requestPramObj = request.getSession().getAttribute("requestPram"+ssoParamCode);

RequestParameter param = (RequestParameter)requestPramObj;

//还原原来的请求场景

//generateHtmlFormSubmit(param,request,response);

//生成跳转链接,直接调转,废弃模拟表单提交的方式,因为表单提交的方式会出现不友好的loading页面。

String ssoUrl = this.generateRedirectUrl(param);

request.getSession().removeAttribute("requestPram"+ssoParamCode);

response.sendRedirect(ssoUrl);

return;

}

}

}

/**

* 被动单点退出

* @param request

* @param response

*/

private void ssoLogout(String ticket){

if(TICKET_SESSION_CACHE.containsKey(ticket))

{

HttpSession sess = TICKET_SESSION_CACHE.get(ticket);

if(null != sess)

{

SESSION_TICKET_CACHE.remove(sess.getId());

sess.invalidate();

}

TICKET_SESSION_CACHE.remove(ticket);

}

}

/**

* 单点登陆(登陆窗口在客户端)

* @param request

* @param response

* @throws IOException

* @throws ServletException

*/

private void ssoLogon(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{

String ticket = request.getParameter("ticket");

String ssoerror = request.getParameter(SSOConstants.SSO_SERVER_ERROR);

//ssoerror不为空,说明已经从sso服务端登陆失败返回来了。

if(SSOUtils.isNotBlank(ssoerror))

{

String ssoParamCode = request.getParameter("ssoParamCode");

Object requestPramObj = request.getSession().getAttribute("requestPram"+ssoParamCode);

RequestParameter param = (RequestParameter)requestPramObj;

if(null != SSOConstants.SSO_CLIENT_LOGIN_ISREDIRECT && "false".equals(SSOConstants.SSO_CLIENT_LOGIN_ISREDIRECT))

{

//request.getSession().removeAttribute("requestPram"+ssoParamCode);

String loginUrl = request.getContextPath()+SSOConstants.SSO_CLIENT_LOGINURL;

//如果请求参数为空

if(null == requestPramObj)

{

response.sendRedirect(loginUrl);

return;

}

request.setAttribute(SSOConstants.SSO_SERVER_ERROR, ssoerror);

request.setAttribute("ssoLoginName", param.getParameter("loginName"));

request.setAttribute("ssoPassword", param.getParameter("password"));

request.getRequestDispatcher(loginUrl).forward(request, response);

return;

}

else

{

StringBuilder loginSB = new StringBuilder(request.getContextPath());

loginSB.append(SSOConstants.SSO_CLIENT_LOGINURL);

loginSB.append("?");

loginSB.append(SSOConstants.SSO_SERVER_ERROR);

loginSB.append("=");

loginSB.append(ssoerror);

loginSB.append("&ssoParamCode=");

loginSB.append(ssoParamCode);

//request.getSession().removeAttribute("requestPram"+ssoParamCode);

response.sendRedirect(loginSB.toString());

return;

}

}

//如果还没有验证

if(SSOUtils.isBlank(ticket))

{

//接收相关参数(必须的参数)传统登陆方式

String identity = request.getParameter("identity");

String password = request.getParameter("password");

String projectCode = SSOConstants.SSO_CLIENT_PROJECTCODE;

String backURL = request.getParameter("backURL");

if(SSOUtils.isBlank(identity) || SSOUtils.isBlank(password))

{

//不符合以上登陆方式,登陆失败

sendRedirect(request,response,SSOConstants.SSO_CLIENT_LOGINURL);

return;

}

String paramCode = RequestParameter.generateCode();

RequestParameter param = new RequestParameter();

//拼装参数信息

Map pramMap = new HashMap();

//密码加密传输

password = EncryptUtils.MD5Encode(password);

if(!SSOUtils.isBlank(identity))

{

pramMap.put("identity", new String[]{identity});

}

if(!SSOUtils.isBlank(password))

{

pramMap.put("password", new String[]{password});

}

pramMap.put("projectCode", new String[]{projectCode});

pramMap.put("service", new String[]{getService(request,paramCode,false)});

pramMap.put("backURL", new String[]{backURL});

param.setCode(paramCode);

param.setMethod("post");

param.setRequestPram(pramMap);

param.setAction(SSOConstants.SSO_SERVER_SIGNIN);

request.getSession().setAttribute("requestPram"+paramCode, param);

//拼装表单提交

//generateHtmlFormSubmit(param,request,response);

//生成跳转链接,直接调转,废弃模拟表单提交的方式,因为表单提交的方式会出现不友好的loading页面。

String ssoUrl = this.generateRedirectUrl(param);

response.sendRedirect(ssoUrl);

return;

}

//经过上面二层的判断,ticket不为空,说明已经从服务端验证通过了

String ssoParamCode = request.getParameter("ssoParamCode");

String service = getService(request,ssoParamCode,false);

SSOReceipt receipt = SSOUtils.validateTicket(ticket, service);

Object requestPramObj = request.getSession().getAttribute("requestPram"+ssoParamCode);

request.getSession().removeAttribute("requestPram"+ssoParamCode);

//如果请求参数为空

if(null == requestPramObj)

{

sendRedirect(request,response,SSOConstants.SSO_CLIENT_LOGINURL);

return;

}

RequestParameter param = (RequestParameter)requestPramObj;

//验证失败

if(null == receipt)

{

String loginName = param.getParameter("loginName");

String password = param.getParameter("password");

request.setAttribute(SSOConstants.SSO_SERVER_ERROR,"ticketerror");

request.setAttribute("loginName",loginName);

request.setAttribute("password",password);

request.getRequestDispatcher(SSOConstants.SSO_CLIENT_LOGINURL).forward(request, response);

return;

}

SessionHandle handle;

try {

handle = (SessionHandle) (Class.forName(SSOConstants.SSO_CLIENT_SESSIONHANDLE).newInstance());

handle.handle(request, receipt);

} catch (Exception e) {

e.printStackTrace();

}

//缓存ticket 和 session

TICKET_SESSION_CACHE.put(ticket, request.getSession());

SESSION_TICKET_CACHE.put(request.getSession().getId(), ticket);

//转向成功地址

String backURL = param.getParameter("backURL");

if(SSOUtils.isNotBlank(backURL))

{

sendRedirect(request,response,backURL);

}else

{

sendRedirect(request,response,SSOConstants.SSO_CLIENT_LOGINURL);

}

}

/**

* 获得service

* @param request

* @param paramCode

* @param encode

* @return

* @throws UnsupportedEncodingException

*/

private String getService(HttpServletRequest request,String paramCode,boolean encode) throws UnsupportedEncodingException{

StringBuffer sb = new StringBuffer();

sb.append(request.getScheme()+"://");

if(null == SSOConstants.SSO_CLIENT_SERVERNAME || "".equals(SSOConstants.SSO_CLIENT_SERVERNAME))

{

sb.append(request.getServerName());

}

else

{

sb.append(SSOConstants.SSO_CLIENT_SERVERNAME);

}

if(!"80".equals(request.getServerPort()))

{

sb.append(":");

sb.append(request.getServerPort());

}

sb.append(request.getRequestURI());

if(SSOUtils.isNotBlank(paramCode))

{

sb.append("?ssoParamCode="+paramCode);

}

if(encode)

{

String encodedService = URLEncoder.encode(sb.toString(),"utf-8");

return encodedService;

}else

{

return sb.toString();

}

}

/**

* 获得service

* @param request

* @param paramCode

* @param encode

* @return

* @throws UnsupportedEncodingException

*/

private String getService_bak(HttpServletRequest request,String paramCode,boolean encode) throws UnsupportedEncodingException{

StringBuffer sb = new StringBuffer();

sb.append(SSOConstants.HTTP_PRE);

sb.append(SSOConstants.SSO_CLIENT_SERVERNAME);

sb.append(request.getRequestURI());

if(SSOUtils.isNotBlank(paramCode))

{

sb.append("?ssoParamCode="+paramCode);

}

if(encode)

{

String encodedService = URLEncoder.encode(sb.toString(),"utf-8");

return encodedService;

}else

{

return sb.toString();

}

}

/**生成重定向url链接

*

* @param param

* @return

*/

private String generateRedirectUrl(RequestParameter param)

{

StringBuilder urlBuff = new StringBuilder();

urlBuff.append(param.getAction());

Set paramSet = param.getRequestPram().keySet();

String paramName = null;

String[] paramValues = null;

int idx = 0;

for (Iterator iterator = paramSet.iterator(); iterator.hasNext();) {

paramName = iterator.next();

paramValues = param.getRequestPram().get(paramName);

for(int i=0;i

{

if(i == 0 && idx ==0 && param.getAction().indexOf("?")<0)

{

urlBuff.append("?");

}else

{

urlBuff.append("&");

}

urlBuff.append(paramName);

urlBuff.append("=");

if (paramValues[i].contains("http")

|| paramValues[i].contains("#")

|| paramValues[i].contains("=")

|| paramValues[i].contains("&")

|| paramValues[i].contains("+")

|| paramValues[i].contains(".")

|| paramValues[i].contains("%"))

{

try {

urlBuff.append(java.net.URLEncoder.encode(paramValues[i],"utf-8"));

} catch (UnsupportedEncodingException e) {

e.printStackTrace();

}

}else

{

urlBuff.append(paramValues[i]);

}

}

idx ++;

}

return urlBuff.toString();

}

/**

* 根据相关参数生成表单提交html代码

* @param param

* @param request

* @param response

* @throws IOException

*/

private void generateHtmlFormSubmit(RequestParameter param,HttpServletRequest request,HttpServletResponse response) throws IOException

{

response.setContentType("text/html");

response.setCharacterEncoding("UTF-8");

PrintWriter out = response.getWriter();

out.println(""-//W3C//DTD HTML 4.01 Transitional//EN\">");

out.println("");

out.println("

");

out.println("");

out.println("

loading...");

out.println("

out.println("var i = 0;");

out.println("var s = \"loading\";");

out.println("function addPoint(){ ");

out.println("if(i<6){");

out.println("s += \".\";");

out.println("document.getElementById(\"point\").innerHTML = s;");

out.println("i++; ");

out.println("}else{ s = \"loading\";");

out.println("document.getElementById(\"point\").innerHTML = s;");

out.println("i = 0; ");

out.println("}}");

out.println("function loadPoint(){ window.setInterval(\"addPoint()\",200);}");

out.println("");

out.println("");

out.println("

");

out.println("

");

Set paramSet = param.getRequestPram().keySet();

String paramName = null;

String[] paramValues = null;

for (Iterator iterator = paramSet.iterator(); iterator.hasNext();) {

paramName = iterator.next();

paramValues = param.getRequestPram().get(paramName);

for(int i=0;i

{

out.println(" ");

}

}

out.println("

");

//添加等待loading begin

out.println("

");

out.println("

");

out.println("loading......");

out.println("

");

//添加等待loading end

out.println(" ");

out.println("");

out.println("

out.println("window.document.forms[0].submit();");

out.println("");

out.flush();

out.close();

}

/**

* 客户端跳转

* @param request

* @param response

* @param url

* @throws IOException

*/

private void sendRedirect(HttpServletRequest request,HttpServletResponse response,String url) throws IOException

{

if(SSOUtils.isBlank(url))

{

return;

}

if(url.startsWith(SSOConstants.HTTP_PRE) || url.startsWith(SSOConstants.HTTPS_PRE))

{

response.sendRedirect(url);

return;

}

response.sendRedirect(request.getContextPath()+url);

}

@Override

public void init(FilterConfig filterConfig) throws ServletException {

//如果通知类型为rabbitmq

if(SSOConstants.SSO_NOTIFICATION_TYPE.equals("rabbitmq"))

{

try {

//启动mq 消费线程

QueueConsumer consumer = new QueueConsumer("sso.*");

Thread consumerThread = new Thread(consumer);

consumerThread.start();

} catch (Exception e) {

System.out.println("启动mq线程报错");

e.printStackTrace();

}

}

}

@Override

public void destroy() {

}

}

一键复制

编辑

Web IDE

原始数据

按行查看

历史

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值