日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

asp 退出登录修改cookie能进入后台_深入浅出让你理解跨域与SSO单点登录原理与技术...

發(fā)布時(shí)間:2023/12/13 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 asp 退出登录修改cookie能进入后台_深入浅出让你理解跨域与SSO单点登录原理与技术... 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一:SSO體系結(jié)構(gòu)

SSO

SSO英文全稱Single Sign On,單點(diǎn)登錄。SSO是在多個(gè)應(yīng)用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的應(yīng)用系統(tǒng)。它包括可以將這次主要的登錄映射到其他應(yīng)用中用于同一個(gè)用戶的登錄的機(jī)制。它是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。

體系結(jié)構(gòu)

當(dāng)用戶第一次訪問應(yīng)用系統(tǒng)1的時(shí)候,因?yàn)檫€沒有登錄,會(huì)被引導(dǎo)到認(rèn)證系統(tǒng)中進(jìn)行登錄;根據(jù)用戶提供的登錄信息,認(rèn)證系統(tǒng)進(jìn)行身份校驗(yàn),如果通過校驗(yàn),應(yīng)該返回給用戶一個(gè)認(rèn)證的憑據(jù)--token;用戶再訪問別的應(yīng)用的時(shí)候就會(huì)將這個(gè)token帶上,作為自己認(rèn)證的憑據(jù),應(yīng)用系統(tǒng)接受到請(qǐng)求之后會(huì)把token送到認(rèn)證系統(tǒng)進(jìn)行校驗(yàn),檢查token的合法性。如果通過校驗(yàn),用戶就可以在不用再次登錄的情況下訪問應(yīng)用系統(tǒng)2和應(yīng)用系統(tǒng)3了 。

Token(令牌)

token的意思是“令牌”,是服務(wù)端生成的一串字符串,作為客戶端進(jìn)行請(qǐng)求的一個(gè)標(biāo)識(shí)。

當(dāng)用戶第一次登錄后,服務(wù)器生成一個(gè)token并將此token返回給客戶端,客戶端收到token后把它存儲(chǔ)起來,可以放在cookie或者Local Storage(本地存儲(chǔ))里。以后客戶端只需帶上這個(gè)token前來請(qǐng)求數(shù)據(jù)即可,無需再次帶上用戶名和密碼。

簡(jiǎn)單token的組成;uid(用戶唯一的身份標(biāo)識(shí))、time(當(dāng)前時(shí)間的時(shí)間戳)、sign(簽名,token的前幾位以哈希算法壓縮成的一定長(zhǎng)度的十六進(jìn)制字符串。為防止token泄露)。

設(shè)計(jì)token的值可以有以下方式

  • 用設(shè)備mac地址作為token

  • 用sessionid作為token

  • 同域SSO原理分析

    實(shí)際上,HTTP協(xié)議是無狀態(tài)的,單個(gè)系統(tǒng)的會(huì)話由服務(wù)端Session進(jìn)行維持,Session保持會(huì)話的原理是通過Cookie把sessionId寫入瀏覽器,每次訪問都會(huì)自動(dòng)攜帶全部Cookie,在服務(wù)端讀取其中的sessionId進(jìn)行驗(yàn)證實(shí)現(xiàn)會(huì)話保持。同域下單點(diǎn)登錄其實(shí)就是手寫token代替sessionId進(jìn)行會(huì)話認(rèn)證。

    token的生成

    服務(wù)端生成token后,將token與user對(duì)象存儲(chǔ)在Map結(jié)構(gòu)中,token為Key,user對(duì)象為value,response.addCookie()生成新的Cookie,名為token,值為token的值。

    token過期移除

    將服務(wù)端的token從Map中移除,再刪除瀏覽器端的名為token的Cookie。

    認(rèn)證流程

    跨域SSO原理分析

    當(dāng)有多個(gè)系統(tǒng)時(shí),認(rèn)證機(jī)制的流程如下:

  • 提供用戶登錄界面,供用戶進(jìn)行身份認(rèn)證

  • 用戶驗(yàn)證通過后,生成新token

  • 將tokenuser 對(duì)存入全局MAP中供校驗(yàn)

  • 將token寫入所有域的Cookie中

  • 頁(yè)面重定向回原始請(qǐng)求URL

  • 分析

    當(dāng)系統(tǒng)有多個(gè)并且在不同域(domain)時(shí),Cookie只會(huì)作用在當(dāng)前域下。

    將token寫入所有域的Cookie中才是解決跨域SSO的核心。

    二:Cookie增刪改查

    如何讀取Cookie?

    通過Servlet中的request對(duì)象可以讀取到Cookie數(shù)組,然后foreach遍歷讀取,一般只是獲取到nam和value,其他信息寫入到瀏覽器后,瀏覽器不主動(dòng)再發(fā)回來,讀取并無意義。

    ????????Cookie[]?cookies?=?request.getCookies();
    ????????if?(cookies?!=?null)?{
    ????????????for?(Cookie?cookie?:?cookies)?{
    ????????????????System.out.println(
    ????????????????????????cookie.getName()?+
    ????????????????????????cookie.getValue()?+
    ????????????????????????cookie.getMaxAge()?+
    ????????????????????????cookie.getPath()?+
    ????????????????????????cookie.getDomain()?+
    ????????????????????????cookie.getSecure()?+
    ????????????????????????cookie.isHttpOnly()//客戶端js是否可以獲取
    ????????????????);
    ????????????}
    ????????}

    如何寫入Cookie帶瀏覽器?

    新建Cookie對(duì)象設(shè)置一系列屬性,然后添加到response中去。需要注意的是,當(dāng)設(shè)置path為“/”時(shí),表示所有路徑都會(huì)被該Cookie作用到,如果設(shè)置為/path1那么由/path2發(fā)起請(qǐng)求就不會(huì)攜帶該Cookie。默認(rèn)不設(shè)置只作用在當(dāng)前路徑下。

    ????????Cookie?cookie?=?new?Cookie("myCookieName","myCookieValue");
    ????????cookie.setHttpOnly(false);//Javascript不能處理
    ????????//一個(gè)正值表示cookie將在經(jīng)過許多秒之后過期。注意,值是cookie過期的最大時(shí)間,而不是cookie當(dāng)前的時(shí)間。
    ????????//負(fù)值表示cookie沒有持久存儲(chǔ),在Web瀏覽器退出時(shí)將被刪除。零值會(huì)導(dǎo)致刪除cookie。
    ????????cookie.setMaxAge(-1000);
    ????????cookie.setSecure(false);//如果為true,僅支持HTTPS協(xié)議
    ????????//cookie對(duì)指定目錄中的所有頁(yè)面以及該目錄子目錄中的所有頁(yè)面都可見。
    ????????cookie.setPath("/");
    ????????//cookie.setDomain("www.a.com");//默認(rèn)情況下,cookie只返回給發(fā)送cookie的服務(wù)器。
    ????????response.addCookie(cookie);

    修改Cookie

    修改更新Cookie時(shí),除了要保證Cookie的name是相同的,也要保證Cookie的一系列屬性是相同的,否則瀏覽器會(huì)生成新的Cookie。

    刪除Cookie

    只需要設(shè)置Cookie的MaxAge為負(fù)值,意味著是過去的Cookie,瀏覽器就會(huì)清除。

    三:跨域讀寫Cookie

    1.利用HTML的script標(biāo)簽跨域?qū)慍ookie

    比如當(dāng)前域是www.a.com,下面的script標(biāo)簽是跨域?qū)慶ookie的核心,通過此標(biāo)簽實(shí)現(xiàn)了向www.b.com域?qū)懭隿ookie:

    <script?type="text/javascript"?src="http://www.b.com/setCookie?cname=token&cval=123456">script>

    P3P協(xié)議

    P3P是一種被稱為個(gè)人隱私安全平臺(tái)項(xiàng)目(the Platform for Privacy Preferences)的標(biāo)準(zhǔn),能夠保護(hù)在線隱私權(quán),使Internet沖浪者可以選擇在瀏覽網(wǎng)頁(yè)時(shí),是否被第三方收集并利用自己的個(gè)人信息。如果一個(gè)站點(diǎn)不遵守P3P標(biāo)準(zhǔn)的話,那么有關(guān)它的Cookies將被自動(dòng)拒絕,并且P3P還能夠自動(dòng)識(shí)破多種Cookies的嵌入方式。p3p是由全球資訊聯(lián)盟網(wǎng)所開發(fā)的。

    舉個(gè)例子:

    我們?cè)谠L問A網(wǎng)站時(shí),理論上說,我們只能把Cookie信息保存到A站域名下,而不能寫入到B網(wǎng)站下。如果想要跨域讀寫Cookie,只是通過script標(biāo)簽變相訪問B網(wǎng)站在一些瀏覽器是行不通的,此時(shí)B網(wǎng)站的服務(wù)器應(yīng)該告訴瀏覽器允許A網(wǎng)站寫入Cookie,否則瀏覽器將會(huì)拒絕執(zhí)行,這就是P3P協(xié)議。

    服務(wù)端如何告訴瀏覽器?

    P3P提供了一種簡(jiǎn)單的方式 ,來加載用戶隱私策略,只要在http響應(yīng)的頭信息中增加 response.setHeader("P3P","CP=NON DSP COR CURa ADMa DEVa TAIa PSAa PSDa IVAa IVDa CONa HISa TELa OTPa OUR UNRa IND UNI COM NAV INT DEM CNT PRE LOC);而無需指定隱私策略文件也可以達(dá)到指定隱私策略的目的。CP=后面的字符串分別代表不同的策略信息。

    總結(jié)

    因?yàn)镻3P協(xié)議所以不能保證所有瀏覽器都能通過script標(biāo)簽方式跨域?qū)慍ookie,有的瀏覽器本身就是拒絕跨域的。

    顯然這種方式是不能保證跨域?qū)慶ookie的成功性。

    2.通過URL參數(shù)實(shí)現(xiàn)跨域信息傳遞

    我們要在A域?qū)崿F(xiàn)寫入token到B域,需要在A域設(shè)計(jì)一個(gè)servlet接收請(qǐng)求,代碼:

    @WebServlet(name?=?"tg")
    public?class?Servlet?extends?HttpServlet?{
    ????protected?void?doPost(HttpServletRequest?request,?HttpServletResponse?response)?throws?IOException?{
    ????????//獲取請(qǐng)求的目標(biāo)域
    ????????String?from?=?request.getParameter("from");
    ????????//生成token,
    ????????String?token?=?"123456";
    ????????//重定向到目標(biāo)域
    ????????response.sendRedirect(from?+?"?cname=token&cval="?+?token);
    ????}
    ????...
    ?}

    由a域發(fā)起請(qǐng)求,請(qǐng)求地址:http://www.a.com/tg?from=http://www.b.com/set_cookie, 請(qǐng)求后該Servlet會(huì)獲取from參數(shù)的值并生成token最后讓客戶端重定向到http://www.b.com/set_cookie?cname=token&cval=123456,然后B域的Servlet("set_cookie")獲取Url參數(shù)寫入Cookie到客戶端,代碼:

    ????????//將要寫入的cookie項(xiàng),調(diào)用者通過參數(shù)傳遞
    ????????String?cookieName?=?request.getParameter("cname");
    ????????String?cookieValue?=?request.getParameter("cval");

    ????????//生成cookie
    ????????Cookie?cookie?=?new?Cookie(cookieName,cookieValue);
    ????????cookie.setPath("/");
    ????????//一般可以將domain設(shè)置到頂級(jí)域
    ????????//cookie.setDomain("www.b.com");
    ????????response.addCookie(cookie);

    這時(shí)候再查看B域下的Cookie就可以發(fā)現(xiàn)(token=123456)已經(jīng)被寫入到瀏覽器。

    3.讀取其它域的Cookie

    利用script標(biāo)簽

    利用script標(biāo)簽執(zhí)行另一個(gè)域?qū)崿F(xiàn)的讀取cookie方法,script標(biāo)簽返回結(jié)果將是變量定義形式的JS代碼,每一個(gè)變量表示一個(gè)cookie項(xiàng),這些代碼加載后,此頁(yè)面后續(xù)JS代碼可以直接在script腳本中讀取已定義的變量值,即各cookie值。

    <script?type="text/javascript"?src="http://www.b.com/reaf_cookies">script>

    HTML頁(yè)面讀取

    <script>
    alert(token);script>

    B域的url為/read_cookies的Servlet是如何實(shí)現(xiàn)的?

    如圖,首先我們先在request中獲取cookie數(shù)組,然后for循環(huán)遍歷拼接為類似var token='test123';的字符串。最重要的是設(shè)置ContentType為application/javascript,代碼如下:

    ????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
    ????????Cookie[]?cookies?=?request.getCookies();
    ????????StringBuilder?stringBuilder?=?new?StringBuilder();
    ????????//一定要設(shè)置響應(yīng)類型,否則可能導(dǎo)致IE不解析js直接進(jìn)行下載操作
    ????????response.setContentType("application/javascript");

    ????????if?(cookies?!=?null)?{
    ????????????for?(Cookie?cookie?:?cookies)?{
    ????????????????//結(jié)果類似于這樣?var?token='123456';
    ????????????????stringBuilder.append("var?")
    ????????????????????????.append(cookie.getName())
    ????????????????????????.append("=")
    ????????????????????????.append("'")
    ????????????????????????.append(cookie.getValue())
    ????????????????????????.append("'")
    ????????????????????????.append(";");
    ????????????}
    ????????????response.getWriter().append(stringBuilder.toString());
    ????????}
    ?????}

    四:跨域Ajax請(qǐng)求

    1.Jsonp的方式

    跨域Ajax請(qǐng)求在瀏覽器階段就會(huì)被阻止,我們可以通過script標(biāo)簽返回想要的json數(shù)據(jù)。如圖:

    ?<script?type="text/javascript"?src="http://www.b.com/user_info_2">script>

    后臺(tái)Servlet代碼

    ????????//要正確設(shè)置響應(yīng)類型,避免IE出現(xiàn)下載
    ????????response.setContentType("application/javascript");

    ????????String?userInfo?=?"{\"id\":1,\"name\":\"zhangsan\"}";

    ????????//返回拼接的javascript語(yǔ)句字符串,語(yǔ)句本身執(zhí)行一個(gè)調(diào)用函數(shù)的操作
    ????????String?ret?=?"showResult("+userInfo+")";

    在Servlet中設(shè)置返回類型為javascript,并正常獲取json格式的數(shù)據(jù),最關(guān)鍵的是在最后拼接為js語(yǔ)句字符串,語(yǔ)句本身就是執(zhí)行一個(gè)調(diào)用函數(shù)的操作:

    showResult({"id":1,"name":"zhangsan"})

    而showResult(ret)回調(diào)函數(shù)自然需要我們?cè)谥熬投x好:

    ????<script>function?showResult(ret){console.log(ret)
    ????????}script>

    優(yōu)化

    這種方式,前端的回調(diào)函數(shù)和后端耦合度較高。前端可以在調(diào)用后端方法時(shí)帶上回調(diào)函數(shù)名(?callback=xxxxx),后端優(yōu)化后的代碼:

    ????????//通過參數(shù)傳遞回調(diào)函數(shù)名,一定程度降低了前后端代碼的耦合度
    ????????String?callback?=?request.getParameter("callback");

    ????????//返回拼接的javascript語(yǔ)句字符串,語(yǔ)句本身執(zhí)行一個(gè)調(diào)用函數(shù)的操作
    ????????String?ret?=?callback+"("+userInfo+")";

    再優(yōu)化

    HTML頁(yè)面加載到我們定義的script標(biāo)簽時(shí)就會(huì)執(zhí)行我們的回調(diào)方法,更多時(shí)候我們想要控制回調(diào)方法的執(zhí)行時(shí)機(jī)。這個(gè)問題可以通過前端動(dòng)態(tài)生成節(jié)點(diǎn)來解決,當(dāng)我們執(zhí)行完之后再移除節(jié)點(diǎn)即可:

    ????<script>var?script?=?document.createElement("script");
    ????????script.src?=?"http://www.b.com/user_info_2?callback=showResult";document.body.appendChild(script);
    ????????script.onload?=?function?()?{document.body.removeChild(script);
    ????????}script>

    JQuery

    我們可以把這些封裝到一個(gè)方法里,隨時(shí)調(diào)用。這里可以使用Jquery封裝好的API。

    ????????????????$.ajax({
    ????????????????????url:?"http://localhost:9090/query",
    ????????????????????type:?"GET",
    ????????????????????dataType:?"jsonp",??//指定服務(wù)器返回的數(shù)據(jù)類型
    ????????????????????jsonpCallback:?"showData",??//指定回調(diào)函數(shù)名稱
    ????????????????????success:?function?(data)?{
    ????????????????????????console.info("調(diào)用success");
    ????????????????????}
    ????????????????});
    ????????????????function?showData(data){
    ????????????????????var?result?=?JSON.stringify(data);
    ????????????????}

    2.CORS簡(jiǎn)介

    出于安全原因,瀏覽器限制從腳本內(nèi)發(fā)起的跨源HTTP請(qǐng)求。例如,XMLHttpRequest和Fetch API遵循同源策略。這意味著使用這些API的Web應(yīng)用程序只能從加載應(yīng)用程序的同一個(gè)域請(qǐng)求HTTP資源,除非使用CORS頭文件。

    跨域資源共享( CORS)機(jī)制允許 Web 應(yīng)用服務(wù)器進(jìn)行跨域訪問控制,從而使跨域數(shù)據(jù)傳輸?shù)靡园踩M(jìn)行。瀏覽器支持在 API 容器中(例如 XMLHttpRequest或 Fetch)使用 CORS,以降低跨域 HTTP 請(qǐng)求所帶來的風(fēng)險(xiǎn)。

    GET跨域請(qǐng)求原理

    當(dāng)客戶端瀏覽器發(fā)起一個(gè)跨域的HTTP請(qǐng)求,瀏覽器經(jīng)過請(qǐng)求響應(yīng),如果沒有看到Access-Control-Allow-Origin的header頭部,會(huì)認(rèn)為你的請(qǐng)求是不合法的。換句話說,我們只要在被請(qǐng)求的服務(wù)器上設(shè)置這個(gè)頭部,瀏覽器就會(huì)允許我們進(jìn)行請(qǐng)求。

    解決方法

    對(duì)于簡(jiǎn)單的請(qǐng)求,我們直接在服務(wù)端 設(shè)置就可以了。如圖,只要請(qǐng)求的地址是www.a.com就會(huì)被瀏覽器允許跨域。如果想要允許對(duì)于多個(gè)來源可以用,號(hào)進(jìn)行隔開;如果想要允許所有來源,設(shè)置為*就可以,不過建議不要使用,這樣會(huì)造成安全隱患。

    ????protected?void?doGet(HttpServletRequest?request,?HttpServletResponse?response)?throws?ServletException,?IOException?{
    ????????//簡(jiǎn)單請(qǐng)求,直接設(shè)置Access-Control-Allow-Origin就可以了
    ????????response.setHeader("Access-Control-Allow-Origin","*");
    ????????//要正確設(shè)置響應(yīng)類型,避免IE出現(xiàn)下載
    ????????response.setContentType("application/json");

    ????????response.getWriter().write("{\"id\":1,\"name\":\"zhangsan\"}");
    ????}

    對(duì)于復(fù)雜的請(qǐng)求,比如POST,或者加入了自定義header頭部,上面的方法就不適用了。下面繼續(xù)看。

    CORS流程

    請(qǐng)求發(fā)起時(shí),瀏覽器先判斷當(dāng)前是否是跨域的AJAX;

    如果是,判斷是否是普通類型請(qǐng)求(GET類型,無自定義頭數(shù)據(jù));

    普通請(qǐng)求,直接發(fā)起GET到服務(wù)端,在響應(yīng)頭中尋找 Access-Contro-Alow- Origin,如果有且允許,處理響應(yīng)結(jié)果;

    不是普通請(qǐng)求(非GET類型,或有自定義頭), 先 PreFlight(即發(fā)起一個(gè) method= OPTIONS)的請(qǐng)求,

    要求返回 Access-Control-Allow- Methods和 Access-Control-Allow- Headers, 內(nèi)容體為空

    PreFlight正確執(zhí)行后, 再發(fā)起GET請(qǐng)求, 獲得響應(yīng)結(jié)果, 并處理結(jié)果.

    實(shí)現(xiàn)

    歸根到我們的代碼中的實(shí)現(xiàn),只需要在servlet中定義options請(qǐng)求的處理方法即可。如圖

    ????protected?void?doOptions(HttpServletRequest?req,?HttpServletResponse?response)?{
    ????????response.setHeader("Access-Control-Allow-Origin","*");
    ????????response.setHeader("Access-Control-Allow-Methods","GET,POST,OPTIONS,DELETE");
    ????????response.setHeader("Access-Control-Allow-Headers","reqid,xxx");
    ????}

    注意:Access-Control-Allow-Origin是必需的。

    3.兩種跨域AJax請(qǐng)求對(duì)比

    兼容性

    Jsonp對(duì)所有瀏覽器兼容,CORS對(duì)現(xiàn)代瀏覽器兼容(IE8之后)。

    請(qǐng)求方式

    Jsonp只支持GET方式,CORS支持GET,POST等。

    調(diào)用方式

    Jsonp需要服務(wù)端封裝返回信息,CORS更像原生AJax一樣使用。

    作者:風(fēng)平浪靜如碼
    鏈接:

    https://juejin.im/post/5e81e82551882573a1377a08

    總結(jié)

    以上是生活随笔為你收集整理的asp 退出登录修改cookie能进入后台_深入浅出让你理解跨域与SSO单点登录原理与技术...的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。