這期內容當中小編將會給大家?guī)碛嘘PJWT怎么用,文章內容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
創(chuàng)新互聯(lián)建站自2013年起,是專業(yè)互聯(lián)網(wǎng)技術服務公司,擁有項目網(wǎng)站建設、網(wǎng)站設計網(wǎng)站策劃,項目實施與項目整合能力。我們以讓每一個夢想脫穎而出為使命,1280元淄博做網(wǎng)站,已為上家服務,為淄博各地企業(yè)和個人服務,聯(lián)系電話:13518219792
JWT簡稱JSON Web Token,通過JSON形式作為Web應用中的令牌,將信息作為JSON對象在各方之間安全傳輸,在數(shù)據(jù)傳輸過程中還可以完成數(shù)據(jù)加密、簽名等相關處理。
JWT的最常見方案,一旦用戶登錄,每個后續(xù)請求將包括JWT,從而允許訪問系統(tǒng)的資源,一般適用于單點登錄系統(tǒng),因為開銷很小并且可以在不同的域中輕松使用。
JWT是在各方之間安全地傳輸信息的好方法,因為可以對JWT進行簽名,例如使用公鑰或者私鑰對,由于簽名是使用標頭和有效負載計算的,還可以驗證內容是否遭到篡改。
JWT跟Session不一樣,JWT存儲在客戶端,Session存儲在服務器端,服務器斷電后Session就會被銷毀,而JWT因為存儲在客戶端,所以就不會被影響,只要JWT不過期,就可以繼續(xù)使用。

Session都是保存在內存中,而隨著認證用戶的增多,服務端的開銷會明顯增大。
用戶認證之后,服務端做認證記錄,如果認證的記錄被保存在內存中的話,這意味著用戶下次請求還必須要請求在這臺服務器上,這樣才能拿到授權的資源,在分布式系統(tǒng)中,限制了負載均衡器的能力,也限制了應用的擴展能力。
CSRF跨站偽造請求攻擊攻擊,Session是基于Cookie進行用戶識別的,如果Cookie被截獲,用戶會很容易受到跨站請求偽造的攻擊。
Sessionid就是一個特征值,表達的信息不夠豐富,不容易擴展,而且如果后端應用是多節(jié)點部署,需要實現(xiàn)session共享機制,不方便集群應用。

前端通過Web表單將自己的用戶名和密碼發(fā)送到后端的接口,一般是為http post請求,盡量通過SSL加密的傳輸,避免泄漏敏感信息。
后端核對用戶名和密碼成功后,將用戶的id等其他信息作為JWT負載,將其與頭部分別進行Base64編碼拼接后簽名,形成的JWT就是一個形同lll.zzz.xxx的字符串,格式為head.payload.signature。
后端將JWT字符串作為登錄成功的返回結果返回給前端,前端可以將返回的結果保存在localStorage或sessionStorage上,退出登錄時前端刪除保存的JWT。
前端為了解決XSS和XSRF問題,在每次請求時將JWT放入http head中的authorization位置。
后端檢查是否存在,如存在驗證JWT的有效性,檢查簽名是否正確,檢查Token是否過期,檢查Token的接收方是否是自己。
驗證通過后,后端使用JWT中包含的用戶信息進行其他邏輯操作,返回相應結果。
簡潔,可以通過Url和Http參數(shù)或者在Http請求頭發(fā)送,因為數(shù)據(jù)量小,傳輸速度也很快。
自包含,負載中包含了所有用戶所需要的信息,避免了多次查詢數(shù)據(jù)庫。
Token是以JSON加密的形式保存在客戶端的,所以JWT是跨語言的,原則上任何Web形式都支持。
不需要在服務端保存會話信息,特別適用于分布式微服務。
token string ====> header.payload.singnature token
標頭(Header)
有效載荷(Payload)
簽名(Signature)
因此,JWT通常如下所示:xxxxx.yyyyy.zzzzz Header.Payload.Signature
標頭通常由兩部分組成:令牌的類型和所使用的簽名算法,例如HMAC SHA256或RSA,它會使用 Base64 編碼組成 JWT 結構的第一部分。
Base64是一種編碼,是可以被翻譯回原來的樣子,它并不是一種加密過程。
{
"alg": "HS256",
"typ": "JWT"
}令牌的第二部分是有效負載,其中包含聲明。聲明是有關實體和其他數(shù)據(jù)的聲明,也使用 Base64 編碼組成 JWT 結構的第二部分。
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}前面兩部分都是使用 Base64 進行編碼的,即前端可以獲得里面的信息。Signature 需要使用編碼后的 header 和 payload 以及我們提供的一個密鑰,然后使用 header 中指定的簽名算法(HS256)進行簽名。
簽名的作用是保證 JWT 沒有被篡改過,例如HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),secret)。
如果對頭部以及負載的內容解碼之后進行修改,再進行編碼,最后加上之前的簽名組合形成新的JWT的話,那么服務器端會判斷出新的頭部和負載形成的簽名和JWT附帶上的簽名是不一樣的,如果要對新的頭部和負載進行簽名,在不知道服務器加密時用的密鑰的話,得出來的簽名也是不一樣的。
在JWT中,不應該在負載里面加入任何敏感的數(shù)據(jù)。

pom.xml
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.3.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>org.example</groupId> <artifactId>springboot-jwt-token</artifactId> <version>1.0-SNAPSHOT</version> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!--引入jwt--> <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--引入mybatis--> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.3</version> </dependency> <!--引入MySQL--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.18</version> </dependency> <!--引入druid--> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.23</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
application.properties
spring.application.name=jwt spring.datasource.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=utf8&useSSL=true&serverTimezone=UTC&useSSL=false spring.datasource.username=root mybatis.type-aliases-package=com.alfred.bean mybatis.mapper-locations=classpath:com/alfred/mapper/*.xml logging.level.com.alfred.dao=debug
mybatis xml映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.alfred.dao.UserDao">
<select id="login" parameterType="com.alfred.bean.User" resultType="com.alfred.bean.User">
select *
from tb_user
where name = #{name}
and password = #{password}
</select>
</mapper>實體類
@Data
@Accessors(chain = true)
public class User {
private String id;
private String name;
private String password;
}dao 層
@Mapper
public interface UserDao {
/**
* 登錄
*
* @param user User對象
* @return User對象
*/
User login(User user);
}service層
public interface UserService {
/**
* 登錄接口
*
* @param user 表單中的user
* @return 數(shù)據(jù)庫中查詢到的User
*/
User login(User user);
}@Service
public class UserServiceImpl implements UserService {
@Resource
private UserDao userDAO;
@Transactional(propagation = Propagation.SUPPORTS)
@Override
public User login(User user) {
User userDb = userDAO.login(user);
if (userDb != null) {
return userDb;
}
throw new RuntimeException("認證失敗");
}
}jwt工具類
public class JwtUtil {
private static String SECRET = "hell world";
/**
* 生成token
*
* @param map map集合
* @return token
*/
public static String getToken(Map<String, String> map) {
JWTCreator.Builder builder = JWT.create();
map.forEach(builder::withClaim);
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.HOUR, 12);
return builder.sign(Algorithm.HMAC256(SECRET));
}
/**
* 驗證token
*
* @param token token字符串
* @return 驗證接口
*/
public static DecodedJWT verify(String token) {
return JWT.require(Algorithm.HMAC256(SECRET)).build().verify(token);
}
}攔截器
@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 獲取請求頭中的令牌
String token = request.getHeader("token");
log.info("當前token為:{}", token);
Map<String, Object> map = new HashMap<>();
try {
JwtUtil.verify(token);
return true;
} catch (SignatureVerificationException e) {
e.printStackTrace();
map.put("msg", "簽名不一致");
} catch (TokenExpiredException e) {
e.printStackTrace();
map.put("msg", "令牌過期");
} catch (AlgorithmMismatchException e) {
e.printStackTrace();
map.put("msg", "算法不匹配");
} catch (InvalidClaimException e) {
e.printStackTrace();
map.put("msg", "失效的payload");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "token無效");
}
map.put("state", false);
//響應到前臺: 將map轉為json
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json);
return false;
}
}@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JwtInterceptor())
.addPathPatterns("/user/test")
.excludePathPatterns("/user/login");
}
}controller層
@RestController
@Slf4j
public class UserController {
@Resource
private UserService userService;
@GetMapping("/user/login")
public Map<String, Object> login(User user) {
log.info("用戶名:{}", user.getName());
log.info("密碼: {}", user.getPassword());
Map<String, Object> map = new HashMap<>();
try {
User userDb = userService.login(user);
Map<String, String> payload = new HashMap<>();
payload.put("id", userDb.getId());
payload.put("name", userDb.getName());
String token = JwtUtil.getToken(payload);
map.put("state", true);
map.put("msg", "登錄成功");
map.put("token", token);
return map;
} catch (Exception e) {
e.printStackTrace();
map.put("state", false);
map.put("msg", e.getMessage());
map.put("token", "");
}
return map;
}
@PostMapping("/user/test")
public Map<String, Object> test(HttpServletRequest request) {
String token = request.getHeader("token");
DecodedJWT verify = JwtUtil.verify(token);
String id = verify.getClaim("id").asString();
String name = verify.getClaim("name").asString();
log.info("id:{}", id);
log.info("用戶名: {}", name);
// TODO 業(yè)務邏輯
Map<String, Object> map = new HashMap<>();
map.put("state", true);
map.put("msg", "請求成功");
return map;
}
}上述就是小編為大家分享的JWT怎么用了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
網(wǎng)頁標題:JWT怎么用
網(wǎng)址分享:http://chinadenli.net/article20/phdcco.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供、服務器托管、響應式網(wǎng)站、軟件開發(fā)、微信小程序、網(wǎng)站設計
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經(jīng)允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)