国产欧美另类精品又又欠钱_免费自慰AV_免费观看全部A片大全不卡_国产成人综合久久精品小说,Chinese 中国 XXXX 乱子 a,免费AV无码一区二区,国产三级久久,91在线无,免费黄片视频观看,亚洲国产精品人人做人人爱,中文一区在线

南京軟件定制開發(fā)

南京傾心軟件歡迎您訪問本站

13605185909

新聞資訊

NEWS CENTER
欄目導(dǎo)航

南京軟件開發(fā)之Cookie、Session,、Token

發(fā)布時(shí)間:Mar 11, 2021         已有 人瀏覽

Cookie


  • 瀏覽器第一次訪問服務(wù)端時(shí),,服務(wù)器此時(shí)肯定不知道他的身份,,所以創(chuàng)建一個(gè)獨(dú)特的身份標(biāo)識數(shù)據(jù),格式為key=value,,放入到Set-Cookie字段里,隨著響應(yīng)報(bào)文發(fā)給瀏覽器,。

  • 瀏覽器看到有Set-Cookie字段以后就知道這是服務(wù)器給的身份標(biāo)識,,于是就保存起來,下次請求時(shí)會(huì)自動(dòng)將此key=value值放入到Cookie字段中發(fā)給服務(wù)端,。

  • 服務(wù)端收到請求報(bào)文后,,發(fā)現(xiàn)Cookie字段中有值,就能根據(jù)此值識別用戶的身份然后提供個(gè)性化的服務(wù),。

接下來我們用代碼演示一下服務(wù)器是如何生成,,我們自己搭建一個(gè)后臺(tái)服務(wù)器,這里我用的是SpringBoot搭建的,,并且寫入SpringMVC的代碼如下:


@RequestMapping("/testCookies")public String cookies(HttpServletResponse response){ response.addCookie(new Cookie("testUser","xxxx")); return "cookies";}

項(xiàng)目啟動(dòng)以后我們輸入路徑http://localhost:8005/testCookies,,然后查看發(fā)的請求??梢钥吹较旅婺菑垐D使我們首次訪問服務(wù)器時(shí)發(fā)送的請求,,可以看到服務(wù)器返回的響應(yīng)中有Set-Cookie字段。而里面的key=value值正是我們服務(wù)器中設(shè)置的值,。

接下來我們再次刷新這個(gè)頁面可以看到在請求體中已經(jīng)設(shè)置了Cookie字段,,并且將我們的值也帶過去了。這樣服務(wù)器就能夠根據(jù)Cookie中的值記住我們的信息了,。

接下來我們換一個(gè)請求呢,?是不是Cookie也會(huì)帶過去呢?接下來我們輸入路徑http://localhost:8005請求,。我們可以看到Cookie字段還是被帶過去了,。

那么瀏覽器的Cookie是存放在哪呢?如果是使用的是Chrome瀏覽器的話,,那么可以按照下面步驟,。

  • 在計(jì)算機(jī)打開Chrome

  • 在右上角,一次點(diǎn)擊更多圖標(biāo)->設(shè)置

  • 在底部,,點(diǎn)擊高級

  • 隱私設(shè)置和安全性下方,,點(diǎn)擊網(wǎng)站設(shè)置

  • 依次點(diǎn)擊Cookie->查看所有Cookie和網(wǎng)站數(shù)據(jù)

然后可以根據(jù)域名進(jìn)行搜索所管理的Cookie數(shù)據(jù)。所以是瀏覽器替你管理了Cookie的數(shù)據(jù),,如果此時(shí)你換成了Firefox等其他的瀏覽器,,因?yàn)?code style="box-sizing: border-box; outline: 0px; --tw-shadow:0 0 #0000 ; --tw-ring-inset:var(--tw-empty, ); --tw-ring-offset-width:0px; --tw-ring-offset-color:#fff; --tw-ring-color:rgba(66, 153, 225, 0.5); --tw-ring-offset-shadow:0 0 #0000; --tw-ring-shadow:0 0 #0000 ; border-radius: 4px; overflow-wrap: break-word;">Cookie剛才是存儲(chǔ)在Chrome里面的,所以服務(wù)器又蒙圈了,,不知道你是誰,,就會(huì)給Firefox再次貼上小紙條,。

Cookie中的參數(shù)設(shè)置

說到這里,應(yīng)該知道了Cookie就是服務(wù)器委托瀏覽器存儲(chǔ)在客戶端里的一些數(shù)據(jù),,而這些數(shù)據(jù)通常都會(huì)記錄用戶的關(guān)鍵識別信息,。

所以Cookie需要用一些其他的手段用來保護(hù),防止外泄或者竊取,,這些手段就是Cookie的屬性,。

參數(shù)名 作用 后端設(shè)置方法

Max-Age

設(shè)置cookie的過期時(shí)間,,單位為秒

cookie.setMaxAge(10)

Domain

指定了Cookie所屬的域名

cookie.setDomain("")

Path

指定了Cookie所屬的路徑

cookie.setPath("");

HttpOnly

告訴瀏覽器此Cookie只能靠瀏覽器Http協(xié)議傳輸,禁止其他方式訪問

cookie.setHttpOnly(true)

Secure

告訴瀏覽器此Cookie只能在Https安全協(xié)議中傳輸,如果是Http則禁止傳輸

cookie.setSecure(true)

下面我就簡單演示一下這幾個(gè)參數(shù)的用法及現(xiàn)象,。

Path

設(shè)置為cookie.setPath("/testCookies"),,接下來我們訪問http://localhost:8005/testCookies,,我們可以看到在左邊和我們指定的路徑是一樣的,,所以Cookie才在請求頭中出現(xiàn),接下來我們訪問http://localhost:8005,我們發(fā)現(xiàn)沒有Cookie字段了,這就是Path控制的路徑。

Domain

設(shè)置為cookie.setDomain("localhost"),,接下來我們訪問http://localhost:8005/testCookies我們發(fā)現(xiàn)下圖中左邊的是有Cookie的字段的,,但是我們訪問http://172.16.42.81:8005/testCookies,,看下圖的右邊可以看到?jīng)]有Cookie的字段了。這就是Domain控制的域名發(fā)送Cookie,。

接下來的幾個(gè)參數(shù)就不一一演示了,,相信到這里大家應(yīng)該對Cookie有一些了解了。

Session

- Cookie是存儲(chǔ)在客戶端方,,Session是存儲(chǔ)在服務(wù)端方,,客戶端只存儲(chǔ)SessionId

在上面我們了解了什么是Cookie,既然瀏覽器已經(jīng)通過Cookie實(shí)現(xiàn)了有狀態(tài)這一需求,,那么為什么又來了一個(gè)Session呢,?這里我們想象一下,如果將賬戶的一些信息都存入Cookie中的話,,一旦信息被攔截,,那么我們所有的賬戶信息都會(huì)丟失掉。所以就出現(xiàn)了Session,,在一次會(huì)話中將重要信息保存在Session中,,瀏覽器只記錄SessionId一個(gè)SessionId對應(yīng)一次會(huì)話請求。


@RequestMapping("/testSession")@ResponseBodypublic String testSession(HttpSession session){ session.setAttribute("testSession","this is my session"); return "testSession";}


@RequestMapping("/testGetSession")@ResponseBodypublic String testGetSession(HttpSession session){ Object testSession = session.getAttribute("testSession"); return String.valueOf(testSession);}


這里我們寫一個(gè)新的方法來測試Session是如何產(chǎn)生的,,我們在請求參數(shù)中加上HttpSession session,,然后再瀏覽器中輸入http://localhost:8005/testSession進(jìn)行訪問可以看到在服務(wù)器的返回頭中在Cookie中生成了一個(gè)SessionId。然后瀏覽器記住此SessionId下次訪問時(shí)可以帶著此Id,,然后就能根據(jù)此Id找到存儲(chǔ)在服務(wù)端的信息了,。

此時(shí)我們訪問路徑http://localhost:8005/testGetSession,發(fā)現(xiàn)得到了我們上面存儲(chǔ)在Session中的信息,。那么Session什么時(shí)候過期呢,?

  • 客戶端:和Cookie過期一致,如果沒設(shè)置,默認(rèn)是關(guān)了瀏覽器就沒了,,即再打開瀏覽器的時(shí)候初次請求頭中是沒有SessionId了,。

  • 服務(wù)端:服務(wù)端的過期是真的過期,即服務(wù)器端的Session存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu)多久不可用了,,默認(rèn)是30分鐘,。

既然我們知道了Session是在服務(wù)端進(jìn)行管理的,那么或許你們看到這有幾個(gè)疑問,,Session是在在哪創(chuàng)建的,?Session是存儲(chǔ)在什么數(shù)據(jù)結(jié)構(gòu)中?接下來帶領(lǐng)大家一起看一下Session是如何被管理的,。

Session的管理是在容器中被管理的,,什么是容器呢?Tomcat,、Jetty等都是容器,。接下來我們拿最常用的Tomcat為例來看下Tomcat是如何管理Session的。在ManageBasecreateSession是用來創(chuàng)建Session的,。


@Overridepublic Session createSession(String sessionId) { //首先判斷Session數(shù)量是不是到了最大值,,最大Session數(shù)可以通過參數(shù)設(shè)置 if ((maxActiveSessions >= 0) && (getActiveSessions() >= maxActiveSessions)) { rejectedSessions++; throw new TooManyActiveSessionsException( sm.getString("managerBase.createSession.ise"), maxActiveSessions); }


// 重用或者創(chuàng)建一個(gè)新的Session對象,請注意在Tomcat中就是StandardSession // 它是HttpSession的具體實(shí)現(xiàn)類,,而HttpSession是Servlet規(guī)范中定義的接口 Session session = createEmptySession();


// 初始化新Session的值 session.setNew(true); session.setValid(true); session.setCreationTime(System.currentTimeMillis()); // 設(shè)置Session過期時(shí)間是30分鐘 session.setMaxInactiveInterval(getContext().getSessionTimeout() * 60); String id = sessionId; if (id == null) { id = generateSessionId(); } session.setId(id);// 這里會(huì)將Session添加到ConcurrentHashMap中 sessionCounter++;


//將創(chuàng)建時(shí)間添加到LinkedList中,,并且把最先添加的時(shí)間移除 //主要還是方便清理過期Session SessionTiming timing = new SessionTiming(session.getCreationTime(), 0); synchronized (sessionCreationTiming) { sessionCreationTiming.add(timing); sessionCreationTiming.poll(); } return session}

到此我們明白了Session是如何創(chuàng)建出來的,創(chuàng)建出來后Session會(huì)被保存到一個(gè)ConcurrentHashMap中,。可以看StandardSession類,。


protected Map<string, session> www.jintianxuesha.com sessions = new ConcurrentHashMap&lt;&gt;();

到這里大家應(yīng)該對Session有簡單的了解了,。

Session是存儲(chǔ)在Tomcat的容器中,所以如果后端機(jī)器是多臺(tái)的話,,因此多個(gè)機(jī)器間是無法共享Session的,,此時(shí)可以使用Spring提供的分布式Session的解決方案,是將Session放在了Redis中,。

Token

Session是將要驗(yàn)證的信息存儲(chǔ)在服務(wù)端,,并以SessionId和數(shù)據(jù)進(jìn)行對應(yīng),SessionId由客戶端存儲(chǔ),,在請求時(shí)將SessionId也帶過去,,因此實(shí)現(xiàn)了狀態(tài)的對應(yīng)。而Token是在服務(wù)端將用戶信息經(jīng)過Base64Url編碼過后傳給在客戶端,,每次用戶請求的時(shí)候都會(huì)帶上這一段信息,,因此服務(wù)端拿到此信息進(jìn)行解密后就知道此用戶是誰了,這個(gè)方法叫做JWT(Json Web Token)。

Token相比較于Session的優(yōu)點(diǎn)在于,,當(dāng)后端系統(tǒng)有多臺(tái)時(shí),,由于是客戶端訪問時(shí)直接帶著數(shù)據(jù),因此無需做共享數(shù)據(jù)的操作,。

Token的優(yōu)點(diǎn)

  • 簡潔:可以通過URL,POST參數(shù)或者是在HTTP頭參數(shù)發(fā)送,,因?yàn)閿?shù)據(jù)量小,傳輸速度也很快

  • 自包含:由于串包含了用戶所需要的信息,,避免了多次查詢數(shù)據(jù)庫

  • 因?yàn)門oken是以Json的形式保存在客戶端的,,所以JWT是跨語言的

  • 不需要在服務(wù)端保存會(huì)話信息,特別適用于分布式微服務(wù)

JWT的結(jié)構(gòu)

實(shí)際的JWT大概長下面的這樣,,它是一個(gè)很長的字符串,,中間用.分割成三部分

JWT是有三部分組成的

Header

是一個(gè)Json對象,描述JWT的元數(shù)據(jù),,通常是下面這樣子的



{ "alg": "HS256", "typ": "JWT"}

上面代碼中,,alg屬性表示簽名的算法(algorithm),默認(rèn)是 HMAC SHA256(寫成 HS256),;typ屬性表示這個(gè)令牌(token)的類型(type),,JWT 令牌統(tǒng)一寫為JWT。最后,,將上面的 JSON 對象使用 Base64URL 算法轉(zhuǎn)成字符串,。

> JWT 作為一個(gè)令牌(token),有些場合可能會(huì)放到 URL(比如 api.example.com/?token=xxx),。Base64 有三個(gè)字符+,、/和=,在 URL 里面有特殊含義,,所以要被替換掉:=被省略,、+替換成-,/替換成_ ,。這就是 Base64URL 算法,。

Payload

Payload部分也是一個(gè)Json對象,用來存放實(shí)際需要傳輸?shù)臄?shù)據(jù),,JWT官方規(guī)定了下面幾個(gè)官方的字段供選用,。

  • iss (issuer):簽發(fā)人

  • exp (expiration time):過期時(shí)間

  • sub (subject):主題

  • aud (audience):受眾

  • nbf (Not Before):生效時(shí)間

  • iat (Issued At):簽發(fā)時(shí)間

  • jti (JWT ID):編號

當(dāng)然除了官方提供的這幾個(gè)字段我們也能夠自己定義私有字段,下面就是一個(gè)例子



{ "name": "xiaoMing", "age": 14}

默認(rèn)情況下JWT是不加密的,,任何人只要在網(wǎng)上進(jìn)行Base64解碼就可以讀到信息,,所以一般不要將秘密信息放在這個(gè)部分。這個(gè)Json對象也要用Base64URL 算法轉(zhuǎn)成字符串

Signature

Signature部分是對前面的兩部分的數(shù)據(jù)進(jìn)行簽名,,防止數(shù)據(jù)篡改,。

首先需要定義一個(gè)秘鑰,這個(gè)秘鑰只有服務(wù)器才知道,不能泄露給用戶,,然后使用Header中指定的簽名算法(默認(rèn)情況是HMAC SHA256),,算出簽名以后將Header、Payload,、Signature三部分拼成一個(gè)字符串,,每個(gè)部分用.分割開來,就可以返給用戶了,。

> HS256可以使用單個(gè)密鑰為給定的數(shù)據(jù)樣本創(chuàng)建簽名,。當(dāng)消息與簽名一起傳輸時(shí),接收方可以使用相同的密鑰來驗(yàn)證簽名是否與消息匹配,。

Java中如何使用Token

上面我們介紹了關(guān)于JWT的一些概念,,接下來如何使用呢?首先在項(xiàng)目中引入Jar包



compile('io.jsonwebtoken:jjwt:0.9.0')

然后編碼如下


// 簽名算法 ,,將對token進(jìn)行簽名 SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; // 通過秘鑰簽名JWT byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("SECRET"); Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); Map<String,Object> claimsMap = new HashMap<>(); claimsMap.put("name","xiaoMing"); claimsMap.put("age",14); JwtBuilder builderWithSercet = Jwts.builder()                  .setSubject("subject")          .setIssuer("issuer")          .addClaims(claimsMap)          .signWith(signatureAlgorithm, signingKey);System.out.printf(builderWithSercet.compact());

發(fā)現(xiàn)輸出的Token如下



eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJzdWJqZWN0IiwiaXNzIjoiaXNzdWVyIiwibmFtZSI6InhpYW9NaW5nIiwiYWdlIjoxNH0.3KOWQ-oYvBSzslW5vgB1D-JpCwS-HkWGyWdXCP5l3Ko

此時(shí)在網(wǎng)上隨便找個(gè)Base64解碼的網(wǎng)站就能將信息解碼出來

總結(jié)

相信大家看到這應(yīng)該對Cookie,、SessionToken有一定的了解了,,接下來再回顧一下重要的知識點(diǎn),。

  • Cookie是存儲(chǔ)在客戶端的

  • Session是存儲(chǔ)在服務(wù)端的,可以理解為一個(gè)狀態(tài)列表,。擁有一個(gè)唯一會(huì)話標(biāo)識SessionId,。可以根據(jù)SessionId在服務(wù)端查詢到存儲(chǔ)的信息,。

  • Session會(huì)引發(fā)一個(gè)問題,,即后端多臺(tái)機(jī)器時(shí)Session共享的問題,解決方案可以使用Spring提供的框架,。

  • Token類似一個(gè)令牌,,無狀態(tài)的,服務(wù)端所需的信息被Base64編碼后放到Token中,,服務(wù)器可以直接解碼出其中的數(shù)據(jù),。

Copyright © 2020-2022 南京傾心軟件技術(shù)有限公司 版權(quán)所有     蘇ICP備2020070309號-1
QQ在線咨詢
13605185909
返回頂部