java单点登录(SSO)的实现

单点登录(SSO):SSO是指在多个应用系统中个,用户只需要登陆一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一用户的登陆的机制。

SSO的实现过程:

通过上述图形,我们可以看到SSO的大体实现步骤主要分为两大步:存储登录信息,查验登录信息。

对于SSO,我们也可以将之分为两大不同的类型:同域SSO和跨域SSO;其中同域SSO又可以分为完全同域SSO和同父域SSO。

一、完全同域SSO:指的是域名完全相同的多个应用系统中实现单点登录。

其实现步骤主要分为:前期准备工作,编写统一登录接口,编写登录校验接口,编写验证页面,实现SSO;

编写统一登录接口:
登录页面的编写主要是录入用户的登录信息,包括用户名,密码,以及登录页面的地址。因为存在多个应用系统,所以用户在统一登录页面登陆成功后,系统需要知道用户想要访问的是哪个系统页面,这个时候就需要记录用户第一次访问的地址,等到用户登录成功后,就可直接跳转该页面。

<body>
    <center>
        <h1>请登录</h1>
        <form action="/sso/doLogin.action" method="POST">
            <span>用户名:</span><input type="text" name="username" />
            <span>密码:</span><input type="text" name="password" />
            //暂存需要登录页面的url地址
            <input type="hidden" name="gotoUrl" value="${gotoUrl}" />
            <input type="submit" />
        </form>
    </center>
</body>

登录方法的编写:需要新建cookie,将用户的信息存进cookie中,并指定cookie的路径,因为是完全同域,所以cookie的地址可以简写为(“/”)。这里必须要设置cookie的路径,如果不设置,那么cookie的路径将并不一定在当前域名的顶层,它有可能就在当前的这个路径下才可见,这样会导致在当前域的其他路径下找不到这个cookie,解决办法就是把cookie设置到当前域的最顶层域里面,这样当前域下的所有应用就会都可见。

public String doLogin(){
        //新建Cookie
        Cookie cookie = new Cookie("ssocookie","sso");
        //设置Cookie路径
        cookie.setPath("/");
        HttpServletResponse response = ServletActionContext.getResponse();
        response.addCookie(cookie);
        return "success";
 }

登录校验接口的编写:通常SSO登录接口校验都会放在登录拦截器中,当用户想要访问某个系统时,登录拦截器将直接重定向到统一登录页面,用户填写完登录信息后,就会进行登录校验。

//cookie校验(放在拦截器中进行校验)
    public static boolean checkCookie(HttpServletRequst request){
        Cookie[] cookies=request.getCookies();
        if(cookies!=null){
            for(Cookies cookie:cookies){
                if(cookie.getName().equals("ssocookie")
                        &&cookie.getValue().equals("sso")){
                    return true;
                }
            }
        }
        return false;
  }

编写测试主页

public String main(){
        HttpServletRequst request = ServletActionContext.getRequst();
        if(SSOCheck.checkCookie(request)){
            //登陆成功,记录用户登录信息......
            return "success";
        }
        //登录失败,暂存需要访问的地址,登录成功后,直接访问该地址
        gotoUrl="/demo1/main.action";
        return "login";
 }

最后还有struts2的配置文件

<struts>
    <package name="sso" namespace="/sso" extends="struts-default">
        <action name="doLogin" class="com.xm.controllerAction.SSOAction" method="doLogin">
       <!-- 用户登录成功后,需要进行重定向,重新跳转到用户最初访问的路径 -->
            <result name="success" type="redirect">${gotoUrl}</result>
        </action>
    </package>

    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="com.xm.controllerAction.Demo1Action" method="main">
            <result name="success">/success1.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="com.xm.controllerAction.Demo2Action" method="main">
            <result name="success">/success2.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
</struts>

二、同父域SSO:指的是父域名相同的应用系统上实现SSO。

其实现步骤与上述完全同域SSO相同。

其中检验域名:http://check.x.com

测试页面域名:http://demo1.x.com和http://demo2.x.com

编写统一登录接口:
代码实现与完全同域名SSO基本一致,不过在设置提交路径时,因为二级域名不同,所以不能写成相对路径,需要写成绝对路径地址。

<body>
    <center>
        <h1>请登录</h1>
     //表单提交地址需写成绝对路径,不能写相对路径
        <form action="http://check.x.com/sso/doLogin.action" method="POST">
            <span>用户名:</span><input type="text" name="username" />
            <span>密码:</span><input type="text" name="password" />
            //暂存需要登录页面的url地址
            <input type="hidden" name="gotoUrl" value="${gotoUrl}" />
            <input type="submit" />
        </form>
    </center>
</body>

登录方法:在设置cookie路径的时候有所变化,同上,为了使得当前两个同父域的应用系统都可见这个cookie,那么我们需要将这个cookie设置到父域下面,而不应该设置到本域下面,这样才可以实现域不同,但是父域相同的应用都可以看到的这个cookie。

   public String doLogin(){
     boolean ok = SSOCheck.checkLogin(userName,passWord);
     if(ok){
          //新建Cookie
          Cookie cookie = new Cookie("ssocookie","sso");
          //设置Cookie的父域
          cookie.setDomain(".x.com");
          //设置Cookie路径
          cookie.setPath("/");
          HttpServletResponse response = ServletActionContext.getResponse();
          response.addCookie(cookie);
          return "success";
     }
  }

登录校验接口:因为有着不同的域,所以我们应该将登录所获得cookie传到专门的校验域下的校验方法中进行校验,否则我们需要在各自不同的登录页面实现校验,这样显得代码十分的冗余。

    private String cookieName;
    private String cookieValue;
    public String getCookieName() {
      return cookieName;
    }
    public void setCookieName(String cookieName) {
      this.cookieName = cookieName;
    }
    public String getCookieValue() {
      return cookieValue;
    }
    public void setCookieValue(String cookieValue) {
      this.cookieValue = cookieValue;
    }

   //二级域名向二级域名发送请求
    public void checkCookie() throws IOException{
        boolean ok=SSOCheck.checkCookie(cookieName,cookieValue);
        String result="0";
        if(ok){
            result="1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
    }

public static boolean checkCookie(String cookieName,String cookieValue){
        if(cookieName.equals("ssocookie")&&cookieValue.equals("sso")){
            return true;
        }
        return false;
    }

编写测试主页

public String main(){
        HttpServletRequst request = ServletActionContext.getRequst();
     //获取cookie
        Cookie[] cookies=request.getCookies();
        if(cookies!=null){
            for(Cookie cookie:cookies){
                if(cookie.getName().equals("ssocookie")){
            //向检验服务器中发送cookieName和cookieValue
                    String result = Demo1Tool.doGet("http://check.x.com/so/checkCookie.action",
                            cookie.getName(),cookie.getValue());
                    if(result.equals("1")){
                        return "success";
                    }
                }
            }
        }
        //暂存需要访问的地址,登录成功后,直接访问该地址
        gotoUrl="http://demo1.x.com/demo1/main.action";
        return "login";
}
public static String doGet(String url,String cookieName,String cookieValue){
        //定义返回值
        StringBuffer sb = new StringBuffer();
        HttpURLConnection httpURLConnection = null;
        try{
            //校验方法所在的地址
            URL urls = new URL(url+
                    "?cookieName="+cookieName+"&cookieValue="+cookieValue);
            //打开连接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            //设置打开连接的方法
            httpURLConnection.setRequestMethod("GET");
            //开始连接
            httpURLConnection.connect();
            InputStream in = httpURLConnection.getInputStream();
            InputStreamReader isr = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(isr);
            String temp = null;
            while((temp = br.readLine())!=null){
                sb.append(temp);
            }
            br.close();
            isr.close();
            in.close();
        } catch(IOException e){
            e.printStackTrace();
        } finally{
            if(httpURLConnection!=null){
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
}

struts配置文件

<struts>
    <package name="sso" namespace="/sso" extends="struts-default">
        <action name="doLogin" class="com.xm.controllerAction.SSOAction" method="doLogin">
            <result name="success" type="redirect">${gotoUrl}</result>
        </action>
        <action name="checkCookie" class="check.x.com.SSOAction" method="checkCookie">
        </action>
    </package>
    <package name="demo1" namespace="/demo1" extends="struts-default">
        <action name="main" class="demo1.x.com.Demo1Action" method="main">
            <result name="success">/success1.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
    <package name="demo2" namespace="/demo2" extends="struts-default">
        <action name="main" class="demo2.x.com.Demo2Action" method="main">
            <result name="success">/success2.jsp</result>
            <result name="login">/login.jsp</result>
        </action>
    </package>
</struts>

三、跨域SSO:在域名完全不同的应用程序上实现SSO。

其实现步骤与完全同域SSO相同。

其中检验域名:http://www.x.com

测试页面域名:http://www.a.com和http://www.b.com

编写统一登录接口:

<body>
    <center>
        <h1>请登录</h1>
        //这里需要向当前所在的域提交申请,因为如果向校验域提交申请,那么在本域中将无法看到cookie
        <form action="/${path}/doLogin.action" method="POST">
            <span>用户名:</span><input type="text" name="username" />
            <span>密码:</span><input type="text" name="password" />
            //暂存需要登录页面的url地址
            <input type="hidden" name="gotoUrl" value="${gotoUrl}" />
            <input type="submit" />
        </form>
    </center>
</body>

登录方法:

public String doLogin(){
        Map<String,String> map = new HashMap<String,String>();
        map.put("userName", userName);
        map.put("password", passWord);
        String result = Demo1Tool.doGet("http://www.x.com/sso/doLogin.action",map);
        if(result.equals("1")){
            return "success";
        }
        return "login";
}
public void doLogin() throw IOException{
        boolean ok=SSOCheck.checkCookie(cookieName,cookieValue);
        String result = "0";
        if(ok){
            result = "1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
}

登录校验接口;和同父域SSO的登录校验基本一致,没有什么变化。

public void checkCookie() throws IOException{
        boolean ok=SSOCheck.checkCookie(cookieName,cookieValue);
        String result="0";
        if(ok){
            result="1";
        }
        HttpServletResponse response = ServletActionContext.getResponse();
        response.getWriter().print(result);
        response.getWriter().close();
}

编写测试主页

public String main(){
        HttpServletRequst request = ServletActionContext.getRequst();
        Cookie[] cookies=request.getCookies();
        if(cookies!=null){
            for(Cookie cookie:cookies){
                if(cookie.getName().equals("ssocookie")){
                    Map<String,String> map = new HashMap<String,String>();
                    map.put("userName", cookie.getName());
                    map.put("password", cookie.getValue());
                    String result = Demo1Tool.doGet("http://www.x.com/so/checkCookie.action",
                            cookie.getName(),cookie.getValue());
                    if(result.equals("1")){
                        return "success";
                    }
                }
            }
        }
        //暂存需要访问的地址,登录成功后,直接访问该地址
        path = "demo1";
        gotoUrl="http://www.a.com/demo1/main.action";
        return "login";
    }
public static String doGet(String url,Map<String,String> map){
        //定义返回值
        StringBuffer sb = new StringBuffer();
        HttpURLConnection httpURLConnection = null;
        try{
            StringBuffer t_s = new StringBuffer(url).append("?");
            for(Map.Entry<String, String> entry:map.entrySet()){
                t_s.append(entry.getKey()).append("=").append(entry.getValue()).append("&");

            }
            url = t_s.substring(0,t_s.length()-1);
            //校验方法所在的地址
            URL urls = new URL(url);
            //打开连接
            httpURLConnection = (HttpURLConnection) urls.openConnection();
            //设置打开连接的方法
            httpURLConnection.setRequestMethod("GET");
            //开始连接
            httpURLConnection.connect();
            InputStream in = httpURLConnection.getInputStream();
            InputStreamReader isr = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(isr);
            String temp = null;
            while((temp = br.readLine())!=null){
                sb.append(temp);
            }
            br.close();
            isr.close();
            in.close();
        } catch(IOException e){
            e.printStackTrace();
        } finally{
            if(httpURLConnection!=null){
                httpURLConnection.disconnect();
            }
        }
        return sb.toString();
    }

至此,准备工作做完,接下来是跨域SSO实现中最重要的部分,也就是cookie的设置,在之前完全同域和同父域的情况下,为了实现SSO,我们在进行doLogin时就设置了cookie,因为域名相同,所以十分简单,但是在跨域SSO中,因为不同域之间的cookie是不可见的,所以我们不可能只设置一个cookie,然后令所有的域名下的应用程序皆可见,所以我们应该在每个域下面都有着为本域设置cookie的方法,而不应该直接将设置cookie交给校验域。

//为本域设置cookie的方法
    public void addCookie(){
        Cookie cookie = new Cookie("ssocookie","sso");
        cookie.setPath("/");
        HttpServletResponse response = ServletActionContext.getResponse();
        response.addCookie(cookie);
    }

还需要在配置文件中进行配置:

<action name="addCookie" class="www.a.com.Demo1Action" method="addCookie"></action>

写完好方法,则需要进行调用,因此我们需要找一个可以让二者进行交会的地方,在这里我选择了登录成功的瞬间,通过隐藏的Iframe让二者进行交会。

public String doLogin(){
        Map<String,String> map = new HashMap<String,String>();
        map.put("userName", userName);
        map.put("password", passWord);
        String result = Demo1Tool.doGet("http://www.x.com/sso/doLogin.action",map);
        if(result.equals("1")){
            return "success";
        }
        List hidderUrl = new ArrayList<String>();
        hidderUrl.add("http://www.a.com/demo1/addCookie.action");
        hidderUrl.add("http://www.b.com/demo2/addCookie.action");
        return "login";
    }
<c:forEach var="url" item="${hiddenUrl}">
    <iframe src="${url}" width="0px" heigth="0px" style="display:none"></iframe>
</c:forEach>

到此这篇关于java单点登录(SSO)的实现的文章就介绍到这了,更多相关java单点登录内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java模拟实现QQ三方登录(单点登录2.0)

    本文实例为大家分享了Java模拟实现QQ三方登录的具体代码,供大家参考,具体内容如下 本次例子模拟这样的情况: 一共有2个spring boot应用: 一个是某公司的web,第二个是QQ服务端. 某公司的应用为127.0.0.1:8082 QQ服务端为127.0.0.1:8081 演示如下: 点击使用QQ登录: 在弹出的界面输入数据点击登录后: 关键代码如下: 某公司web端: MyController.java package cn.it1995.login.controller; impor

  • java单点登录(SSO)的实现

    单点登录(SSO):SSO是指在多个应用系统中个,用户只需要登陆一次就可以访问所有相互信任的应用系统.它包括可以将这次主要的登录映射到其他应用中用于同一用户的登陆的机制. SSO的实现过程: 通过上述图形,我们可以看到SSO的大体实现步骤主要分为两大步:存储登录信息,查验登录信息. 对于SSO,我们也可以将之分为两大不同的类型:同域SSO和跨域SSO:其中同域SSO又可以分为完全同域SSO和同父域SSO. 一.完全同域SSO:指的是域名完全相同的多个应用系统中实现单点登录. 其实现步骤主要分为:

  • asp.net简单实现单点登录(SSO)的方法

    本文实例讲述了asp.net简单实现单点登录(SSO)的方法.分享给大家供大家参考,具体如下: 单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统 CAS(Central Authentication Service)是一款不错的针对 Web 应用的单点登录框架(耶鲁大学开发)主要用于Java Php 有兴趣大家可以研究下.. 下面是一个简单实现单点登录的

  • 基于.Net的单点登录(SSO)实现解决方案

    前些天一位朋友要我帮忙做一单点登录,其实这个概念早已耳熟能详,但实际应用很少,难得最近轻闲,于是决定通过本文来详细描述一个SSO解决方案,希望对大家有所帮助.SSO的解决方案很多,但搜索结果令人大失所望,大部分是相互转载,并且描述的也是走马观花. 闲话少叙,进入正题,我的想法是使用集中验证方式,多个站点集中Passport验证. 如下图所示:  为方便清晰描述,先定义几个名词,本文中出现之处均为如下含义. 主站:Passport集中验证服务器 http://www.passport.com/ .

  • 详解可跨域的单点登录(SSO)实现方案【附.net代码】

    SSO简介 定义: 传统的单站点登录访问授权机制是:登录成功后将用户信息保存在session中,sessionId保存在cookie中,每次访问需要登录访问的资源(url)时判断当前session是否为空,为空的话跳转到登录界面登录,不为空的话允许访问. 单点登录是一种多站点共享登录访问授权机制,访问用户只需要在一个站点登录就可以访问其它站点需要登录访问的资源(url).用户在任意一个站点注销登录,则其它站点的登录状态也被注销.简而言之就是:一处登录,处处登录.一处注销,处处注销. 应用场景:

  • Java spring单点登录系统

    目录 1.单点登录系统介绍 2.简单业务实现 2.1添加依赖 2.2 项目配置文件 2.3添加项目启动类 2.4 启动并访问项目 3. 优化进一步设计 3.1 定义安全配置类 SecurityConfig 3.2定义用户信息处理对象 3.3 网关中登陆路由配置 3.4基于Postman进行访问测试 3.5 定义登陆页面 3.6 构建令牌配置对象 3.7 定义认证授权核心配置 授权服务器的核心配置 Postman访问测试 4 资源服务器配置–sca-resource 4.1 构建令牌配置对象 4.

  • SpringBoot集成redis与session实现分布式单点登录

    目录 单点登录 SSO(Single Sign On) 什么是单点登录? 实现方式 开发技术 单点登录实现流程 实现案例 看效果 前言: 由于考虑到cookie的安全性问题,就有了下面这个版本的sso 单点登录 SSO(Single Sign On) 什么是单点登录? 单点登录的英文名叫做:Single Sign On(简称SSO),指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的系统.简而言之,多个系统,统一登陆. 我们可以这样理解,在一个服务模块登录后,其他模块无

  • 深入浅析C#中单点登录的原理和使用

    什么是单点登录? 我想肯定有一部分人"望文生义"的认为单点登录就是一个用户只能在一处登录,其实这是错误的理解(我记得我第一次也是这么理解的). 单点登录指的是多个子系统只需要登录一个,其他系统不需要登录了(一个浏览器内).一个子系统退出,其他子系统也全部是退出状态. 如果你还是不明白,我们举个实际的例子把.比如我们首页:https://www.jb51.ne ,和我们的搜索http://so.jb51.net .这就是两个系统(不同的域名).如果你登录其中一个,另一个也是登录状态.如果

  • Android端实现单点登录的方法详解

    前言 单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任.单点登录在大型网站里使用得非常频繁,例如像阿里巴巴这样的网站,在网站的背后是成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉.实现单点登录说到底就是要解决如何产生和存储那个信任,再就是其他系统如何验证这个信任的有效

  • Django集成CAS单点登录的方法示例

    CAS 全称集中式认证服务(Central Authentication Service),是实现单点登录(SSO)的一中手段. CAS 的通讯流程图如下(图片来自Google图库): 对于本文用户可感知的层面,认证过程如下: 前端访问后端登录接口 后端返回重定向到 CAS 服务器的登录页面,并携带当前用户访问的网页链接 用户登录,浏览器发送请求到 CAS 服务器进行认证 CAS 认证通过,将本次登录保存到会话,返回回调地址给后端 后端返回重定向请求给前端 前端重定向到跳转登录前的页面 中间涉及

  • 入门到精通Java SSO单点登录原理详解

    目录 1. 基础概念 2. 单点登录 3. CAS 流程 4. OAuth 流程 5. CAS和OAuth的区别 1. 基础概念 SSO单点登录(Single sign-on) 所谓单点登录就是在多个应用系统中,用户只需登录一次就可以访问所有相互信任的系统. CAS 中央认证服务(Central Authentication Service) CAS是由美国耶鲁大学发起的一个企业级开源项目,旨在为WEB应用系统提供一种可靠的单点登录解决方案(WEB SSO). OAuth2.0 开放授权(Ope

随机推荐