<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Session跨域及單點(diǎn)登錄解決方案

          共 7954字,需瀏覽 16分鐘

           ·

          2021-06-01 23:44

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達(dá)

          cookie機(jī)制

          關(guān)于cookie和seesion的聯(lián)系

          cookie中會包含那些信息

          名字,值,過期時間,路徑,域

          cookie會帶到http請求頭中發(fā)送給服務(wù)端

          如果cookie沒有設(shè)置過期時間的話,那么cookie的默認(rèn)生命周期是瀏覽器的會話

           

          session機(jī)制

          1,session是容器對象,客戶端在請求服務(wù)端的時候,服務(wù)端會根據(jù)客戶端的請求判斷是否包含了jsessionId的標(biāo)識

          2,如果已經(jīng)包含了,說明客戶端之前已經(jīng)創(chuàng)建了會話。sessionId是一個唯一的值

          3,如果sessionid不存在,那么服務(wù)端為這個客戶端生成一個sessionid. JESSIONID

           

          session       cookie 存儲的是JSESSIONID  

          session存儲在服務(wù)器端  cookie存儲在瀏覽器端

          服務(wù)器端(Tomcat) 會生成一個唯一的sessionId號存儲在cookie中 叫 jessionid

          在服務(wù)器端(tomcat)中存儲serssion 使用concurrentMap (ConcurrentMap   key JSESSIONID  values session)

          瀏覽器端下次請求服務(wù)器端是將jsessionId帶過來 找到對應(yīng)的session 獲取session中存儲的信息(用戶信息)

          客戶端瀏 覽器禁用了cookie怎么辦?

          [如果客戶端瀏 覽器禁用了cookie,一般會通過URL重寫的方式來進(jìn)行會 話會話嗯個總,也就是在url中攜帶sessionid] 

           

          解決session跨域共享問題

          1.  session sticky  :會話保存在單機(jī)上  保證會話請求落在同一臺服務(wù)器上

              采用源地址哈希法進(jìn)行負(fù)載均衡,同一IP地址的客戶端,當(dāng)后端服務(wù)器列 表不變時,它每次都會映射到同一臺后端服務(wù)器進(jìn)行訪問

          根據(jù)獲取客戶端的IP地址,通過哈希函數(shù)計算得到的一個 數(shù)值,用該數(shù)值對服務(wù)器列表的大小進(jìn)行取模運(yùn)算,得到的結(jié)果便是客服端要訪問服務(wù)器的序號。采用源地址哈希 法進(jìn)行負(fù)載均衡,同一IP地址的客戶端,當(dāng)后端服務(wù)器列表不變時,它每次都會映射到同一臺后端服務(wù)器進(jìn)行訪問

          這種實(shí)現(xiàn)方式會有些問題: 如果一臺web服務(wù)器宕機(jī)或者重啟,那么這臺機(jī)器上保 存的會話數(shù)據(jù)都會丟失,會造成用戶暫時無法訪問的問 題,或者用戶之前的授權(quán)操作需要再執(zhí)行一次 

          2. session replication:session 復(fù)制  每一臺服務(wù)器上都保持一份相同的session (造成額外的存儲開銷和網(wǎng)絡(luò)開銷)

          session復(fù)制,通過相關(guān)技術(shù)實(shí)現(xiàn)session復(fù)制,使得集群 中的各個服務(wù)器相互保存各自節(jié)點(diǎn)存儲的 session 數(shù)據(jù)。tomcat本身就可以實(shí)現(xiàn)session復(fù)制的功能,基于IP組播 放方式。

          這種實(shí)現(xiàn)方式的問題:

          1. 同步session數(shù)據(jù)會造成網(wǎng)絡(luò)開銷,隨著集群規(guī)模越大, 同步session帶來的帶寬影響也越大

          2. 每個節(jié)點(diǎn)需要保存集群中所有節(jié)點(diǎn)的 session 數(shù)據(jù),就 需要比較大的內(nèi)存來存儲。

          3. session 集中存儲  :存儲在db、 存儲在緩存服務(wù)器 (redis)

              使用 spring-session -data-redis

              http://www.glmapper.com/

          4. 基于cookie (主流)

          a)

          access_token(userid/token/timestamp(過期時間)   加密)  

          將access_token存儲在客戶端的cookie中 每次 客戶端過來訪問 服務(wù)器端攔截其中 獲取cookie中的access_token 根據(jù) userid和timestamp(過期時間) 判斷是否有效

          b)基于JWT的解決方案

          json web Token  客戶端和服務(wù)端信息安全傳遞,身份認(rèn)證的一種解決方案。用在登陸上

          jwt由三個組成:header,payload 載荷,signature

          header{

          typ:"jwt" //類型

          alg:"HS256" //加密算法

          zip: "gzip/deflate"  //壓縮算法   加密之后的字符串 比較長的時候 可以使用壓縮算法

          }

          payload  :jwt本身規(guī)范提供的格式 claims

          iss:“簽發(fā)者”

          iat:“簽發(fā)時間”

          exp:“過期時間”

          sub:

          可以自己定一些claims,放入自定義的信息如 uid 等

          signature:將 header+ payload 組合成為一個字符串

          Base64(header).Base64(payload)  +  head中定義的算法 +密鑰  生成一個字符串    str.簽名字符串  就是 JWT的token

           

          <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
                  <dependency>
                      <groupId>com.auth0</groupId>
                      <artifactId>java-jwt</artifactId>
                      <version>3.3.0</version>
                  </dependency>
           
           
                  <!-- https://mvnrepository.com/artifact/joda-time/joda-time -->
                  <dependency>
                      <groupId>joda-time</groupId>
                      <artifactId>joda-time</artifactId>
                      <version>2.9.9</version>
                  </dependency>

           
          /**
           * @Auther: tengxiao
           * @Date: 2018/9/13 16:47
           * @Description:
           */
          public class JWTTokenUtil {
           
              private static final String JWT_KEY_USER_ID="JWT_KEY_USER_ID";
              private static final int EXPIRED_TIME=6000;
              private static final String SECRET_KEY="tengvincent_user";
           
              public static String generatorToken(Long userId)throws Exception{
                  //header Map
                  Map<String,Object> headerMap=new HashMap<>();
                  headerMap.put("typ","JWT");
                  headerMap.put("alg","HS256");
           
                  String token=JWT.create()
                          .withHeader(headerMap)
                          .withClaim("iss","Service")//簽發(fā)者
                          .withClaim("aud","APP")
                          .withClaim(JWT_KEY_USER_ID,userId)
                          .withIssuedAt(DateTime.now().toDate())//sign time
                          .withExpiresAt(DateTime.now().plusMinutes(EXPIRED_TIME).toDate())//expired time
                          .sign(Algorithm.HMAC256(SECRET_KEY));
           
                  return token;
              }
           
              public static Map<String,Claim> varifyToken(String token){
                  DecodedJWT jwt=null;
                  try{
                   JWTVerifier verifer= JWT.require(Algorithm.HMAC256(SECRET_KEY)).build();
                   jwt=verifer.verify(token);
                  }catch (Exception e){
                      // e.printStackTrace();
                      // token 校驗(yàn)失敗, 拋出Token驗(yàn)證非法異常
                  }
                  return jwt.getClaims();
              }
           
           
              public static Long getTokenInfo(String token){
                  Map<String, Claim> claims = varifyToken(token);
                  Claim user_id_claim = claims.get("user_id");
                  if (null == user_id_claim || StringUtils.isEmpty(user_id_claim.asString())) {
                      // token 校驗(yàn)失敗, 拋出Token驗(yàn)證非法異常
                  }
                  return Long.valueOf(user_id_claim.asString());
              }
           
          }

          1.token+redis與jwt的區(qū)別

              (1)簡單的說,token只是一個標(biāo)識,以token加redis為例,服務(wù)端將token保存在redis中,客服端訪問時帶上token,如果在redis中能夠查到這個token,說明身份有效。

              (2)jwt不需要查庫,本身已經(jīng)包含了用戶的相關(guān)信息,可以直接通過服務(wù)端解析出相關(guān)的信息,與session,token的最大區(qū)別就是服務(wù)端不保存任何信息(服務(wù)端只需要保存密鑰key)。

          2.如何實(shí)現(xiàn)jwt續(xù)期

          在jwt中保存過期時間,解析時進(jìn)行判定,如果即將超時則重新設(shè)置過期時間返回一個新的jwt給客戶端。

          3.jwt登出失效

          登出時將相關(guān)的信息比如用戶名存儲在redis中,并設(shè)置過期時間。當(dāng)再次訪問時,從jwt中解析出用戶名去redis中查找,如果存在則表示此jwt已登出失效。這里需要注意的是,如果用此方法,則驗(yàn)證jwt是否登出應(yīng)該放在第一位。思考一個場景,如果redis中存儲的是用戶名,那么當(dāng)用戶登出后,redis中已經(jīng)有了相應(yīng)的用戶名,當(dāng)用戶再次登錄時,解析jwt發(fā)現(xiàn)此用戶已登出,則jwt失效,所以在登錄時要清空相關(guān)的登出緩存。



          版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接和本聲明。

          本文鏈接:

          https://blog.csdn.net/tengxvincent/article/details/82685042







          瀏覽 109
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码在线观看一区二区三区 | 一级在线免费视频 | 黄色视频网站免费在线观看 | 欧美成人在线三级免费 | www国产成人免费观看视频 |