美文网首页
2019-05-26_SSO单点登录知识学习

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

作者: kikop | 来源:发表于2019-05-26 21:54 被阅读0次

    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

    相关文章

      网友评论

          本文标题:2019-05-26_SSO单点登录知识学习

          本文链接:https://www.haomeiwen.com/subject/tafqtctx.html