国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Web應(yīng)用程序的身份驗(yàn)證:Session認(rèn)證、Token認(rèn)證

這篇具有很好參考價(jià)值的文章主要介紹了Web應(yīng)用程序的身份驗(yàn)證:Session認(rèn)證、Token認(rèn)證。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一、Web應(yīng)用程序的身份驗(yàn)證

1、Session認(rèn)證

① 用戶向服務(wù)器發(fā)送用戶名和密碼

② 服務(wù)器驗(yàn)證通過后,在當(dāng)前對話(session)里面保存相關(guān)數(shù)據(jù),如用戶角色,登陸時(shí)間等

③ 服務(wù)器向用戶返回一個(gè)session_id,寫入用戶的Cookie

④ 用戶隨后的每一次請求,都會通過Cookie,將session_id傳回服務(wù)器

⑤ 服務(wù)器收到session_id,找到前期保存的數(shù)據(jù),由此得知用戶的身份

認(rèn)證流程:

Web應(yīng)用程序的身份驗(yàn)證:Session認(rèn)證、Token認(rèn)證

?

????????Session認(rèn)證的方式擴(kuò)展性不好,如果是服務(wù)器集群,或者是跨域的服務(wù)導(dǎo)向架構(gòu),就要求session數(shù)據(jù)共享,以便每臺服務(wù)器都能夠讀取session,針對這問題有兩種解決方案:

????????① session數(shù)據(jù)持久化,寫入數(shù)據(jù)庫或別的持久層。優(yōu)點(diǎn)是架構(gòu)清晰,但工程量大

????????② 服務(wù)器不再保存session數(shù)據(jù),所有數(shù)據(jù)都保存在客戶端,每次請求都發(fā)回服務(wù)器。Token就是其中一個(gè)代表

2、Token認(rèn)證

Token是在服務(wù)端產(chǎn)生的一串字符串,是客戶端訪問資源接口(API)時(shí)所需要的資源憑證

????????① 客戶端使用用戶名和密碼請求登陸,服務(wù)端收到請求,去驗(yàn)證用戶名和密碼

????????② 驗(yàn)證成功后,服務(wù)端會簽發(fā)一個(gè)token并把這個(gè)token發(fā)送給客戶端

????????③ 客戶端收到token后,存儲起來,比如放在cookie或者localStorage里頭

????????④ 客戶端每次向服務(wù)端請求資源時(shí)需要帶上這個(gè)token

????????⑤ 服務(wù)端收到請求后去驗(yàn)證這個(gè)token,成功則返回請求數(shù)據(jù)

Web應(yīng)用程序的身份驗(yàn)證:Session認(rèn)證、Token認(rèn)證

?

實(shí)現(xiàn)方式:JWT(JSON Web Token)認(rèn)證

原理:

① 用戶發(fā)送用戶名和密碼后,服務(wù)器認(rèn)證并生成JWT令牌(JSON對象),將其發(fā)回給客戶端

?(為了防止用戶篡改數(shù)據(jù),服務(wù)器在生成這個(gè)對象的時(shí)候會加上簽名)

② 客戶端將JWT令牌存儲在本地以便后續(xù)使用

③ 當(dāng)客戶端向另一個(gè)域名服務(wù)器發(fā)送請求時(shí),將JWT令牌作為請求頭(放在Authorization字段里頭)或請求參數(shù)發(fā)送

④ 服務(wù)器收到請求后,檢查JWT令牌的有效性,并進(jìn)行身份驗(yàn)證和授權(quán)

⑤ 若令牌有效則返回請求的數(shù)據(jù),否則返回未授權(quán)的錯(cuò)誤信息

JWT由三個(gè)部分組成:

1、Header(頭部):

{
 ?"alg": "HS256", // 令牌類型
 ?"typ": "JWT" //加密算法 
}

2、Payload(負(fù)載):

{
  "iss": "example.com",
  "sub": "1234567890",
  "aud": ["foo", "bar"],
  "exp": 1648696800,
  "nbf": 1648693200, // 2022年4月29日10:20:00
  "iat": 1648694700,
  "jti": "abcdef123456"
}
// 1、iss(issuer): 表示JWT簽發(fā)者的名稱,通常是一個(gè)字符串或URL。
// 2、sub(subject): 表示JWT的主題,即客戶端的唯一標(biāo)識符,通常是一個(gè)用戶ID。
// 3、aud(audience): 表示JWT的預(yù)期接收者,即對該JWT有效的接收方,可以是單個(gè)字符串或一個(gè)字符串?dāng)?shù)組。
// 4、exp(expiration time): 表示JWT的過期時(shí)間,用Unix時(shí)間戳表示。
// 5、nbf(not before): 表示JWT的生效時(shí)間,用Unix時(shí)間戳表示。
// 6、iat(issued at): 表示JWT的簽發(fā)時(shí)間,用Unix時(shí)間戳表示。
// 7、jti(JWT ID): 表示JWT的唯一標(biāo)識符,通常用于避免重放攻擊。

3、Signature(簽名):由Header、Payload和一個(gè)密鑰(secret,存儲在服務(wù)器端,對外不可見)進(jìn)行簽名生成。

HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  secret)

將Header、Payload和Signature通過'.'連接在一起形成JWT令牌,例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

代碼實(shí)現(xiàn):

① 引入依賴

<dependency>
 ? ?<groupId>io.jsonwebtoken</groupId>
 ? ?<artifactId>jjwt</artifactId>
 ? ?<version>0.9.1</version>
</dependency>

② 添加JWT配置

# JWT相關(guān)配置
jwt.secret=your-secret
jwt.expiration=3600

③ 創(chuàng)建JWT工具類:用于生成和解析JWT

@Component
public class JwtUtils {
?
 ? ?// 秘鑰
 ? ?@Value("${jwt.secret}")
 ? ?private String secret;
?
 ? ?// 過期時(shí)間,單位秒
 ? ?@Value("${jwt.expiration}")
 ? ?private Long expiration;
?
 ? ?// 生成JWT
 ? ?public String generateToken(Long userId) {
 ? ? ? ?SecretKey key = Keys.hmacShaKeyFor(secret.getBytes()); // 創(chuàng)建密鑰
 ? ? ? ?Date now = new Date();
 ? ? ? ?Date expireTime = new Date(now.getTime() + expiration * 1000);
 ? ? ? ?return Jwts.builder()
 ? ? ? ? ?      .setIssuer("issuer") // 設(shè)置JWT的簽發(fā)者
 ? ? ? ? ?      .setAudience("audience") // 設(shè)置JWT的接收方
 ? ? ? ? ?      .setSubject(userId.toString()) // 設(shè)置JWT的主題
 ? ? ? ? ?      .setIssuedAt(now) // 設(shè)置JWT的簽發(fā)時(shí)間
 ? ? ? ? ?      .setExpiration(expireTime) // 設(shè)置JWT的過期時(shí)間
 ? ? ? ? ?      .signWith(key, SignatureAlgorithm.HS256) // 用HS256算法和密鑰key簽名JWT
 ? ? ? ? ?      .compact(); // 生成JWT字符串
 ?  }
?
 ? ?// 解析JWT
 ? ?public Claims parseToken(String token) {
 ? ? ? ?SecretKey key = Keys.hmacShaKeyFor(secret.getBytes()); // 創(chuàng)建密鑰
 ? ? ? ?return Jwts.parserBuilder()
 ? ? ? ? ? ? ?  .setSigningKey(key) // 設(shè)置用于解析JWT的密鑰
 ? ? ? ? ? ? ?  .build()
 ? ? ? ? ? ? ?  .parseClaimsJws(token) // 解析JWT,獲取Jws<Claims>實(shí)例
 ? ? ? ? ? ? ?  .getBody();
 ?  }
}
 

④ 配置攔截器:用于驗(yàn)證請求中的JWT是否有效

@Component
public class JwtInterceptor implements HandlerInterceptor {
?
 ? ?@Autowired
 ? ?private JwtUtils jwtUtils;
?
 ? ?@Override
 ? ?public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
 ? ? ? ?// 從請求頭中獲取token
 ? ? ? ?String token = request.getHeader("Authorization");
 ? ? ? ?// 判斷token是否存在并以Bearer開頭
 ? ? ? ?if (token != null && token.startsWith("Bearer ")) { 
 ? ? ? ? ? ?token = token.substring(7); // 去掉token前綴
 ? ? ? ? ? ?Claims claims = jwtUtils.parseToken(token); // 解析JWT
 ? ? ? ? ? ?if (claims != null) {
 ? ? ? ? ? ? ? ?Long userId = Long.valueOf(claims.getSubject()); // 獲取JWT中的用戶id
 ? ? ? ? ? ? ? ?// 將用戶信息存儲到request中,方便后續(xù)操作
 ? ? ? ? ? ? ? ?request.setAttribute("userId", userId);
 ? ? ? ? ? ? ? ?return true;
 ? ? ? ? ?  }
 ? ? ?  }
 ? ? ? ?// 解析失敗,返回401未授權(quán)狀態(tài)碼
 ? ? ? ?response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
 ? ? ? ?return false; // 攔截請求
 ?  }
}
?

⑤ 使用JWT

@RestController
@RequestMapping("/api")
public class UserController {
 ? ?
 ? ?@Autowired
 ? ?private UserService userService;
 ? ?
    @PostMapping("/login")
    public ResponseEntity<?> login(@RequestBody UserLoginDto userLoginDto) {
 ?      // 用戶登錄邏輯
 ? ?
 ?      // 生成 JWT token
     ? String token = Jwts.builder()
 ? ? ? ? ?  .setSubject(user.getUsername()) // 主題
 ? ? ? ? ?  .claim("roles", user.getRoles()) 
 ? ? ? ? ?  .setIssuedAt(new Date()) // 簽發(fā)時(shí)間
 ? ? ? ? ?  .setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME)) // 過期時(shí)間
 ? ? ? ? ?  .signWith(SignatureAlgorithm.HS512, SECRET_KEY) // 使用算法和密鑰對token進(jìn)行簽名。
 ? ? ? ? ?  .compact(); // 將JWT token生成為字符串
 ? ?
     ? // 返回 token 給客戶端
     ? return ResponseEntity.ok(new AuthResponse(token));
    }
?
 ? ?
    @GetMapping("/users")
    @PreAuthorize("hasAuthority('ROLE_ADMIN')") // 擁有 ROLE_ADMIN 權(quán)限的用戶才能訪問該方法
    public ResponseEntity<?> getUsers(@RequestHeader("Authorization") String    authorizationHeader) {
 ? ? ? ?String token = authorizationHeader.substring(7); // 去掉 "Bearer" 前綴
 ? ?
 ? ? ? ?// 驗(yàn)證 token 是否有效
 ? ? ? ?Claims claims = Jwts.parser() // 獲取一個(gè)JwtParser對象
 ? ? ?       ?  .setSigningKey(SECRET_KEY) // 設(shè)置JWT的簽名密鑰,用于校驗(yàn)JWT的合法性
 ? ? ?       ?  .parseClaimsJws(token) // 將其轉(zhuǎn)化為Jws對象
 ? ? ? ?     ? .getBody(); // 獲取Jws對象中的payload信息
 ? ?
 ?   ? ?// 獲取用戶列表邏輯
}
?
 ? ?
 ? ?@GetMapping("/users/{id}")
 ? ?public ResponseEntity<?> getUserById(@PathVariable Long id) {
 ? ? ? ?// 根據(jù)用戶ID獲取用戶信息邏輯
 ?  }
 ? ?
 ? ?// 省略其他接口...
}
 

Session和Token認(rèn)證的區(qū)別:

????????Session和Token都是常用的用戶認(rèn)證方式,它們的作用都是為了驗(yàn)證用戶身份和授權(quán)訪問資源,但是它們的實(shí)現(xiàn)方式有所不同。

????????Session是一種服務(wù)器端認(rèn)證方式,通常通過在服務(wù)器端保存用戶的登錄信息(較安全),以便在后續(xù)的請求中進(jìn)行驗(yàn)證。當(dāng)用戶進(jìn)行登錄操作時(shí),服務(wù)器會創(chuàng)建一個(gè)Session,并給這個(gè)Session分配一個(gè)唯一的標(biāo)識符(Session ID),然后將這個(gè)Session ID發(fā)送給客戶端保存??蛻舳嗽诤罄m(xù)的請求中需要攜帶這個(gè)Session ID,服務(wù)器端根據(jù)這個(gè)Session ID來查找對應(yīng)的Session,從而驗(yàn)證用戶的身份。

????????Token是一種無狀態(tài)認(rèn)證方式,通常通過在客戶端保存用戶的登錄信息(不安全),以便在后續(xù)的請求中進(jìn)行驗(yàn)證。當(dāng)用戶進(jìn)行登錄操作時(shí),服務(wù)器會生成一個(gè)Token,并將這個(gè)Token發(fā)送給客戶端保存。客戶端在后續(xù)的請求中需要攜帶這個(gè)Token,服務(wù)器端通過驗(yàn)證這個(gè)Token來確定用戶的身份。

優(yōu)缺點(diǎn):

????????Session需要在服務(wù)器端保存用戶的登錄信息,因此需要占用服務(wù)器的資源,并且需要在分布式系統(tǒng)中進(jìn)行Session共享和Session失效管理(工程量大)。

????????Token是無狀態(tài)的,不需要在服務(wù)器端保存用戶的登錄信息,因此具有良好的可擴(kuò)展性,并且可以很方便地實(shí)現(xiàn)分布式系統(tǒng)中的認(rèn)證和授權(quán)。用解析token的計(jì)算時(shí)間換取session的存儲空間,從而減輕服務(wù)器壓力,減少頻繁查詢數(shù)據(jù)庫

????????Session的安全性比較高,因?yàn)镾ession的內(nèi)容保存在服務(wù)器端,客戶端無法直接修改Session的內(nèi)容

????????Token的安全性相對較低,因?yàn)門oken的內(nèi)容保存在客戶端,客戶端可以通過一些手段來篡改Token的內(nèi)容。

Session和Token的應(yīng)用場景:

????????一般來說,使用 session 可能更適合傳統(tǒng)的 Web 應(yīng)用,因?yàn)樗ǔP枰脩粼跒g覽器中持續(xù)地與應(yīng)用交互,而且涉及到敏感數(shù)據(jù)的處理。例如,在電子商務(wù)網(wǎng)站中,用戶需要登錄才能訪問個(gè)人購物車和訂單等敏感信息,此時(shí)可以使用 session 來驗(yàn)證用戶身份,并在服務(wù)器端存儲相關(guān)的用戶信息和狀態(tài)。

????????而在 API (應(yīng)用程序編程接口)設(shè)計(jì)和單頁面應(yīng)用中,使用 token 可能更加常見。由于 API 和單頁面應(yīng)用的特性,客戶端可以直接與 API 或后端服務(wù)通信,而不需要經(jīng)過瀏覽器的中間層。此時(shí),使用 token 可以避免一些 session 的問題,如跨域和服務(wù)器負(fù)載均衡等。同時(shí),token 也更容易在不同服務(wù)之間進(jìn)行傳遞和共享,比如使用 OAuth2 等協(xié)議來實(shí)現(xiàn)單點(diǎn)登錄和授權(quán)等功能。文章來源地址http://www.zghlxwxcb.cn/news/detail-437255.html

到了這里,關(guān)于Web應(yīng)用程序的身份驗(yàn)證:Session認(rèn)證、Token認(rèn)證的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包