2019-05-26_SSO单点登录知识学习

SSO单点登录知识学习

1.概述

SSO(Single Sign On)单点登录是实现多个系统之间统一登录的验证系统,简单来说就是:有A,B,C三个系统,在A处登录过后,再访问B系统,B系统就已经处于了登录状态,C系统也是一样。

SSO简单来说就是一句话:一处登录,全部访问。下图是网上的一个关于SSO登录流程的图:

[图片上传失败...(image-2e5d17-1558878674308)]

1.1.登录流程跟踪分析

1.1.1.首次登录

Ssoclient:

[2019-05-26 20:58:53]http-apr-8585-exec-3-00039:[ssoclient]doFilter,getRequestURL:http://localhost:8585/webapp1/

Ssoclient:

[2019-05-26 20:59:18]http-apr-8585-exec-6-00042:[ssoclient]doFilter,getRequestURL:http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 20:59:18]http-apr-8585-exec-6-00042:[ssoclient]redirectUrl:http://localhost:8080/TechnicalAbilityToolBox?action=preLogin&setCookieURL=http://localhost:8585/webapp1/setCookie&gotoURL=http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 20:59:18]http-apr-8585-exec-6-00042:[ssoclient]not find cookie!

Ssoserver:

[2019-05-26 20:59:26]http-apr-8080-exec-3-00039:[ssoserver]doFilter,getRequestURL:http://localhost:8080/TechnicalAbilityToolBox/setCookie

[2019-05-26 20:59:26]http-apr-8080-exec-3-00039:[ssoserver]redirectUrl:http://localhost:8080/TechnicalAbilityToolBox?action=preLogin&setCookieURL=http://localhost:8080/TechnicalAbilityToolBox/setCookie&gotoURL=http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 20:59:26]http-apr-8080-exec-3-00039:[ssoserver]not find cookie!

[2019-05-26 20:59:26]http-apr-8080-exec-3-00039:[ssoserver]setCookie...

[2019-05-26 20:59:26]http-apr-8080-exec-3-00039:[ssoserver]setCookie ok,gotoUrl:http://localhost:8585/webapp1/sysmainpage.jsp

Ssoclient:

[2019-05-26 20:59:26]http-apr-8585-exec-8-00044:[ssoclient]doFilter,getRequestURL:http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 20:59:26]http-apr-8585-exec-8-00044:[ssoclient]redirectUrl:http://localhost:8080/TechnicalAbilityToolBox?action=preLogin&setCookieURL=http://localhost:8585/webapp1/setCookie&gotoURL=http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 20:59:26]http-apr-8585-exec-8-00044:[ssoclient]find cookie!

[2019-05-26 20:59:26]http-apr-8585-exec-8-00044:[ssoclient]authCookie...

[2019-05-26 20:59:26]http-apr-8585-exec-8-00044:[ssoclient]executeSSOPost...

Ssoserver:

[2019-05-26 20:59:26]http-apr-8080-exec-5-00041:[ssoserver]postAuth begin...

[2019-05-26 20:59:26]http-apr-8080-exec-5-00041:[ssoserver]postAuth end!

Ssoclient:

26-May-2019 20:59:26.420 WARNING [http-apr-8585-exec-8] org.apache.commons.httpclient.HttpMethodBase.getResponseBody Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.

[2019-05-26 20:59:26]http-apr-8585-exec-8-00044:[ssoclient]executeSSOPost ok!

[2019-05-26 21:00:37]http-apr-8585-exec-2-00038:[ssoclient]chain.doFilter(request, response) end!

1.1.2.二次登录

Ssoclient:

[2019-05-26 21:04:28]http-apr-8585-exec-10-00046:[ssoclient]doFilter,getRequestURL:http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 21:04:28]http-apr-8585-exec-10-00046:[ssoclient]redirectUrl:http://localhost:8080/TechnicalAbilityToolBox?action=preLogin&setCookieURL=http://localhost:8585/webapp1/setCookie&gotoURL=http://localhost:8585/webapp1/sysmainpage.jsp

[2019-05-26 21:04:28]http-apr-8585-exec-10-00046:[ssoclient]find cookie!

[2019-05-26 21:04:28]http-apr-8585-exec-10-00046:[ssoclient]authCookie...

[2019-05-26 21:04:28]http-apr-8585-exec-10-00046:[ssoclient]executeSSOPost...

Ssoserver:

[2019-05-26 21:04:28]http-apr-8080-exec-7-00043:[ssoserver]postAuth begin...

[2019-05-26 21:04:28]http-apr-8080-exec-7-00043:[ssoserver]postAuth end!

Ssoclient:

26-May-2019 21:04:28.390 WARNING [http-apr-8585-exec-10] org.apache.commons.httpclient.HttpMethodBase.getResponseBody Going to buffer response body of large or unknown size. Using getResponseBodyAsStream instead is recommended.

[2019-05-26 21:04:28]http-apr-8585-exec-10-00046:[ssoclient]executeSSOPost ok!

[2019-05-26 21:05:37]http-apr-8585-exec-2-00038:[ssoclient]chain.doFilter(request, response) end!

2.****sso登录代码****分析

1.1.sso server

1.1.1.ssoLogin.jsp

<%--

Created by IntelliJ IDEA.

User: kikop

Date: 2019/5/21

Time: 8:02

To change this template use File | Settings | File Templates.

--%>

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>

<%--引入 jstl 标签--%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%--取出部署的应用程序名或者是当前的项目名称,等价于 request.getContextPath()--%>

<c:set var="contextPath" value="${pageContext.request.contextPath}" scope="page"/>

<c:set var="gotoURL" value="${pageContext.request.getParameter('gotoURL')}" scope="page"/>

<html>

<body>

<h2>1.获取页面的gotoURL</h2>

<h2>2.输入账号进行sso登录</h2>

<h2>3.登录生成token,并返回业务系统</h2>

<h3>业务系统跳转地址:${gotoURL}</h3>

<%--获取页面的gotoURL=http://localhost:8585/webapp1/syspage.html--%>

<%--<a href="http://localhost:8080/TechnicalAbilityToolBox/setCookie?gotoURL=http://localhost:8585/webapp1/syspage.html">登录</a>--%>

<%--生成ticket和expiry--%>

<a href="http://localhost:8080/TechnicalAbilityToolBox/setCookie?gotoURL=${gotoURL}&ticket=hello&expiry=1800">登录</a>

</body>

</html>

1.1.2.****SSOServerAuth****Filter

package com.tech.ability.myssoserver;

import com.tech.ability.util.DateUtil;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.HttpStatus;

import org.apache.commons.httpclient.NameValuePair;

import org.apache.commons.httpclient.methods.PostMethod;

import org.json.JSONException;

import org.json.JSONObject;

import javax.servlet.*;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.util.UUID;

/**

  • 单点登录管理中心服务端过滤器

  • <p>

  • Created by kikop on 2017/9/17.

*/

public class SSOServerAuth implements Filter {

private String ssoServerUrl;

private String ssoServerName;

/**

 * 初始化

 *

 * @param filterConfig

 * @throws ServletException

 */

@Override

public void init(FilterConfig filterConfig) throws ServletException {

    //1.获取本机sso配置文件信息

    this.ssoServerUrl = filterConfig.getInitParameter("ssoServerUrl");

    this.ssoServerName = filterConfig.getInitParameter("ssoServerName");

}

/**

 * 销毁

 */

@Override

public void destroy() {

}

/**

 * 1.拦截请求

 *

 * @param servletRequest

 * @param servletResponse

 * @param filterChain

 * @throws IOException

 * @throws ServletException

 */

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    //1.强转

    HttpServletRequest request = (HttpServletRequest) servletRequest;

    HttpServletResponse response = (HttpServletResponse) servletResponse;

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]doFilter,getRequestURL:"+request.getRequestURL()));

    //2.操作

    //2.1.得到请求资源路径

    String contextPath = request.getContextPath();   //请求服务名: /TechnicalAbilityToolBox

    String gotoURL = request.getParameter("gotoURL");  //webapp1的实际请求地址: /webapp1/syspage.html

    if (gotoURL == null) {  //获取请求页面本身

        gotoURL = request.getRequestURL().toString();  //返回全路径: http://localhost:8080/TechnicalAbilityToolBox/login.jsp

    }

    String redirectUrl = ssoServerUrl + "?action=preLogin&setCookieURL=" + request.getScheme() + "://"

            + request.getServerName() + ":" + request.getServerPort()

            + contextPath + "/setCookie&gotoURL=" + gotoURL;

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]redirectUrl:"+redirectUrl));

    //2.2.管理中心token的验证核心思路获取指定cookie

    Cookie currentCookie = null;

    Cookie[] cookies = request.getCookies();  //获取客户端的所有cookie,kk

    boolean isFindCookie = false;

    if (cookies != null) {

        for (Cookie cookie : cookies) {

            if (cookie.getName().equals(ssoServerName)) {

                currentCookie = cookie;

                isFindCookie = true;

                System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]find cookie!"));

                break;

            }

        }

    }

    if (!isFindCookie) {

        System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]not find cookie!"));

    }

    //3.放行,注意这里的逻辑顺序(命令优先)

    if (request.getRequestURI().equals(contextPath + "/logout"))  //1.login out用户退出

        doLogout(request, response, filterChain, currentCookie, redirectUrl);

    else if (currentCookie != null)                               //2.cookie 优先 token校验

        authCookie(request, response, filterChain, currentCookie, redirectUrl);

    else if (request.getRequestURI().equals(contextPath + "/setCookie"))  //3.login in设置cookie

        setCookie(request, response);

    else //4.不再处理范围内,直接放行

        response.sendRedirect(redirectUrl);

}

/**

 * 3.设置Cookie

 * key:ssoServerName,value:

 *

 * @param request

 * @param response

 * @throws IOException

 */

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

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]setCookie..."));

    //1.生成cookie并组装keyvalue参数

    //Cookie currentCookie = new Cookie(ssoServerName, request.getParameter("ticket"));

    Cookie currentCookie = new Cookie(ssoServerName, String.format("%s_token", UUID.randomUUID().toString()));

    currentCookie.setPath("/");        //可以在webapp文件夹下的所有应用共享cookie

    currentCookie.setMaxAge(30 * 60);  //过期时间为半小时(单位:秒)

    //2.追加到response

    response.addCookie(currentCookie);

    //3.读取应用app的地址

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

    //4.重定向app

    if (gotoURL != null) {

        System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]setCookie ok,gotoUrl:"+gotoURL));

        response.sendRedirect(gotoURL);

    }

}

/**

 * 4.Cookie认证协议

 *

 * @param request

 * @param response

 * @param chain

 * @param cookie

 * @param redirectUrl

 * @throws IOException

 * @throws ServletException

 */

private void authCookie(HttpServletRequest request, HttpServletResponse response,

                        FilterChain chain, Cookie cookie, String redirectUrl) throws IOException, ServletException {

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]authCookie..."));

    NameValuePair[] params = new NameValuePair[2];

    params[0] = new NameValuePair("action", "authTicket");

    params[1] = new NameValuePair("ssoServerName", cookie.getValue());

    try {

        JSONObject result = executeSSOPost(request, response, chain, params);

        if (result != null) {

            if (result.has("success")) {

                boolean success = result.getBoolean("success");

                if (success) {

                    request.setAttribute("username", result.getString("username"));

                    request.setAttribute("userid", result.getString("userid"));

                    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]chain.doFilter(request, response) end!"));

                    chain.doFilter(request, response);

                } else {

                    throw new RuntimeException("[ssoserver]auth token exception!");

                }

            } else {

                throw new RuntimeException("[ssoserver]auth token exception!");

            }

        } else {

            throw new RuntimeException("[ssoserver]auth token exception!");

        }

    } catch (JSONException e) {

        throw new RuntimeException(e);

    }

}

/**

 * 5.退出协议

 *

 * @param request

 * @param response

 * @param chain

 * @param cookie

 * @param redirectUrl

 * @throws IOException

 * @throws ServletException

 */

private void doLogout(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Cookie cookie,

                      String redirectUrl) throws IOException, ServletException {

    NameValuePair[] params = new NameValuePair[2];

    params[0] = new NameValuePair("action", "logout");

    params[1] = new NameValuePair("ssoServerName", cookie.getValue());

    try {

        executeSSOPost(request, response, chain, params);

    } catch (JSONException ex) {

        throw new RuntimeException(ex);

    } finally {

        //重定向到某app页面

        response.sendRedirect(redirectUrl);

    }

}

/**

 * 2.执行Post请求

 *

 * @param request

 * @param response

 * @param chain

 * @param params

 * @return

 * @throws IOException

 * @throws ServletException

 * @throws JSONException

 */

private JSONObject executeSSOPost(HttpServletRequest request, HttpServletResponse response,

                                  FilterChain chain, NameValuePair[] params)

        throws IOException, ServletException, JSONException {

    //1.请求管理中心,并设置请求参数

    HttpClient httpClient = new HttpClient();

    PostMethod postMethod = new PostMethod(ssoServerUrl);

    postMethod.addParameters(params);

    switch (httpClient.executeMethod(postMethod)) {

        case HttpStatus.SC_OK:

            return new JSONObject(postMethod.getResponseBodyAsString());

        default:

            System.out.println("[ssoserver]executeMethod return null!");

            return null;

    }

}

}

1.1.3.MySSOAuth Controller

package com.tech.ability.springmvcstudy.mycontroller;

import com.alibaba.fastjson.JSONObject;

import com.tech.ability.util.DateUtil;

import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

/**

  • Created by kikop on 2019/2/24.

*/

@Controller

@RequestMapping("/sso")

public class MySSOAuth {

@RequestMapping(value = "/postAuth.do", method = {RequestMethod.POST})

@ResponseBody

public JSONObject postAuth(HttpServletRequest request, HttpServletResponse response) {

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]postAuth begin..."));

    JSONObject jsonObject = new JSONObject();

    try {

        jsonObject.put("success", true);

        jsonObject.put("username", "kikop");

        jsonObject.put("userid", "123456");

    } catch (Exception ex) {

        ex.printStackTrace();

        jsonObject.put("success", false);

    }

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoserver]postAuth end!"));

    return jsonObject;

}

//url http://localhost:8080/TechnicalAbilityToolBox/sso/getAuth.do?id=2

@RequestMapping(value = "/getAuth.do", method = {RequestMethod.GET})

@ResponseBody

public JSONObject getAuth(HttpServletRequest request, HttpServletResponse response, int id) {

    JSONObject jsonObject = new JSONObject();

    try {

        jsonObject.put("success", true);

        jsonObject.put("username", "kikop");

        jsonObject.put("userid", "123456");

    } catch (Exception ex) {

        ex.printStackTrace();

        jsonObject.put("success", false);

    }

    return jsonObject;

}

}

1.1.4.web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee

                  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

     version="3.1">

<display-name>TechnicalAbilityToolBox Web Application</display-name>

<!--1.sso server认证-->

<filter>

    <filter-name>SSOServerAuth</filter-name>

    <!--业务处理逻辑-->

    <filter-class>com.tech.ability.myssoserver.SSOServerAuth</filter-class>

    <init-param>

        <!--外部认证系统服务URL-->

        <param-name>ssoServerUrl</param-name>

        <param-value>http://localhost:8080/TechnicalAbilityToolBox</param-value>

    </init-param>

    <init-param>

        <!-- 认证系统服务名称 -->

        <param-name>ssoServerName</param-name>

        <param-value>ssoname</param-value>

    </init-param>

</filter>

<!--sso client 设置模式匹配内容(.jsp、/logout、/setCookie)-->

<!--放行ssologin.jsp-->

<!--<filter-mapping>-->

    <!--<filter-name>SSOServerAuth</filter-name>-->

    <!--<url-pattern>*.jsp</url-pattern>-->

<!--</filter-mapping>-->

<filter-mapping>

    <filter-name>SSOServerAuth</filter-name>

    <url-pattern>/authTicket</url-pattern>

</filter-mapping>

<filter-mapping>

    <filter-name>SSOServerAuth</filter-name>

    <url-pattern>/logout</url-pattern>

</filter-mapping>

<filter-mapping>

    <filter-name>SSOServerAuth</filter-name>

    <url-pattern>/setCookie</url-pattern>

</filter-mapping>

<!--2.spring容器加载-->

<listener>

    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<!--1.1.配置spring文件设置-->

<context-param>

    <param-name>contextConfigLocation</param-name>

    <param-value>classpath:myspring/spring.xml</param-value>

</context-param>

<!--1.添加spring的一个servlet,定义前端控制器-->

<servlet>

    <servlet-name>spring</servlet-name>

    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

    <!-- 指定路径 -->

    <init-param>

        <param-name>contextConfigLocation</param-name>

        <param-value>

            classpath*:/myspring/spring-servlet.xml

        </param-value>

    </init-param>

    <!-- 随spring启动而启动 -->

    <load-on-startup>1</load-on-startup>

</servlet>

<!--设置spring拦截-->

<servlet-mapping>

    <servlet-name>spring</servlet-name>

    <url-pattern>/</url-pattern>

</servlet-mapping>

<!--2.请求代理测试-->

<servlet>

    <servlet-name>proxy</servlet-name>

    <servlet-class>com.tech.ability.ProxyHandler</servlet-class>

    <load-on-startup>2</load-on-startup>

</servlet>

<servlet-mapping>

    <servlet-name>proxy</servlet-name>

    <url-pattern>/proxy</url-pattern>

</servlet-mapping>

<!--3.配置字符编码过滤器-->

<filter>

    <filter-name>encodingFilter</filter-name>

    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>

    <init-param>

        <param-name>encoding</param-name>

        <param-value>UTF-8</param-value>

    </init-param>

    <init-param>

        <param-name>forceEncoding</param-name>

        <param-value>true</param-value>

    </init-param>

</filter>

<filter-mapping>

    <filter-name>encodingFilter</filter-name>

    <!-- /下的所有请求都为UTF-8编码 -->

    <url-pattern>/</url-pattern>

</filter-mapping>

<!-- 7.防止Spring内存溢出监听器 -->

<listener>

    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>

</listener>

<welcome-file-list>

    <welcome-file>ssologin.jsp</welcome-file>

</welcome-file-list>

</web-app>

1.2.sso client

[图片上传失败...(image-a6d70d-1558878674303)]

1.2.1.boot.jsp

<%--

Created by IntelliJ IDEA.

User: kikop

Date: 2019/5/21

Time: 8:02

To change this template use File | Settings | File Templates.

--%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%--引入 jstl 标签--%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<%--取出部署的应用程序名或者是当前的项目名称,等价于 request.getContextPath()--%>

<c:set var="contextPath" value="${pageContext.request.contextPath}" scope="page"/>

<html>

<head>

<title>webapp1</title>

</head>

<body>

<a href="${contextPath}/sysmainpage.jsp">进入业务页面</a>



</body>

</html>

1.2.2.sysmainpage.jsp

<%--

Created by IntelliJ IDEA.

User: kikop

Date: 2019/5/26

Time: 18:01

To change this template use File | Settings | File Templates.

--%>

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

<%--引入 jstl 标签--%>

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<c:set var="username" value="${pageContext.request.getParameter('username')}" scope="page"/>

<html>

<head>

<title>sysmainpage</title>

</head>

<body>

${username}成功登录!

</body>

</html>

1.2.3.web.xml

<?xml version="1.0" encoding="UTF-8"?>

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"

     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"

     version="3.1">

<!--1.sso client 认证-->

<filter>

    <filter-name>SSOClientFilter</filter-name>

    <!--业务处理逻辑-->

    <filter-class>com.mysso.SSOClientFilter</filter-class>

    <init-param>

        <!--外部认证系统服务URL-->

        <param-name>ssoServerUrl</param-name>

        <param-value>http://localhost:8080/TechnicalAbilityToolBox</param-value>

    </init-param>

    <init-param>

        <!-- 认证系统服务名称,服务端存储该key,value为:在管理中心登录后根据用户名,密码生成的token -->

        <!-- 该token客户端获取到后,可以解析-->

        <param-name>ssoServerName</param-name>

        <param-value>ssoname</param-value>

    </init-param>

</filter>

<!--sso client 设置模式匹配内容(.jsp、/logout、/setCookie)-->

<filter-mapping>

    <filter-name>SSOClientFilter</filter-name>

    <url-pattern>*.jsp</url-pattern>

</filter-mapping>

<welcome-file-list>

    <welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

1.2.4.****SSOClientFilter

package com.mysso;

import org.apache.commons.httpclient.HttpClient;

import org.apache.commons.httpclient.HttpStatus;

import org.apache.commons.httpclient.NameValuePair;

import org.apache.commons.httpclient.methods.PostMethod;

import org.json.JSONException;

import org.json.JSONObject;

import javax.servlet.*;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

import java.util.HashSet;

/**

  • 单点登录管理中心客户端过滤器

  • Created by kikop on 2017/9/17.

*/

public class SSOClientFilter implements Filter {

/**

 * 单点服务的url

 */

private String ssoServerUrl;

private String ssoServerName;

/**

 * 无需验证的path

 */

private static final HashSet<String> NOT_AUTH_PATH = new HashSet<String>();

/**

 * 初始化

 *

 * @param filterConfig

 * @throws ServletException

 */

@Override

public void init(FilterConfig filterConfig) throws ServletException {

    NOT_AUTH_PATH.add("/index.jsp");

    //1.获取sso配置文件信息

    this.ssoServerUrl = filterConfig.getInitParameter("ssoServerUrl");

    this.ssoServerName = filterConfig.getInitParameter("ssoServerName");

}

/**

 * 销毁

 */

@Override

public void destroy() {

}

/**

 * 1.SSOClient拦截请求

 *

 * @param servletRequest

 * @param servletResponse

 * @param filterChain

 * @throws IOException

 * @throws ServletException

 */

@Override

public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {

    //1.强转

    HttpServletRequest request = (HttpServletRequest) servletRequest;

    HttpServletResponse response = (HttpServletResponse) servletResponse;

    //2.操作

    //请求Example:

    // http://localhost:8585/webapp1/syspage.html

    //2.1.得到请求资源路径

    String contextPath = request.getContextPath();   //请求服务名: /webapp1

    //取得服务名后面的所有内容,去除斜/

    //String requestURI = request.getRequestURI();  //返回除去host(域名或者ip)部分的路径

    //String requestURIFollowsPath = requestURI.substring(contextPath.length() + 1);

    String requestURL = request.getRequestURL().toString();

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]doFilter,getRequestURL:"+request.getRequestURL()));

    String gotoURL = request.getParameter("gotoURL");  //webapp1的实际请求地址

    if (gotoURL == null) {  //没有,则获取请求页面本身

        gotoURL = request.getRequestURL().toString();  //返回页面本身全路径: http://localhost:8585/webapp1/syspage.html

    }

    String not_auth_path = request.getServletPath();

    if (NOT_AUTH_PATH.contains(not_auth_path)) {

        filterChain.doFilter(request, response);

    } else {

        // 用户首次访问应用端,未携带cookie数据. 应用端会让用户重定向到服务器

        String redirectUrl = ssoServerUrl + "?action=preLogin&setCookieURL=" + request.getScheme() + "://"

                + request.getServerName() + ":" + request.getServerPort()

                + contextPath + "/setCookie&gotoURL=" + gotoURL;

        System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]redirectUrl:"+redirectUrl));

        //2.2.根据 ssoServerName 查找cookie是否有指定cookie(服务端也会验证)

        Cookie currentCookie = null;

        boolean isFindCookie = false;

        Cookie[] cookies = request.getCookies();

        if (cookies != null) {

            for (Cookie cookie : cookies) {

                if (cookie.getName().equals(ssoServerName)) {

                    currentCookie = cookie;

                    isFindCookie = true;

                    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]find cookie!"));

                    break;

                }

            }

        }

        if (!isFindCookie) {

            System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]not find cookie!"));

        }

        //3.处理逻辑(放行、注意这里的逻辑顺序)

        if (request.getRequestURI().equals(contextPath + "/logout"))  //1.login out用户退出

            doLogout(request, response, filterChain, currentCookie, redirectUrl);

        else if (currentCookie != null)                               //2.cookie 优先 token校验

            authCookie(request, response, filterChain, currentCookie, redirectUrl);

        else //3.登录管理中心验证

            response.sendRedirect(redirectUrl);

    }

}

/**

 * 4.Cookie认证协议

 *

 * @param request

 * @param response

 * @param chain

 * @param cookie

 * @param redirectUrl

 * @throws IOException

 * @throws ServletException

 */

private void authCookie(HttpServletRequest request, HttpServletResponse response,

                        FilterChain chain, Cookie cookie, String redirectUrl) throws IOException, ServletException {

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]authCookie..."));

    NameValuePair[] params = new NameValuePair[2];

    params[0] = new NameValuePair("action", "authTicket");

    params[1] = new NameValuePair("ssoServerName", cookie.getValue());

    try {

        JSONObject result = executeSSOPost(request, response, chain, params);

        if (result != null) {

            if (result.has("success")) {

                boolean success = result.getBoolean("success");

                if (success) {

                    request.setAttribute("username", result.getString("username"));

                    request.setAttribute("userid", result.getString("userid"));

                    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]chain.doFilter(request, response) end!"));

                    chain.doFilter(request, response);

                } else {

                    throw new RuntimeException("[ssoclient]auth token exception!");

                }

            } else {

                throw new RuntimeException("[ssoclient]auth token exception!");

            }

        } else {

            throw new RuntimeException("[ssoclient]auth token exception!");

        }

    } catch (JSONException e) {

        throw new RuntimeException(e);

    }

}

/**

 * 2.执行Post请求

 *

 * @param request

 * @param response

 * @param chain

 * @param params

 * @return

 * @throws IOException

 * @throws ServletException

 * @throws JSONException

 */

private JSONObject executeSSOPost(HttpServletRequest request, HttpServletResponse response,

                                  FilterChain chain, NameValuePair[] params)

        throws IOException, ServletException, JSONException {

    System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]executeSSOPost..."));

    //1.请求管理中心,并设置请求参数

    HttpClient httpClient = new HttpClient();

    PostMethod postMethod = new PostMethod(ssoServerUrl + "/sso/postAuth.do");

    postMethod.addParameters(params);

    switch (httpClient.executeMethod(postMethod)) {

        case HttpStatus.SC_OK:

            System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]executeSSOPost ok!"));

            return new JSONObject(postMethod.getResponseBodyAsString());

        default:

            System.out.println(DateUtil.getCurrentThreadInfo("[ssoclient]executeSSOPost return null!"));

            return null;

    }

}

}

1.3.Util

1.3.1.DateUtil

package com.mysso;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

/**

  • 日期工具类

  • @author Administrator

*/

public class DateUtil {

/**

 * 日期对象转字符串

 *

 * @param date

 * @param format

 * @return

 */

public static String formatDate(Date date, String format) {

    String result = "";

    SimpleDateFormat sdf = new SimpleDateFormat(format);

    if (date != null) {

        result = sdf.format(date);

    }

    return result;

}

/**

 * 字符串转日期对象

 *

 * @param str

 * @param format

 * @return

 * @throws Exception

 */

public static Date formatString(String str, String format) throws Exception {

    if (StringUtil.isEmpty(str)) {

        return null;

    }

    SimpleDateFormat sdf = new SimpleDateFormat(format);

    return sdf.parse(str);

}

public static String getCurrentDateStr() {

    Date date = new Date();

    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    return sdf.format(date);

}

public static void isDoubleWeekDay() {

    int isDoble = Calendar.DAY_OF_WEEK % 2;

    System.out.println(isDoble);

}

/**

 * 获取当前函数运行信息

 *

 * @param strMsg

 * @return

 */

public static String getCurrentThreadInfo(String strMsg) {

    return

            String.format("[%s]%15s-%05d:%s ", getCurrentDateStr(), Thread.currentThread().getName(), Thread.currentThread().getId(),strMsg);

}

}

1.3.2.StringUtil

package com.mysso;

import java.util.ArrayList;

import java.util.List;

/**

  • 字符串工具类

  • @author

*/

public class StringUtil {

/**

 * 判断是否是空

 *

 * @param str

 * @return

 */

public static boolean isEmpty(String str) {

    if (str == null || "".equals(str.trim())) {

        return true;

    } else {

        return false;

    }

}

/**

 * 判断是否不是空

 *

 * @param str

 * @return

 */

public static boolean isNotEmpty(String str) {

    if ((str != null) && !"".equals(str.trim())) {

        return true;

    } else {

        return false;

    }

}

/**

 * 格式化模糊查询

 *

 * @param str

 * @return

 */

public static String formatLike(String str) {

    if (isNotEmpty(str)) {

        return "%" + str + "%";

    } else {

        return null;

    }

}

/**

 * 过滤掉集合里的空格

 *

 * @param list

 * @return

 */

public static List<String> filterWhite(List<String> list) {

    List<String> resultList = new ArrayList<String>();

    for (String l : list) {

        if (isNotEmpty(l)) {

            resultList.add(l);

        }

    }

    return resultList;

}

}

3.web基础

3.1.request几种方式

request.getRequestURL() 返回全路径 request.getRequestURI() 返回除去host(域名或者ip)部分的路径 request.getContextPath() 返回工程名,如果工程映射为/,此处返回则为空 request.getServletPath() 返回除去host和工程名的路径 request.getRequestURL() http://localhost:8080/jqueryLearn/resources/request.jsp request.getRequestURI() /jqueryLearn/resources/request.jsp request.getContextPath()/jqueryLearn request.getServletPath()/resources/request.jsp

3.2.chrome浏览器中查看cookie

<u>chrome://settings/content/cookies</u>

<u>chrome://settings/cookies/detail?site=localhost</u>

[图片上传失败...(image-29ffde-1558878674296)]

[图片上传失败...(image-45ca51-1558878674296)]

3.3.cookie生命周期

cookie过期时间设置方式:

cookie.setMaxAge(0);//不记录cookie

cookie.setMaxAge(-1);//会话级cookie,关闭浏览器失效

cookie.setMaxAge(30*60);//过期时间为半小时(单位:秒)

Example:

<a href="http://localhost:8080/TechnicalAbilityToolBox/setCookie?gotoURL=${gotoURL}&ticket=hello&expiry=1800">登录</a>

currentCookie.setMaxAge(Integer.parseInt(request.getParameter("expiry")));

创建时间

2019年5月24日星期五 上午6:34:41

到期时间

2019年5月24日星期五 上午7:04:41

3.4.etc文件修改

C:\Windows\System32\drivers\etc

127.0.0.1 webapp1.com

127.0.0.1 webapp2.com

127.0.0.1 <u>www.mypassport.com</u>

3.5.scope取值(JSP)

page

request

session

application

参考

1.java实现完全跨域SSO单点登录

https://blog.csdn.net/zhangjingao/article/details/81735041

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269