詳解SpringBoot如何使用JWT實(shí)現(xiàn)身份認(rèn)證和授權(quán)
JSON Web Token(JWT)是一種用于在網(wǎng)絡(luò)應(yīng)用之間安全傳遞信息的開(kāi)放標(biāo)準(zhǔn)。它使用了一種緊湊且獨(dú)立于語(yǔ)言的方式在各方之間傳遞信息,通常用于在客戶(hù)端和服務(wù)器之間驗(yàn)證用戶(hù)身份和授權(quán)訪問(wèn)資源。本文將介紹如何在Spring Boot中使用JWT實(shí)現(xiàn)身份認(rèn)證和授權(quán)。
什么是JWT
JWT是一個(gè)輕量級(jí)的令牌(token)協(xié)議,它使用JSON對(duì)象作為負(fù)載(payload)來(lái)傳遞信息,并使用數(shù)字簽名(digital signature)來(lái)驗(yàn)證其真實(shí)性。JWT通常包括以下三個(gè)部分:
- Header(頭部):包含了令牌的類(lèi)型和使用的簽名算法。
- Payload(負(fù)載):包含了一些聲明(claims),例如用戶(hù)ID、過(guò)期時(shí)間等。
- Signature(簽名):用于驗(yàn)證令牌的真實(shí)性,確保它未被篡改。
JWT的主要優(yōu)勢(shì)在于它的輕量性、易于使用以及可擴(kuò)展性。它可以在不同的應(yīng)用程序之間安全傳遞信息,無(wú)需每次都訪問(wèn)數(shù)據(jù)庫(kù)或使用其他形式的驗(yàn)證。
Spring Boot 中使用JWT的步驟
要在Spring Boot應(yīng)用程序中使用JWT,需要執(zhí)行以下步驟:
步驟1:添加依賴(lài)項(xiàng)
首先,您需要在pom.xml文件中添加以下依賴(lài)項(xiàng)以使用JWT庫(kù):
<dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-api</artifactId> <version>0.11.2</version> </dependency> <dependency> <groupId>io.jsonwebtoken</groupId> <artifactId>jjwt-impl</artifactId> <version>0.11.2</version> </dependency>
步驟2:創(chuàng)建JWT工具類(lèi)
接下來(lái),您需要?jiǎng)?chuàng)建一個(gè)JWT工具類(lèi),用于生成和驗(yàn)證JWT令牌。以下是一個(gè)示例的JWT工具類(lèi):
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springframework.stereotype.Component; import java.util.Date; import java.util.HashMap; import java.util.Map; @Component public class JwtUtils { private final String secret = "your_secret_key"; private final long expirationTime = 86400000; // 1 day in milliseconds // 生成JWT令牌 public String generateToken(String username) { Date now = new Date(); Date expirationDate = new Date(now.getTime() + expirationTime); Map<String, Object> claims = new HashMap<>(); claims.put("sub", username); return Jwts.builder() .setClaims(claims) .setIssuedAt(now) .setExpiration(expirationDate) .signWith(SignatureAlgorithm.HS512, secret) .compact(); } // 從JWT令牌中提取用戶(hù)名 public String extractUsername(String token) { Claims claims = Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) .getBody(); return claims.getSubject(); } // 驗(yàn)證JWT令牌 public boolean validateToken(String token) { try { Jwts.parser().setSigningKey(secret).parseClaimsJws(token); return true; } catch (Exception e) { return false; } } }
在上述代碼中,JwtUtils類(lèi)負(fù)責(zé)生成、解析和驗(yàn)證JWT令牌。
步驟3:創(chuàng)建身份認(rèn)證和授權(quán)邏輯
您需要?jiǎng)?chuàng)建身份認(rèn)證和授權(quán)邏輯以確保只有合法用戶(hù)可以訪問(wèn)受保護(hù)的資源??梢允褂肧pring Security等安全框架來(lái)實(shí)現(xiàn)這些功能。以下是一個(gè)示例的Spring Security配置類(lèi),用于使用JWT進(jìn)行身份認(rèn)證和授權(quán):
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { private final JwtRequestFilter jwtRequestFilter; private final UserDetailsService userDetailsService; public SecurityConfig(JwtRequestFilter jwtRequestFilter, UserDetailsService userDetailsService) { this.jwtRequestFilter = jwtRequestFilter; this.userDetailsService = userDetailsService; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/authenticate").permitAll() // 放行認(rèn)證接口 .anyRequest().authenticated() // 所有其他請(qǐng)求需要認(rèn)證 .and() .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class); } }
在上述代碼中,SecurityConfig
類(lèi)配置了哪些端點(diǎn)需要進(jìn)行身份認(rèn)證,以及如何使用JWT進(jìn)行認(rèn)證。
步驟4:創(chuàng)建認(rèn)證控制器
創(chuàng)建一個(gè)認(rèn)證控制器,它負(fù)責(zé)生成JWT令牌并將其返回給客戶(hù)端。以下是一個(gè)示例的認(rèn)證控制器:
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.web.bind.annotation.*; @RestController public class AuthController { private final AuthenticationManager authenticationManager; private final JwtUtils jwtUtils; private final UserDetailsService userDetailsService; @Autowired public AuthController(AuthenticationManager authenticationManager, JwtUtils jwtUtils, UserDetailsService userDetailsService) { this.authenticationManager = authenticationManager; this.jwtUtils = jwtUtils; this.userDetailsService = userDetailsService; } @PostMapping("/authenticate") public ResponseEntity<?> createAuthenticationToken(@RequestBody AuthRequest authenticationRequest) throws Exception { authenticate(authenticationRequest.getUsername(), authenticationRequest.getPassword()); final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername()); final String jwt = jwtUtils.generateToken(userDetails.getUsername()); return ResponseEntity.ok(new AuthResponse(jwt)); } private void authenticate(String username, String password) throws Exception { try { authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, password)); } catch (Exception e) { throw new Exception("Invalid username or password"); } } }
在上述代碼中,AuthController
類(lèi)包含了生成JWT令牌的邏輯。
步驟5:創(chuàng)建受保護(hù)的資源和授權(quán)邏輯
最后,您可以創(chuàng)建受保護(hù)的資源和相應(yīng)的授權(quán)邏輯。在Spring Security配置中,您可以使用@PreAuthorize
注解來(lái)限制訪問(wèn)資源的權(quán)限。以下是一個(gè)示例:
@RestController public class ResourceController { @GetMapping("/hello") @PreAuthorize("hasRole('USER')") public String helloUser() { return "Hello, User!"; } @GetMapping("/admin") @PreAuthorize("hasRole('ADMIN')") public String helloAdmin() { return "Hello, Admin!"; } }
在上述代碼中,@PreAuthorize注解確保只有具有相應(yīng)角色的用戶(hù)可以訪問(wèn)/hello和/admin端點(diǎn)。
測(cè)試JWT認(rèn)證和授權(quán)
現(xiàn)在,您可以測(cè)試JWT認(rèn)證和授權(quán)功能。首先,您可以使用/authenticate端點(diǎn)來(lái)獲取JWT令牌,然后將該令牌包含在請(qǐng)求的Authorization頭中,以訪問(wèn)受保護(hù)的資源。如果令牌有效并且用戶(hù)具有所需的權(quán)限,將允許訪問(wèn)資源。
結(jié)論
JWT是一種強(qiáng)大的工具,可用于實(shí)現(xiàn)身份認(rèn)證和授權(quán)功能。在Spring Boot中使用JWT可以簡(jiǎn)化安全性的實(shí)現(xiàn),使您能夠輕松地保護(hù)應(yīng)用程序的資源。通過(guò)遵循本文中的步驟,您可以在Spring Boot應(yīng)用程序中成功使用JWT。
到此這篇關(guān)于詳解SpringBoot如何使用JWT實(shí)現(xiàn)身份認(rèn)證和授權(quán)的文章就介紹到這了,更多相關(guān)SpringBoot JWT身份認(rèn)證內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 詳解Spring Boot實(shí)戰(zhàn)之Filter實(shí)現(xiàn)使用JWT進(jìn)行接口認(rèn)證
- Vue+Jwt+SpringBoot+Ldap完成登錄認(rèn)證的示例代碼
- Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的步驟詳解
- SpringBoot整合SpringSecurity和JWT和Redis實(shí)現(xiàn)統(tǒng)一鑒權(quán)認(rèn)證
- SpringBoot使用Jwt處理跨域認(rèn)證問(wèn)題的教程詳解
- 利用Springboot實(shí)現(xiàn)Jwt認(rèn)證的示例代碼
- springboot+jwt實(shí)現(xiàn)token登陸權(quán)限認(rèn)證的實(shí)現(xiàn)
- SpringBoot整合SpringSecurity實(shí)現(xiàn)JWT認(rèn)證的項(xiàng)目實(shí)踐
- Spring Boot整合JWT實(shí)現(xiàn)認(rèn)證與授權(quán)的項(xiàng)目實(shí)踐
相關(guān)文章
Spring Boot利用@Async如何實(shí)現(xiàn)異步調(diào)用:自定義線程池
這篇文章主要給大家介紹了關(guān)于Spring Boot利用@Async如何實(shí)現(xiàn)異步調(diào)用:自定義線程池的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2018-05-05java int類(lèi)型二維數(shù)組實(shí)現(xiàn)“楊輝三角”的完整實(shí)例
這篇文章主要給大家介紹了關(guān)于java int類(lèi)型二維數(shù)組實(shí)現(xiàn)“楊輝三角”的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12Springboot+AOP實(shí)現(xiàn)返回?cái)?shù)據(jù)提示語(yǔ)國(guó)際化的示例代碼
這篇文章主要介紹了Springboot+AOP實(shí)現(xiàn)返回?cái)?shù)據(jù)提示語(yǔ)國(guó)際化的示例代碼,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07java實(shí)現(xiàn)多線程之定時(shí)器任務(wù)
本篇文章主要介紹了java實(shí)現(xiàn)多線程之定時(shí)器任務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-02-02Layui 后臺(tái)加載菜單欄名稱(chēng)以及url的例子
今天小編就為大家分享一篇Layui 后臺(tái)加載菜單欄名稱(chēng)以及url的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09