资讯专栏INFORMATION COLUMN

慕课网_《Java实现SSO单点登录》学习总结

flyer_dev / 575人阅读

摘要:时间年月日星期三说明本文部分内容均来自慕课网。慕课网教学示例源码无个人学习源码第一章概述课程介绍及介绍课程目标认识并理解及其应用,并能根据其实现原理自行实现。

时间:2017年3月22日星期三
说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com
教学示例源码:无
个人学习源码:https://github.com/zccodere/s...

第一章:概述 1-1 课程介绍及SSO介绍

课程目标

认识并理解SSO及其应用,并能根据其实现原理自行实现SSO。

学习内容

1.SSO的介绍和应用体验(以新浪为例)
    SSO:一次登录,处处穿梭
2.SSO的分类介绍的实现探讨
    同域SSO:不同的应用位于同一个域名下面
    跨域SSO:不同的应用位于不同的域名下面
3.各种SSO的具体实现介绍的代码示例

同域SSO图示

1-2 SSO核心技术分析

SSO的实现步骤和原理

以旅游是购买的通票为例:

SSO特点:

1.必须要登陆一次
2.票据与验票机制

实现SSO的步骤拆解

关键:存储票据(购票与存储),查验票据(是否有票与是否有效)

核心技术点实现原理:

比照旅游进行
第二章:同域SSO 2-1 同域SSO准备工作

教学示例流程图

个人学习流程图

项目搭建

说明:教学使用SSH搭建演示项目,我在学习时使用springboot搭建,源码可以在我的github上查看、下载、运行等。因为本节主要是讲SSO单点登录,并不是将项目搭建,所以搭建过程省略。

项目命名为:myssosamedomain

2-2 编写统一登录接口

编写校验工具类

package com.myimooc.sso.web.util;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * 登录校验工具类
 * @author ZhangCheng
 * @date 2017-03-22
 * @version V1.0
 */
public class LoginCheck {
    /** 测试用户名 */
    public static final String USERNAME="user";
    /** 测试密码*/
    public static final String PASSWORD="123";
    /** Cookie键 */
    public static final String COOKIE_NAME = "ssocookie";
    /** Cookie值*/
    public static final String COOKIE_VALUE = "sso";
    
    /**
     * 登录用户名和密码校验
     * @param username 用户名
     * @param password 密码
     * @return true用户名和密码正确;false用户名或密码错误
     */
    public static boolean checkLogin(String username,String password){
        if(USERNAME.equalsIgnoreCase(username) && 
            PASSWORD.equalsIgnoreCase(password)){
            return true;
        }
        return false;
    }
    
    /**
     * 校验Cookie
     * @param request
     * @return true正确;false错误
     */
    public static boolean checkCookie(HttpServletRequest request){
        Cookie[] cookies = request.getCookies();
        if( cookies == null){
            return false;
        }
        for (Cookie cookie : cookies) {
            if(COOKIE_NAME.equals(cookie.getName()) && 
                COOKIE_VALUE.equals(cookie.getValue())){
                return true;
            }
        }
        return false;
    }
}

编写校验控制器

package com.myimooc.sso.web.controller;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.web.util.LoginCheck;

/**
 * SSO登录控制器
 * @author ZhangCheng
 * @date 2017-03-22
 * @version V1.0
 */
@Controller
@RequestMapping("/sso")
public class LoginController {
    
    /**
     * 处理用户登录请求
     * @param username 用户名
     * @param password 密码
     * @param gotoUrl 登录成功后请求路径
     * @param response
     * @return
     */
    @PostMapping("/doLogin")
    public ModelAndView doLogin(String username,String password,
            String gotoUrl,HttpServletResponse response){
        ModelAndView mv = new ModelAndView("login_fail");
        // 校验用户名和密码
        boolean ok = LoginCheck.checkLogin(username, password);
        // 判断是否登录成功
        if(ok){
            Cookie cookie = new Cookie(LoginCheck.COOKIE_NAME,LoginCheck.COOKIE_VALUE);
            // 顶级域名下,所有应用都是可见的
            cookie.setPath("/");
            // 添加Cookie
            response.addCookie(cookie);
            mv.setViewName("redirect:"+gotoUrl);
        }
        return mv;
    }
    
    /**
     * 跳转到登录页面
     * @return
     */
    @GetMapping("/login")
    public ModelAndView login(){
        return new ModelAndView("login");
    }

}

编写登录页面





登录


请登录

用户名: 密 码:

编写登录失败页面





登录失败


登录失败

重新登录
2-3 编写登录页面demo1和demo2控制器

demo1控制器

package com.myimooc.sso.demo1;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.web.util.LoginCheck;

/**
 * 
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
@Controller
public class DemoOneController {
    
    @RequestMapping("/demo1")
    public ModelAndView main(HttpServletRequest request) {
        
        ModelAndView mv = new ModelAndView();
        
        if (LoginCheck.checkCookie(request)) {
            mv.setViewName("demo1");
            return mv;
        }
        mv.addObject("gotoUrl", "/demo1");
        mv.setViewName("login");
        return mv;
    }
}

demo2控制器

package com.myimooc.sso.demo2;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.web.util.LoginCheck;

/**
 * 
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
@Controller
public class DemoTwoController {

    @RequestMapping("/demo2")
    public ModelAndView main(HttpServletRequest request) {
        
        ModelAndView mv = new ModelAndView();
        
        if (LoginCheck.checkCookie(request)) {
            mv.setViewName("demo2");
            return mv;
        }
        mv.addObject("gotoUrl", "/demo2");
        mv.setViewName("login");
        return mv;
    }
}
2-4 编写DEMO1和DEMO2的主页

demo1页面





欢迎访问demo1


    

这是demo1的主页

demo2页面





欢迎访问demo2


    

这是demo2的主页

2-5 同域SSO最终效果演示

访问demo1页面需要登录

访问demo2页面需要登录

在demo1页面处登录

登录成功,可以访问demo1页面

再次访问demo2时,不需要登录即可访问

第三章:同父域SSO 3-1 准备工作

教学示例流程图

个人学习流程图

通过修改host文件,来模拟实现父子域名。

文件路径:C:WindowsSystem32driversetchosts

修改如下

说明:正常情况下,应该分别建立三个项目,对应demo1.x.com、demo2.x.com、check.x.com。但为了演示讲解方便,我们通过项目里面对应的包名来区分是哪个项目。

项目搭建
项目命名为:myssosamefather

3-2 统一登录接口

编写消息响应类

package com.myimooc.sso.util;

import java.io.Serializable;
/**
 * 消息响应对象
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
public class RespMessage implements Serializable{
    
    private static final long serialVersionUID = 1L;
    /** 响应编号 */
    private String respCode;
    /** 响应消息 */
    private String respMsg;
    
    public String getRespCode() {
        return respCode;
    }

    public void setRespCode(String respCode) {
        this.respCode = respCode;
    }

    public String getRespMsg() {
        return respMsg;
    }

    public void setRespMsg(String respMsg) {
        this.respMsg = respMsg;
    }
    
}

编写登录校验工具类

package com.myimooc.sso.util;

/**
 * 登录校验工具类
 * 
 * @author ZhangCheng
 * @date 2017-03-22
 * @version V1.0
 */
public class LoginCheck {
    /** 测试用户名 */
    public static final String USERNAME = "user";
    /** 测试密码 */
    public static final String PASSWORD = "123";
    /** Cookie键 */
    public static final String COOKIE_NAME = "ssocookie";
    /** Cookie值 */
    public static final String COOKIE_VALUE = "sso";
    
    /**
     * 登录用户名和密码校验
     * 
     * @param username
     *            用户名
     * @param password
     *            密码
     * @return true已登录;false未登录
     */
    public static boolean checkLogin(String username, String password) {
        if (USERNAME.equalsIgnoreCase(username) && PASSWORD.equalsIgnoreCase(password)) {
            return true;
        }
        return false;
    }

    /**
     * 校验Cookie
     * @param cookieName
     * @param cookieValue
     * @return
     */
    public static boolean checkCookie(String cookieName,String cookieValue) {
        if (cookieName == null || cookieName=="") {
            return false;
        }
        if (cookieValue == null || cookieValue=="") {
            return false;
        }
        if (COOKIE_NAME.equals(cookieName) && COOKIE_VALUE.equals(cookieValue)) {
            return true;
        }
        return false;
    }

}

编写http请求工具类

package com.myimooc.sso.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import com.alibaba.fastjson.JSONObject;

/**
 * http工具类
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
public class HttpUtils {
    
    /**
     * 向指定url路径发起get请求,校验cookie
     * @param url 路径
     * @param cookieName
     * @param cookieValue
     * @return
     */
    public static RespMessage doGet(String url,String cookieName,String cookieValue){
        RespMessage respMessage = new RespMessage();
        HttpURLConnection httpURLConnection = null;
        URL targetUrl = null;
        try{
            targetUrl = new URL(url+"?cookieName="+cookieName+"&cookieValue="+cookieValue);
            httpURLConnection = (HttpURLConnection) targetUrl.openConnection();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.connect();
            
            InputStream in = httpURLConnection.getInputStream();
            InputStreamReader isr = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(isr);
            
            StringBuffer sb = new StringBuffer();
            String temp = null;
            while((temp=br.readLine())!=null){
                sb.append(temp);
            }
            
            br.close();
            isr.close();
            in.close();
            
            JSONObject resultJson = JSONObject.parseObject(sb.toString());
            respMessage.setRespCode(resultJson.getString("respCode"));
            respMessage.setRespMsg(resultJson.getString("respMsg"));
            return respMessage;
        }catch (Exception e) {
            respMessage.setRespCode("500");
            respMessage.setRespMsg("Cookie校验请求失败");
            return respMessage;
        }finally {
            if(httpURLConnection !=null){
                httpURLConnection.disconnect();
            }
        }
    }
    
}

check.x.com:编写认证中心控制器

package com.myimooc.sso.check.x.com;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.util.LoginCheck;
import com.myimooc.sso.util.RespMessage;

/**
 * SSO登录控制器
 * 
 * @author ZhangCheng
 * @date 2017-03-22
 * @version V1.0
 */
@Controller
@RequestMapping("/sso")
public class LoginController {

    /**
     * 处理用户登录请求
     * 
     * @param username
     *            用户名
     * @param password
     *            密码
     * @param gotoUrl
     *            登录成功后请求路径
     * @param response
     * @return
     */
    @PostMapping("/doLogin")
    public ModelAndView doLogin(String username, String password, String gotoUrl, HttpServletResponse response) {
        ModelAndView mv = new ModelAndView("login_fail");
        // 校验用户名和密码
        boolean ok = LoginCheck.checkLogin(username, password);
        // 判断是否登录成功
        if (ok) {
            Cookie cookie = new Cookie(LoginCheck.COOKIE_NAME, LoginCheck.COOKIE_VALUE);
            // 设置在父域下面
            cookie.setDomain("x.com");
            // 顶级域名下,所有应用都是可见的
            cookie.setPath("/");
            // 添加Cookie
            response.addCookie(cookie);
            mv.setViewName("redirect:" + gotoUrl);
        }
        return mv;
    }
    
    /**
     * 校验cookie
     * @param cookieName
     * @param cookieValue
     * @param response
     * @return
     */
    @GetMapping("/checkCookie")
    @ResponseBody
    public RespMessage checkCookie(String cookieName,String cookieValue,HttpServletResponse response){
        RespMessage result = new RespMessage();
        result.setRespCode("500");
        result.setRespMsg("CookieName或CookieValue无效");
        boolean isOk = LoginCheck.checkCookie(cookieName, cookieValue);
        if(isOk){
            result.setRespCode("200");
            result.setRespMsg("Cookie有效");
        }
        return result;
    }

    /**
     * 跳转到登录页面
     * 
     * @return
     */
    @GetMapping("/login")
    public ModelAndView login() {
        return new ModelAndView("login");
    }

}
3-3 编写demo1和demo2项目的控制层

demo1.x.com:编写demo1项目控制器

package com.myimooc.sso.demo1.x.com;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.util.HttpUtils;
import com.myimooc.sso.util.RespMessage;

/**
 * 
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
@Controller
public class DemoOneController {

    @RequestMapping("/demo1")
    public ModelAndView main(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        
        //校验cookie是否为空
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length > 0){
            //校验cookie是否存在
            for(Cookie cookie : cookies){
                if("ssocookie".equals(cookie.getName())){
                    //向校验服务器发送校验请求
                    String url = "http://check.x.com:8080/sso/checkCookie";
                    RespMessage respMessage = HttpUtils.doGet(url, cookie.getName(), cookie.getValue());
                    if("200".equals(respMessage.getRespCode())){
                        mv.setViewName("demo1");
                        return mv;
                    }
                }
            }
        }
        mv.addObject("gotoUrl", "http://demo1.x.com:8080/demo1");
        mv.setViewName("login");
        return mv;
    }
}

demo2.x.com:编写demo2项目控制器

package com.myimooc.sso.demo2.x.com;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.util.HttpUtils;
import com.myimooc.sso.util.RespMessage;

/**
 * 
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
@Controller
public class DemoTwoController {

    @RequestMapping("/demo2")
    public ModelAndView main(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        
        //校验cookie是否为空
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length > 0){
            //校验cookie是否存在
            for(Cookie cookie : cookies){
                if("ssocookie".equals(cookie.getName())){
                    //向校验服务器发送校验请求
                    String url = "http://check.x.com:8080/sso/checkCookie";
                    RespMessage respMessage = HttpUtils.doGet(url, cookie.getName(), cookie.getValue());
                    if("200".equals(respMessage.getRespCode())){
                        mv.setViewName("demo2");
                        return mv;
                    }
                }
            }
        }
        mv.addObject("gotoUrl", "http://demo2.x.com:8080/demo2");
        mv.setViewName("login");
        return mv;
    }
}
3-4 编写登录页




Insert title here


请登录

用户名: 密 码:
3-5 同父域情况下的SSO效果演示

请注意观察浏览器URL地址

访问demo1.x.com:需要登录

访问demo2.x.com:需要登录

在demo1.x.com处登录成功后,跳转至demo1页面

再访问demo2.x.com的demo2页面时,不再需要登录了

第四章:跨域SSO的实现 4-1 准备工作

教学示例流程图

个人学习流程图

通过修改host文件,来模拟实现跨域应用。

文件路径:C:WindowsSystem32driversetchosts

修改如下

说明:正常情况下,应该分别建立三个项目,对应www.a.com、www.b.com、www.x.com。但为了演示讲解方便,我们通过项目里面对应的包名来区分是哪个项目。

项目搭建
项目命名为:myssocrossdomain

完成后的目录结构如下

4-2 编写统一登录接口

编写消息响应类

package com.myimooc.sso.util;

import java.io.Serializable;
import java.util.Map;
/**
 * 消息响应对象
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
public class RespMessage implements Serializable{
    
    private static final long serialVersionUID = 1L;
    /** 响应编号 */
    private String respCode;
    /** 响应消息 */
    private String respMsg;
    /** 响应数据 */
    private Map respArgs;
    
    public String getRespCode() {
        return respCode;
    }

    public void setRespCode(String respCode) {
        this.respCode = respCode;
    }

    public String getRespMsg() {
        return respMsg;
    }

    public void setRespMsg(String respMsg) {
        this.respMsg = respMsg;
    }
    

    public Map getRespArgs() {
        return respArgs;
    }

    public void setRespArgs(Map respArgs) {
        this.respArgs = respArgs;
    }

    @Override
    public String toString() {
        return "RespMessage [respCode=" + respCode + ", respMsg=" + respMsg + ", respArgs=" + respArgs + "]";
    }
    
    
}

编写http请求工具类

package com.myimooc.sso.util;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Map;

import com.alibaba.fastjson.JSONObject;

/**
 * Http请求工具类
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
public class HttpUtils {
    
    /**
     * 向指定url路径发起get请求
     * @param url 请求路径
     * @param param 请求参数
     * @return
     */
    public static RespMessage doGet(String url,Map param){
        RespMessage respMessage = new RespMessage();
        HttpURLConnection httpURLConnection = null;
        URL targetUrl = null;
        try{
            // 拼装请求参数
            StringBuffer targetUrlStr = new StringBuffer(url).append("?");
            for(Map.Entry entry : param.entrySet()){
                targetUrlStr.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
            url = targetUrlStr.substring(0,targetUrlStr.length()-1);
            
            targetUrl = new URL(url);
            httpURLConnection = (HttpURLConnection) targetUrl.openConnection();
            httpURLConnection.setRequestMethod("GET");
            httpURLConnection.connect();
            
            InputStream in = httpURLConnection.getInputStream();
            InputStreamReader isr = new InputStreamReader(in);
            BufferedReader br = new BufferedReader(isr);
            
            StringBuffer sb = new StringBuffer();
            String temp = null;
            while((temp=br.readLine())!=null){
                sb.append(temp);
            }
            
            br.close();
            isr.close();
            in.close();
            
            JSONObject resultJson = JSONObject.parseObject(sb.toString());
            respMessage.setRespCode(resultJson.getString("respCode"));
            respMessage.setRespMsg(resultJson.getString("respMsg"));
            
            JSONObject resultJsonMap = JSONObject.parseObject(resultJson.getString("respArgs"));
            respMessage.setRespArgs(resultJsonMap);
            return respMessage;
        }catch (Exception e) {
            respMessage.setRespCode("500");
            respMessage.setRespMsg("请求发起失败");
            return respMessage;
        }finally {
            if(httpURLConnection !=null){
                httpURLConnection.disconnect();
            }
        }
    }
}

www.x.com:编写认证中心校验工具类

package com.myimooc.sso.www.x.com;

/**
 * 登录校验工具类
 * 
 * @author ZhangCheng
 * @date 2017-03-22
 * @version V1.0
 */
public class LoginCheck {
    /** 测试用户名 */
    public static final String USERNAME = "user";
    /** 测试密码 */
    public static final String PASSWORD = "123";
    /** Cookie键 */
    public static final String COOKIE_NAME = "ssocookie";
    /** Cookie值 */
    public static final String COOKIE_VALUE = "sso";
    
    /**
     * 登录用户名和密码校验
     * 
     * @param username
     *            用户名
     * @param password
     *            密码
     * @return true已登录;false未登录
     */
    public static boolean checkLogin(String username, String password) {
        if (USERNAME.equalsIgnoreCase(username) && PASSWORD.equalsIgnoreCase(password)) {
            return true;
        }
        return false;
    }

    /**
     * 校验Cookie
     * @param cookieName
     * @param cookieValue
     * @return
     */
    public static boolean checkCookie(String cookieName,String cookieValue) {
        if (cookieName == null || cookieName=="") {
            return false;
        }
        if (cookieValue == null || cookieValue=="") {
            return false;
        }
        if (COOKIE_NAME.equals(cookieName) && COOKIE_VALUE.equals(cookieValue)) {
            return true;
        }
        return false;
    }

}

www.x.com:编写认证中心控制器

package com.myimooc.sso.www.x.com;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.myimooc.sso.util.RespMessage;

/**
 * SSO登录控制器
 * 
 * @author ZhangCheng
 * @date 2017-03-22
 * @version V1.0
 */
@Controller
@RequestMapping("/sso")
public class LoginController {

    /**
     * 校验用户信息
     * @param param
     * @return
     */
    @GetMapping("/doLogin")
    @ResponseBody
    public RespMessage doLogin(String username,String password) {
        RespMessage result = new RespMessage();
        result.setRespCode("500");
        result.setRespMsg("用户名或密码错误");
        
        // 校验用户名和密码
        boolean ok = LoginCheck.checkLogin(username,password);
        // 判断是否登录成功
        if (ok) {
            result.setRespCode("200");
            result.setRespMsg("用户名和密码正确");
            
            List> targetCookies = new ArrayList>();
            
            // 向www.a.com服务器发送增加cookie
            Map targetCookiea = new HashMap();
            String urla = "http://www.a.com/a/addCookie";
            targetCookiea.put("targetUrl", urla);
            targetCookiea.put("cookieName", LoginCheck.COOKIE_NAME);
            targetCookiea.put("cookieValue", LoginCheck.COOKIE_VALUE);
            
            // 向www.b.com服务器发送增加cookie
            Map targetCookieb = new HashMap();
            String urlb = "http://www.b.com/b/addCookie";
            targetCookieb.put("targetUrl", urlb);
            targetCookieb.put("cookieName", LoginCheck.COOKIE_NAME);
            targetCookieb.put("cookieValue", LoginCheck.COOKIE_VALUE);
            
            targetCookies.add(targetCookiea);
            targetCookies.add(targetCookieb);
            
            Map args = new HashMap();
            args.put("targetCookies", targetCookies);
            
            result.setRespArgs(args);
            
        }
        return result;
    }
    
    /**
     * 校验cookie
     * @param cookieName
     * @param cookieValue
     * @param response
     * @return
     */
    @GetMapping("/checkCookie")
    @ResponseBody
    public RespMessage checkCookie(String cookieName,String cookieValue){
        RespMessage result = new RespMessage();
        result.setRespCode("500");
        result.setRespMsg("CookieName或CookieValue无效");
        boolean isOk = LoginCheck.checkCookie(cookieName, cookieValue);
        if(isOk){
            result.setRespCode("200");
            result.setRespMsg("Cookie有效");
        }
        return result;
    }
}

www.x.com:编写登录页





登录





请登录

用户名: 密 码:

www.x.com:编写login.js

/**
 * 登录js
 */
$(function(){
    var ctx = $("#ctx").val();
    $("#login_button").click(function(){
        login();
    });
});

function login(){
    // 获取登录信息
    var username=$("#username_input").val();
    var password=$("#password_input").val();
    var path=$("#path_input").val();
    var gotoUrl=$("#gotoUrl_input").val();
    
    var requesturl="/a/doLogin";
    $.ajax({
        type:"POST",
        async:false,//发送同步请求
        url:requesturl,
        data:"username="+username+"&password="+password,
        success:function(result){
            // 登录失败
            if(result.respCode != 200 ){
                alert(result.respMsg);
                return;
            }
            // 登录成功
            var targetCookies = result.respArgs.targetCookies;
            
            // 向服务器发出添加cookie请求
            $.each(targetCookies,function(i,targetCookie){
                var targetUrl = targetCookie.targetUrl;
                var cookieName = targetCookie.cookieName;
                var cookieValue = targetCookie.cookieValue;
                creat(targetUrl,cookieName,cookieValue);
            });
        }
    });
    // 跳转到目标页
    window.location.href=gotoUrl;
}
/** js利用iframe实现跨域添加cookie */
function creat(targetUrl,cookieName,cookieValue){
    var iframe = document.createElement("iframe"); 
    var targetSrc = targetUrl+"?"+"cookieName="+cookieName+"&cookieValue="+cookieValue;
    iframe.src=targetSrc;
    document.body.appendChild(iframe);
}
4-3 编写登录校验接口

www.a.com:编写控制器

package com.myimooc.sso.www.a.com;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.util.RespMessage;
import com.myimooc.sso.util.HttpUtils;

/**
 * 
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
@Controller
@RequestMapping("/a")
public class DemoOneController {
    
    /**
     * 跳转到demo1的主页
     * @param request
     * @return
     */
    @RequestMapping("/demo1")
    public ModelAndView demo1(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        
        //校验cookie是否为空
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length > 0){
            //校验cookie是否存在
            for(Cookie cookie : cookies){
                if("ssocookie".equals(cookie.getName())){
                    // 封装请求参数
                    Map param = new HashMap();
                    param.put("cookieName", cookie.getName());
                    param.put("cookieValue", cookie.getValue());
                    // 向校验服务器发送校验请求
                    String url = "http://www.x.com/sso/checkCookie";
                    RespMessage respMessage = HttpUtils.doGet(url, param);
                    // 校验通过
                    if("200".equals(respMessage.getRespCode())){
                        mv.setViewName("demo1");
                        return mv;
                    }
                }
            }
        }
        // 登录失败重新登录
        String path = request.getContextPath();
        mv.addObject("contextPath",path);
        mv.addObject("path","a");
        mv.addObject("gotoUrl", "http://www.a.com/a/demo1");
        mv.setViewName("login");
        return mv;
    }
    
    /**
     * 用户登录
     * @param param
     * @return
     */
    @PostMapping(value="/doLogin")
    @ResponseBody
    public RespMessage doLogin(@RequestParam Map param){
        // 向校验服务器发送校验请求
        String url = "http://www.x.com/sso/doLogin";
        RespMessage respMessage = HttpUtils.doGet(url, param);
        System.out.println("SSO服务器响应消息:"+respMessage);
        return respMessage;
    }
    
    /**
     * 想当前域添加cookie
     * @param cookieName
     * @param cookieValue
     * @param response
     */
    @RequestMapping(value="/addCookie")
    public void addCookie(String cookieName,String cookieValue,HttpServletResponse response){
        Cookie cookie = new Cookie(cookieName,cookieValue);
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}

www.b.com:编写控制器

package com.myimooc.sso.www.b.com;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.myimooc.sso.util.HttpUtils;
import com.myimooc.sso.util.RespMessage;

/**
 * 
 * @author ZhangCheng
 * @date 2017-04-02
 * @version V1.0
 */
@Controller
@RequestMapping("/b")
public class DemoTwoController {

    @RequestMapping("/demo2")
    public ModelAndView main(HttpServletRequest request) {
        ModelAndView mv = new ModelAndView();
        
        //校验cookie是否为空
        Cookie[] cookies = request.getCookies();
        if(cookies != null && cookies.length > 0){
            //校验cookie是否存在
            for(Cookie cookie : cookies){
                if("ssocookie".equals(cookie.getName())){
                 // 封装请求参数
                    Map param = new HashMap();
                    param.put("cookieName", cookie.getName());
                    param.put("cookieValue", cookie.getValue());
                    // 向校验服务器发送校验请求
                    String url = "http://www.x.com/sso/checkCookie";
                    RespMessage respMessage = HttpUtils.doGet(url, param);
                    // 校验通过
                    if("200".equals(respMessage.getRespCode())){
                        mv.setViewName("demo2");
                        return mv;
                    }
                }
            }
        }
        // 登录失败重新登录
        mv.addObject("contextPath",request.getContextPath());
        mv.addObject("path","b");
        mv.addObject("gotoUrl", "http://www.b.com/b/demo2");
        mv.setViewName("login");
        return mv;
    }
    
    /**
     * 用户登录
     * @param param
     * @return
     */
    @PostMapping(value="/doLogin")
    @ResponseBody
    public RespMessage doLogin(@RequestParam Map param){
        // 向校验服务器发送校验请求
        String url = "http://www.x.com/sso/doLogin";
        RespMessage respMessage = HttpUtils.doGet(url, param);
        System.out.println("SSO服务器响应消息:"+respMessage);
        return respMessage;
    }
    
    /**
     * 向当前域添加cookie
     * @param cookieName
     * @param cookieValue
     * @param response
     */
    @RequestMapping(value="/addCookie")
    public void addCookie(String cookieName,String cookieValue,HttpServletResponse response){
        Cookie cookie = new Cookie(cookieName,cookieValue);
        cookie.setPath("/");
        response.addCookie(cookie);
    }
}
4-4 跨域SSO效果演示

注意观察浏览器URL地址

访问www.a.com的a项目需要登录

访问www.b.com的b项目需要登录

在www.a.com域登录

登录成功

www.b.com域即可直接访问,免登陆

第五章:课程总结 5-1 课程总结

1.核心是COOKIE,需要注意设置的域、位置和安全性

注意COOKIE的加密

2.应用群的安全性问题:木桶效应

即应用群的安全性受限于某个安全性最低的应用

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/66947.html

相关文章

  • 课网_Java图片验证码》学习总结

    时间:2017年07月09日星期日说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:概述 1-1 课程概述 主要内容 验证码历史 课程内容 不同方案对比 设计与实现 总结 1-2 验证码历史 验证码历史 无验证码:垃圾骚扰 Luis von Ahn:Captcha 不断...

    haitiancoder 评论0 收藏0
  • 课网_《微信授权登录学习总结

    摘要:时间年月日星期六说明本文部分内容均来自慕课网。第六章公众号与开发平台关联公众号与开放平台关联情景说明当使用端进行微信授权登录时,得到的和公众号授权登录时得到的不一样。 时间:2017年08月12日星期六说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:课程介绍...

    coordinate35 评论0 收藏0
  • 什么是单点登录(SSO)

    摘要:此时,用户想要访问系统受限的资源比如说订单功能,订单功能需要登录后才能访问,系统发现用户并没有登录,于是重定向到认证中心,并将自己的地址作为参数。 前言 只有光头才能变强。文本已收录至我的GitHub仓库,欢迎Star:https://github.com/ZhongFuCheng3y/3y 在我实习之前我就已经在看单点登录的是什么了,但是实习的时候一直在忙其他的事,所以有几个网站就...

    levy9527 评论0 收藏0
  • 什么是单点登录(SSO)

    摘要:此时,用户想要访问系统受限的资源比如说订单功能,订单功能需要登录后才能访问,系统发现用户并没有登录,于是重定向到认证中心,并将自己的地址作为参数。前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:github.com/ZhongFuChen… 在我实习之前我就已经在看单点登录的是什么了,但是实习的时候一直在忙其他的事,所以有几个网站就一直躺在我的收藏夹里边: ...

    番茄西红柿 评论0 收藏0
  • 什么是单点登录(SSO)

    摘要:此时,用户想要访问系统受限的资源比如说订单功能,订单功能需要登录后才能访问,系统发现用户并没有登录,于是重定向到认证中心,并将自己的地址作为参数。前言 只有光头才能变强。 文本已收录至我的GitHub仓库,欢迎Star:github.com/ZhongFuChen… 在我实习之前我就已经在看单点登录的是什么了,但是实习的时候一直在忙其他的事,所以有几个网站就一直躺在我的收藏夹里边: ...

    番茄西红柿 评论0 收藏0

发表评论

0条评论

flyer_dev

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<