摘要:時(shí)間年月日星期三說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。慕課網(wǎng)教學(xué)示例源碼無(wú)個(gè)人學(xué)習(xí)源碼第一章概述課程介紹及介紹課程目標(biāo)認(rèn)識(shí)并理解及其應(yīng)用,并能根據(jù)其實(shí)現(xiàn)原理自行實(shí)現(xiàn)。
時(shí)間:2017年3月22日星期三
說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com
教學(xué)示例源碼:無(wú)
個(gè)人學(xué)習(xí)源碼:https://github.com/zccodere/s...
課程目標(biāo)
認(rèn)識(shí)并理解SSO及其應(yīng)用,并能根據(jù)其實(shí)現(xiàn)原理自行實(shí)現(xiàn)SSO。
學(xué)習(xí)內(nèi)容
1.SSO的介紹和應(yīng)用體驗(yàn)(以新浪為例) SSO:一次登錄,處處穿梭 2.SSO的分類(lèi)介紹的實(shí)現(xiàn)探討 同域SSO:不同的應(yīng)用位于同一個(gè)域名下面 跨域SSO:不同的應(yīng)用位于不同的域名下面 3.各種SSO的具體實(shí)現(xiàn)介紹的代碼示例
同域SSO圖示
1-2 SSO核心技術(shù)分析SSO的實(shí)現(xiàn)步驟和原理
以旅游是購(gòu)買(mǎi)的通票為例:
SSO特點(diǎn):
1.必須要登陸一次 2.票據(jù)與驗(yàn)票機(jī)制
實(shí)現(xiàn)SSO的步驟拆解
關(guān)鍵:存儲(chǔ)票據(jù)(購(gòu)票與存儲(chǔ)),查驗(yàn)票據(jù)(是否有票與是否有效)
核心技術(shù)點(diǎn)實(shí)現(xiàn)原理:
比照旅游進(jìn)行第二章:同域SSO 2-1 同域SSO準(zhǔn)備工作
教學(xué)示例流程圖
個(gè)人學(xué)習(xí)流程圖
項(xiàng)目搭建
說(shuō)明:教學(xué)使用SSH搭建演示項(xiàng)目,我在學(xué)習(xí)時(shí)使用springboot搭建,源碼可以在我的github上查看、下載、運(yùn)行等。因?yàn)楸竟?jié)主要是講SSO單點(diǎn)登錄,并不是將項(xiàng)目搭建,所以搭建過(guò)程省略。
項(xiàng)目命名為:myssosamedomain
2-2 編寫(xiě)統(tǒng)一登錄接口編寫(xiě)校驗(yàn)工具類(lèi)
package com.myimooc.sso.web.util; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; /** * 登錄校驗(yàn)工具類(lèi) * @author ZhangCheng * @date 2017-03-22 * @version V1.0 */ public class LoginCheck { /** 測(cè)試用戶名 */ public static final String USERNAME="user"; /** 測(cè)試密碼*/ public static final String PASSWORD="123"; /** Cookie鍵 */ public static final String COOKIE_NAME = "ssocookie"; /** Cookie值*/ public static final String COOKIE_VALUE = "sso"; /** * 登錄用戶名和密碼校驗(yàn) * @param username 用戶名 * @param password 密碼 * @return true用戶名和密碼正確;false用戶名或密碼錯(cuò)誤 */ public static boolean checkLogin(String username,String password){ if(USERNAME.equalsIgnoreCase(username) && PASSWORD.equalsIgnoreCase(password)){ return true; } return false; } /** * 校驗(yàn)Cookie * @param request * @return true正確;false錯(cuò)誤 */ 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; } }
編寫(xiě)校驗(yàn)控制器
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 { /** * 處理用戶登錄請(qǐng)求 * @param username 用戶名 * @param password 密碼 * @param gotoUrl 登錄成功后請(qǐng)求路徑 * @param response * @return */ @PostMapping("/doLogin") public ModelAndView doLogin(String username,String password, String gotoUrl,HttpServletResponse response){ ModelAndView mv = new ModelAndView("login_fail"); // 校驗(yàn)用戶名和密碼 boolean ok = LoginCheck.checkLogin(username, password); // 判斷是否登錄成功 if(ok){ Cookie cookie = new Cookie(LoginCheck.COOKIE_NAME,LoginCheck.COOKIE_VALUE); // 頂級(jí)域名下,所有應(yīng)用都是可見(jiàn)的 cookie.setPath("/"); // 添加Cookie response.addCookie(cookie); mv.setViewName("redirect:"+gotoUrl); } return mv; } /** * 跳轉(zhuǎn)到登錄頁(yè)面 * @return */ @GetMapping("/login") public ModelAndView login(){ return new ModelAndView("login"); } }
編寫(xiě)登錄頁(yè)面
登錄 請(qǐng)登錄
編寫(xiě)登錄失敗頁(yè)面
2-3 編寫(xiě)登錄頁(yè)面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 編寫(xiě)DEMO1和DEMO2的主頁(yè)
demo1頁(yè)面
歡迎訪問(wèn)demo1 這是demo1的主頁(yè)
demo2頁(yè)面
2-5 同域SSO最終效果演示歡迎訪問(wèn)demo2 這是demo2的主頁(yè)
訪問(wèn)demo1頁(yè)面需要登錄
訪問(wèn)demo2頁(yè)面需要登錄
在demo1頁(yè)面處登錄
登錄成功,可以訪問(wèn)demo1頁(yè)面
再次訪問(wèn)demo2時(shí),不需要登錄即可訪問(wèn)
第三章:同父域SSO 3-1 準(zhǔn)備工作教學(xué)示例流程圖
個(gè)人學(xué)習(xí)流程圖
通過(guò)修改host文件,來(lái)模擬實(shí)現(xiàn)父子域名。
文件路徑:C:WindowsSystem32driversetchosts
修改如下
說(shuō)明:正常情況下,應(yīng)該分別建立三個(gè)項(xiàng)目,對(duì)應(yīng)demo1.x.com、demo2.x.com、check.x.com。但為了演示講解方便,我們通過(guò)項(xiàng)目里面對(duì)應(yīng)的包名來(lái)區(qū)分是哪個(gè)項(xiàng)目。
項(xiàng)目搭建
項(xiàng)目命名為:myssosamefather
編寫(xiě)消息響應(yīng)類(lèi)
package com.myimooc.sso.util; import java.io.Serializable; /** * 消息響應(yīng)對(duì)象 * @author ZhangCheng * @date 2017-04-02 * @version V1.0 */ public class RespMessage implements Serializable{ private static final long serialVersionUID = 1L; /** 響應(yīng)編號(hào) */ private String respCode; /** 響應(yīng)消息 */ 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; } }
編寫(xiě)登錄校驗(yàn)工具類(lèi)
package com.myimooc.sso.util; /** * 登錄校驗(yàn)工具類(lèi) * * @author ZhangCheng * @date 2017-03-22 * @version V1.0 */ public class LoginCheck { /** 測(cè)試用戶名 */ public static final String USERNAME = "user"; /** 測(cè)試密碼 */ public static final String PASSWORD = "123"; /** Cookie鍵 */ public static final String COOKIE_NAME = "ssocookie"; /** Cookie值 */ public static final String COOKIE_VALUE = "sso"; /** * 登錄用戶名和密碼校驗(yàn) * * @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; } /** * 校驗(yàn)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; } }
編寫(xiě)http請(qǐng)求工具類(lèi)
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工具類(lèi) * @author ZhangCheng * @date 2017-04-02 * @version V1.0 */ public class HttpUtils { /** * 向指定url路徑發(fā)起get請(qǐng)求,校驗(yàn)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校驗(yàn)請(qǐng)求失敗"); return respMessage; }finally { if(httpURLConnection !=null){ httpURLConnection.disconnect(); } } } }
check.x.com:編寫(xiě)認(rèn)證中心控制器
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 { /** * 處理用戶登錄請(qǐng)求 * * @param username * 用戶名 * @param password * 密碼 * @param gotoUrl * 登錄成功后請(qǐng)求路徑 * @param response * @return */ @PostMapping("/doLogin") public ModelAndView doLogin(String username, String password, String gotoUrl, HttpServletResponse response) { ModelAndView mv = new ModelAndView("login_fail"); // 校驗(yàn)用戶名和密碼 boolean ok = LoginCheck.checkLogin(username, password); // 判斷是否登錄成功 if (ok) { Cookie cookie = new Cookie(LoginCheck.COOKIE_NAME, LoginCheck.COOKIE_VALUE); // 設(shè)置在父域下面 cookie.setDomain("x.com"); // 頂級(jí)域名下,所有應(yīng)用都是可見(jiàn)的 cookie.setPath("/"); // 添加Cookie response.addCookie(cookie); mv.setViewName("redirect:" + gotoUrl); } return mv; } /** * 校驗(yàn)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無(wú)效"); boolean isOk = LoginCheck.checkCookie(cookieName, cookieValue); if(isOk){ result.setRespCode("200"); result.setRespMsg("Cookie有效"); } return result; } /** * 跳轉(zhuǎn)到登錄頁(yè)面 * * @return */ @GetMapping("/login") public ModelAndView login() { return new ModelAndView("login"); } }3-3 編寫(xiě)demo1和demo2項(xiàng)目的控制層
demo1.x.com:編寫(xiě)demo1項(xiàng)目控制器
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(); //校驗(yàn)cookie是否為空 Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length > 0){ //校驗(yàn)cookie是否存在 for(Cookie cookie : cookies){ if("ssocookie".equals(cookie.getName())){ //向校驗(yàn)服務(wù)器發(fā)送校驗(yàn)請(qǐng)求 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:編寫(xiě)demo2項(xiàng)目控制器
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(); //校驗(yàn)cookie是否為空 Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length > 0){ //校驗(yàn)cookie是否存在 for(Cookie cookie : cookies){ if("ssocookie".equals(cookie.getName())){ //向校驗(yàn)服務(wù)器發(fā)送校驗(yàn)請(qǐng)求 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 編寫(xiě)登錄頁(yè)
3-5 同父域情況下的SSO效果演示Insert title here 請(qǐng)登錄
請(qǐng)注意觀察瀏覽器URL地址
訪問(wèn)demo1.x.com:需要登錄
訪問(wèn)demo2.x.com:需要登錄
在demo1.x.com處登錄成功后,跳轉(zhuǎn)至demo1頁(yè)面
再訪問(wèn)demo2.x.com的demo2頁(yè)面時(shí),不再需要登錄了
第四章:跨域SSO的實(shí)現(xiàn) 4-1 準(zhǔn)備工作教學(xué)示例流程圖
個(gè)人學(xué)習(xí)流程圖
通過(guò)修改host文件,來(lái)模擬實(shí)現(xiàn)跨域應(yīng)用。
文件路徑:C:WindowsSystem32driversetchosts
修改如下
說(shuō)明:正常情況下,應(yīng)該分別建立三個(gè)項(xiàng)目,對(duì)應(yīng)www.a.com、www.b.com、www.x.com。但為了演示講解方便,我們通過(guò)項(xiàng)目里面對(duì)應(yīng)的包名來(lái)區(qū)分是哪個(gè)項(xiàng)目。
項(xiàng)目搭建
項(xiàng)目命名為:myssocrossdomain
完成后的目錄結(jié)構(gòu)如下
4-2 編寫(xiě)統(tǒng)一登錄接口編寫(xiě)消息響應(yīng)類(lèi)
package com.myimooc.sso.util; import java.io.Serializable; import java.util.Map; /** * 消息響應(yīng)對(duì)象 * @author ZhangCheng * @date 2017-04-02 * @version V1.0 */ public class RespMessage implements Serializable{ private static final long serialVersionUID = 1L; /** 響應(yīng)編號(hào) */ private String respCode; /** 響應(yīng)消息 */ private String respMsg; /** 響應(yīng)數(shù)據(jù) */ private MaprespArgs; 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 + "]"; } }
編寫(xiě)http請(qǐng)求工具類(lèi)
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請(qǐng)求工具類(lèi) * @author ZhangCheng * @date 2017-04-02 * @version V1.0 */ public class HttpUtils { /** * 向指定url路徑發(fā)起get請(qǐng)求 * @param url 請(qǐng)求路徑 * @param param 請(qǐng)求參數(shù) * @return */ public static RespMessage doGet(String url,Mapparam){ RespMessage respMessage = new RespMessage(); HttpURLConnection httpURLConnection = null; URL targetUrl = null; try{ // 拼裝請(qǐng)求參數(shù) 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("請(qǐng)求發(fā)起失敗"); return respMessage; }finally { if(httpURLConnection !=null){ httpURLConnection.disconnect(); } } } }
www.x.com:編寫(xiě)認(rèn)證中心校驗(yàn)工具類(lèi)
package com.myimooc.sso.www.x.com; /** * 登錄校驗(yàn)工具類(lèi) * * @author ZhangCheng * @date 2017-03-22 * @version V1.0 */ public class LoginCheck { /** 測(cè)試用戶名 */ public static final String USERNAME = "user"; /** 測(cè)試密碼 */ public static final String PASSWORD = "123"; /** Cookie鍵 */ public static final String COOKIE_NAME = "ssocookie"; /** Cookie值 */ public static final String COOKIE_VALUE = "sso"; /** * 登錄用戶名和密碼校驗(yàn) * * @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; } /** * 校驗(yàn)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:編寫(xiě)認(rèn)證中心控制器
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 { /** * 校驗(yàn)用戶信息 * @param param * @return */ @GetMapping("/doLogin") @ResponseBody public RespMessage doLogin(String username,String password) { RespMessage result = new RespMessage(); result.setRespCode("500"); result.setRespMsg("用戶名或密碼錯(cuò)誤"); // 校驗(yàn)用戶名和密碼 boolean ok = LoginCheck.checkLogin(username,password); // 判斷是否登錄成功 if (ok) { result.setRespCode("200"); result.setRespMsg("用戶名和密碼正確"); List
www.x.com:編寫(xiě)登錄頁(yè)
登錄 請(qǐng)登錄
www.x.com:編寫(xiě)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,//發(fā)送同步請(qǐng)求 url:requesturl, data:"username="+username+"&password="+password, success:function(result){ // 登錄失敗 if(result.respCode != 200 ){ alert(result.respMsg); return; } // 登錄成功 var targetCookies = result.respArgs.targetCookies; // 向服務(wù)器發(fā)出添加cookie請(qǐng)求 $.each(targetCookies,function(i,targetCookie){ var targetUrl = targetCookie.targetUrl; var cookieName = targetCookie.cookieName; var cookieValue = targetCookie.cookieValue; creat(targetUrl,cookieName,cookieValue); }); } }); // 跳轉(zhuǎn)到目標(biāo)頁(yè) window.location.href=gotoUrl; } /** js利用iframe實(shí)現(xiàn)跨域添加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 編寫(xiě)登錄校驗(yàn)接口
www.a.com:編寫(xiě)控制器
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 { /** * 跳轉(zhuǎn)到demo1的主頁(yè) * @param request * @return */ @RequestMapping("/demo1") public ModelAndView demo1(HttpServletRequest request) { ModelAndView mv = new ModelAndView(); //校驗(yàn)cookie是否為空 Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length > 0){ //校驗(yàn)cookie是否存在 for(Cookie cookie : cookies){ if("ssocookie".equals(cookie.getName())){ // 封裝請(qǐng)求參數(shù) Mapparam = new HashMap (); param.put("cookieName", cookie.getName()); param.put("cookieValue", cookie.getValue()); // 向校驗(yàn)服務(wù)器發(fā)送校驗(yàn)請(qǐng)求 String url = "http://www.x.com/sso/checkCookie"; RespMessage respMessage = HttpUtils.doGet(url, param); // 校驗(yàn)通過(guò) 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){ // 向校驗(yàn)服務(wù)器發(fā)送校驗(yàn)請(qǐng)求 String url = "http://www.x.com/sso/doLogin"; RespMessage respMessage = HttpUtils.doGet(url, param); System.out.println("SSO服務(wù)器響應(yīng)消息:"+respMessage); return respMessage; } /** * 想當(dāng)前域添加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:編寫(xiě)控制器
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(); //校驗(yàn)cookie是否為空 Cookie[] cookies = request.getCookies(); if(cookies != null && cookies.length > 0){ //校驗(yàn)cookie是否存在 for(Cookie cookie : cookies){ if("ssocookie".equals(cookie.getName())){ // 封裝請(qǐng)求參數(shù) Map4-4 跨域SSO效果演示param = new HashMap (); param.put("cookieName", cookie.getName()); param.put("cookieValue", cookie.getValue()); // 向校驗(yàn)服務(wù)器發(fā)送校驗(yàn)請(qǐng)求 String url = "http://www.x.com/sso/checkCookie"; RespMessage respMessage = HttpUtils.doGet(url, param); // 校驗(yàn)通過(guò) 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){ // 向校驗(yàn)服務(wù)器發(fā)送校驗(yàn)請(qǐng)求 String url = "http://www.x.com/sso/doLogin"; RespMessage respMessage = HttpUtils.doGet(url, param); System.out.println("SSO服務(wù)器響應(yīng)消息:"+respMessage); return respMessage; } /** * 向當(dāng)前域添加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); } }
注意觀察瀏覽器URL地址
訪問(wèn)www.a.com的a項(xiàng)目需要登錄
訪問(wèn)www.b.com的b項(xiàng)目需要登錄
在www.a.com域登錄
登錄成功
www.b.com域即可直接訪問(wèn),免登陸
第五章:課程總結(jié) 5-1 課程總結(jié)1.核心是COOKIE,需要注意設(shè)置的域、位置和安全性
注意COOKIE的加密
2.應(yīng)用群的安全性問(wèn)題:木桶效應(yīng)
即應(yīng)用群的安全性受限于某個(gè)安全性最低的應(yīng)用
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/66947.html
時(shí)間:2017年07月09日星期日說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:概述 1-1 課程概述 主要內(nèi)容 驗(yàn)證碼歷史 課程內(nèi)容 不同方案對(duì)比 設(shè)計(jì)與實(shí)現(xiàn) 總結(jié) 1-2 驗(yàn)證碼歷史 驗(yàn)證碼歷史 無(wú)驗(yàn)證碼:垃圾騷擾 Luis von Ahn:Captcha 不斷...
摘要:時(shí)間年月日星期六說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。第六章公眾號(hào)與開(kāi)發(fā)平臺(tái)關(guān)聯(lián)公眾號(hào)與開(kāi)放平臺(tái)關(guān)聯(lián)情景說(shuō)明當(dāng)使用端進(jìn)行微信授權(quán)登錄時(shí),得到的和公眾號(hào)授權(quán)登錄時(shí)得到的不一樣。 時(shí)間:2017年08月12日星期六說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹...
摘要:此時(shí),用戶想要訪問(wèn)系統(tǒng)受限的資源比如說(shuō)訂單功能,訂單功能需要登錄后才能訪問(wèn),系統(tǒng)發(fā)現(xiàn)用戶并沒(méi)有登錄,于是重定向到認(rèn)證中心,并將自己的地址作為參數(shù)。 前言 只有光頭才能變強(qiáng)。文本已收錄至我的GitHub倉(cāng)庫(kù),歡迎Star:https://github.com/ZhongFuCheng3y/3y 在我實(shí)習(xí)之前我就已經(jīng)在看單點(diǎn)登錄的是什么了,但是實(shí)習(xí)的時(shí)候一直在忙其他的事,所以有幾個(gè)網(wǎng)站就...
摘要:此時(shí),用戶想要訪問(wèn)系統(tǒng)受限的資源比如說(shuō)訂單功能,訂單功能需要登錄后才能訪問(wèn),系統(tǒng)發(fā)現(xiàn)用戶并沒(méi)有登錄,于是重定向到認(rèn)證中心,并將自己的地址作為參數(shù)。前言 只有光頭才能變強(qiáng)。 文本已收錄至我的GitHub倉(cāng)庫(kù),歡迎Star:github.com/ZhongFuChen… 在我實(shí)習(xí)之前我就已經(jīng)在看單點(diǎn)登錄的是什么了,但是實(shí)習(xí)的時(shí)候一直在忙其他的事,所以有幾個(gè)網(wǎng)站就一直躺在我的收藏夾里邊: ...
摘要:此時(shí),用戶想要訪問(wèn)系統(tǒng)受限的資源比如說(shuō)訂單功能,訂單功能需要登錄后才能訪問(wèn),系統(tǒng)發(fā)現(xiàn)用戶并沒(méi)有登錄,于是重定向到認(rèn)證中心,并將自己的地址作為參數(shù)。前言 只有光頭才能變強(qiáng)。 文本已收錄至我的GitHub倉(cāng)庫(kù),歡迎Star:github.com/ZhongFuChen… 在我實(shí)習(xí)之前我就已經(jīng)在看單點(diǎn)登錄的是什么了,但是實(shí)習(xí)的時(shí)候一直在忙其他的事,所以有幾個(gè)網(wǎng)站就一直躺在我的收藏夾里邊: ...
閱讀 1522·2021-10-08 10:04
閱讀 821·2021-09-07 09:58
閱讀 3023·2019-08-30 15:55
閱讀 2549·2019-08-29 17:21
閱讀 2258·2019-08-28 18:04
閱讀 3152·2019-08-28 17:57
閱讀 818·2019-08-26 11:46
閱讀 2365·2019-08-23 17:20