当前位置:网站首页>JWT certification
JWT certification
2022-07-07 06:32:00 【Lingyixuan】
JWT
1. JWT What is it? ?
JSON Web Token (JWT) is an open standard (RFC 7519 ) that defines a compact and self-contained way for securelytransmitting information between parties as a JSON object. This information can be verified and trusted because it is digitllysigned.JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA orECDSA.
Official website address : https://jwt.io/introduction/
translate : jsonwebtoken (JWT) It's an open standard (rfc7519), It defines a compact 、 The self-contained way , Used between parties to JSON Objects transmit information securely . This information can be verified and trusted , Because it's digitally signed .jwt You can use secrets ( Use HNAC Algorithm ) Or use RSA or ECDSA The public key / The private key pair is signed
Popular explanation
JWT abbreviation .JSON Web Token , That is, through .JSON Formal act Web Token in application , Used to securely treat information as between parties JSON Object transfer . Data encryption can also be completed in the process of data transmission 、 Signature and other related processing .
2. JWT What can be done
1. to grant authorization
This is the use of JWT The most common solution . Once the user logs in , Each subsequent request will include JWT, This allows the user to access the route allowed by the token , Services and resources . Single sign on is widely used today JWT A feature of , Because it costs little and can be easily used in different domains .
2. Information switching
JSON Web Token It's a good way to safely transfer information between parties . Because you can be right JWT To sign 《 for example , Use public key / Private key pair ), So you can make sure that the sender is the person they are talking about . Besides , Because the signature is computed using headers and payloads , So you can also verify that the content has been tampered with .
3. Why JWT
Traditional based session authentication
- 1. authentication
We know ,http Protocol itself is a stateless protocol , This means that if the user provides a user name and password to our application for user authentication , So the next time you ask , The user has to do user authentication again , Because according to http agreement , We don't know which user made the request , So in order for our application to recognize which user made the request , We can only store one copy of user login information on the server , This login information will be passed to the browser in response , Tell it to save as cookie, So that the next request can be sent to our app , In this way, our application can recognize that the request comes from users , This is the basis of tradition session authentication .
- 2. The certification process
3. Expose the problem
1. After each user has passed our application authentication , Our applications all need to record the value at the server once , In order to facilitate the identification of the user's next request , generally session It's all stored in memory , And with the increase of authenticated users , The cost of the server will increase obviously 2. After user authentication , The server makes authentication records , If the authentication record is stored in memory , This means that the next time a user requests it, he must request it on this server . In this way, we can get the authorized resources , So in distributed applications , Accordingly, the capacity of load balancer is limited . This also means that the expansion ability of the application is limited . 3. Because it's based on cookie For user identification ,cookie If intercepted . Users will be vulnerable to cross site request forgery attacks . 4. It's even more painful in the front and rear separation system : The front and back end separation increases the complexity of deployment after application decoupling . Usually, users have to forward multiple requests in a single request . If you use session Every time sessionid To the server , The server also needs to query user information . At the same time, if there are many users . This information is stored in the server memory , Add a load to the server . And that is CSRF( Cross site forgery request attack ) attack ,session Is based on cookie For user identification ,cookie If it is hidden , Users will be vulnerable to cross site request forgery attacks . And that is sessionid It's an eigenvalue . The information expressed is not rich enough . It's not easy to expand . And if your application is multi node deployment . Then we need to achieve session Sharing mechanism . It is not convenient for cluster application .
4. JWT What's the structure of the system ?
Token composition
token string ====> header.payload.signature token
1. header (Header)
2. Payload (Payload)
3. Signature (Signature)
+ therefore ,JWT Usually as follows :xxxxx.yyyyy.zzzzz Header.Payload.Signature
2.Header
The header usually consists of two parts : Type of token ( namely JWT) And the signature algorithm used , for example HINAC SHA256 or RSA. It will use Base64 Code composition JWT The first part of the structure .
- Be careful :Base64 It's a kind of coding , in other words , It can be translated back to the original . It's not an encryption process .
{
"alg" : "HS256",
"typ" : "JWT"
}
3.Payload
The second part of the token is the payload , It contains a statement . The declaration is about the entity ( Usually the user ) Claims and other data . alike , It will use Base64 Code composition JWT The second part of the structure
{
"sub" : "1234567890",
"name" : "John Doe",
"admin" : true
}
4.Signature
- The first two parts use Base64 Coded , That is, the front end can unlock the information inside .Signature You need to use the encoded header and payload And a key we provided , And then use header The signature algorithm specified in (HS256) To sign . The purpose of signature is to guarantee JWT It has not been tampered with
- Such as :
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload) ,secret);
# Signature purpose
- The last step in the process of signing , It's actually signing the header and payload content . Prevent content from being tampered with . If someone decodes the header and the content of the load and then modifies it before encoding , Finally, add the previous signature combination to form a new JWT Words , Then the server side will determine the signature and JWT The signature attached is different . If you want to sign the new header and payload , If you don't know the key used by the server for encryption , The signature is also different .
# Information security issues
- Here we will ask a question :Base64 It's a kind of coding , It's reversible , Then my information was exposed ?
- Yes . therefore , stay JWT in , No sensitive data should be added to the load . In the example above , We transmit the user's User ID. This value is actually not sensitive , It's generally known to be safe . But content like passwords can't be placed in JWT It's in . If you put the user's password in JWT in , Then a malicious third party passes through Base64 Decode it and you'll soon know your password . therefore JWT Suitable for applying to Web Applications deliver some non sensitive information .JWT It is also often used to design user authentication and authorization systems , Even realize Web Single sign on for applications .
#5. Put together
- The output is three dots separated Base64-URL character string , Can be in HTML and HTTP These strings are easily passed in the environment , And based on XMNL Standards for ( for example SAML) comparison , It's more compact .
- concise (Compact) Can pass URL,POST Parameters may be in HTTP header send out , Because of the small amount of data , Fast transmission speed
- Self contained (Self-contained)
The load contains all the information the user needs , Avoid multiple queries to the database
eyJhbGci0iJIUzI1NiIsInR5cCI6IkpXVc.xp.
eyJzdWI:OiIxMjMGNTY30DkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaXNTb2NpYWwiOnRydwv9.
4pcPyMD09olPSyxnrXCjTwXyr4BsezdI1AVTmud2fU4
5. Use JWT
# First step : Introduce dependencies
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.1</version>
</dependency>
<!-- introduce jar-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.1</version>
</dependency>
<!-- introduce Mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<!-- introduce lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<!-- introduce druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- introduce mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Simple test cases :
@SpringBootTest
class SpringBootJWtApplicationTests {
public static final String SIGNATURE = "tiofjdifjaihu899#(*U(*#@";
private String token;
@Test
public void contextLoads() {
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND, 90);
# The second step : Generate token
String token = JWT.create()
.withClaim("username", "Zhang San")
.withClaim("password", "Java")
.withExpiresAt(instance.getTime()) // Expiration time
.sign(Algorithm.HMAC256(SIGNATURE));
this.token = token;
System.out.println(" token = " + token);
# Parse data based on token and signature
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SIGNATURE)).build();
DecodedJWT decodedJWT = jwtVerifier.verify(token);
System.out.println(" user name : " + decodedJWT.getClaim("username").asString());
System.out.println(" The secret code : " + decodedJWT.getClaim("password").asString());
System.out.println(" Expiration time : " + decodedJWT.getExpiresAt());
}
}
#4. Common exception information
- SignatureVerificationException: Signature inconsistency exception
- TokenExpiredException: Token expiration exception
- AlgorithmMismatchException: Algorithm mismatch exception
- InvalidClaimException: Invalid payload abnormal
6. The actual case
database
CREATE DATABASE jwt;
USE jwt;
CREATE TABLE `user` (
`id` INT ( 11 ) NOT NULL AUTO_INCREMENT COMMENT ' Primary key ',
`name` VARCHAR ( 40 ) DEFAULT NULL COMMENT ' user name ',
`password` VARCHAR ( 40 ) DEFAULT NULL COMMENT ' The secret code ',
PRIMARY KEY ( `id` )
) ENGINE = INNODB AUTO_INCREMENT = 2 CHARSET = utf8;
Add a piece of data to the database
INSERT INTO user(name, password) VALUE('zhangsan', '123');
Project structure chart
applicatoin.yaml Profile contents
server:
port: 8081
spring:
application:
name: SpringBootJWt
datasource:
username: Database user name
password: Database password
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql:// The server IP Address : port /jwt?characterEncoding=utf8&useSSL=false&serverTimezone=UTC&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true
mybatis:
type-aliases-package: com.jwt.entity
mapper-locations: mapper/UserMapper.xml
logging:
level:
com.jwt.dao: debug
User Entity class
@Data
public class User {
private String id;
private String name;
private String password;
}
UserDao
@Mapper
public interface UserDao {
User login(@Param("user") User user);
}
Project structure chart
UserMapper
<?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.jwt.dao.UserDao">
<select id="login" resultType="com.jwt.entity.User">
select * from user where name=#{
user.name} and password=#{
user.password}
</select>
</mapper>
UserService
public interface UserService {
User login(User user);
}
UserServiceImpl
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDao userDao;
@Override
public User login(User user) {
User login = userDao.login(user);
if(login != null)
return login;
throw new RuntimeException(" Login failed ");
}
}
JWTUtils
public class JWTUtils {
public static final String SIGNATURE = "fudsifu98ewqurw90ur&^*()#(JI()WEPJBVDS";
// Generate token
public static String getToken(Map<String, String> map){
JWTCreator.Builder builder = JWT.create();
map.forEach((key, value)->{
builder.withClaim(key, value);
});
Calendar instance = Calendar.getInstance();
instance.add(Calendar.MINUTE, 7);
builder.withExpiresAt(instance.getTime());
return builder.sign(Algorithm.HMAC256(SIGNATURE));
}
/** * verification token Legitimacy * @param token */
public static void verify(String token){
JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
}
/** * obtain token Information methods * @param token * @return */
public static DecodedJWT getToken(String token){
return JWT.require(Algorithm.HMAC256(SIGNATURE)).build().verify(token);
}
}
JWTInterceptor
public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
Map<String, Object> map = new HashMap<>();
try {
JWTUtils.verify(token);
return true;
}catch (SignatureVerificationException e) {
map.put("msg", " Inconsistent signature ");
e.printStackTrace();
}catch (TokenExpiredException e){
map.put("msg", " The token expired ");
e.printStackTrace();
} catch (AlgorithmMismatchException e){
map.put("msg", " Algorithm mismatch ");
e.printStackTrace();
}catch (InvalidClaimException e){
map.put("msg", " Abnormal load ");
e.printStackTrace();
}
map.put("state", false);
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=utf8");
response.getWriter().println(json);
return false;
}
}
InterceptorConfig
@Component
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
.addPathPatterns("/user/test")
.excludePathPatterns("/user/login"); // For login, all directions , Other token verification
}
}
UserController
@RestController
@Slf4j
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/user/login")
public Map<String, Object> login(User user) {
log.info(" User name : [{}]", user.getName());
log.info(" User password : [{}]", user.getPassword());
HashMap<String, Object> hashMap = new HashMap<>();
try {
User login = userService.login(user);
HashMap<String, String> payload = new HashMap<>();
payload.put("id", login.getId());
payload.put("name", login.getName());
payload.put("password", login.getPassword());
String token = JWTUtils.getToken(payload);
hashMap.put("state", true);
hashMap.put("msg", " Authentication success ");
hashMap.put("token", token);
} catch (Exception e) {
hashMap.put("state", false);
hashMap.put("msg", e.getMessage());
}
return hashMap;
}
// The first edition , Directly verify when logging in
//@PostMapping("/user/test")
//public Map<String, Object> test(String token) {
// Map<String, Object> map = new HashMap<>();
// log.info(" At present token by {}", token);
//
// try {
// DecodedJWT verify = JWTUtils.getToken(token);
// map.put("state", true);
// map.put("msg", " The request is successful !");
// return map;
// } catch (SignatureVerificationException e) {
// map.put("msg", " Inconsistent signature ");
// e.printStackTrace();
// }catch (TokenExpiredException e){
// map.put("msg", " The token expired ");
// e.printStackTrace();
// } catch (AlgorithmMismatchException e){
// map.put("msg", " Algorithm mismatch ");
// e.printStackTrace();
// }catch (InvalidClaimException e){
// map.put("msg", " Abnormal load ");
// e.printStackTrace();
// }
//
// map.put("state", false);
// return map;
//}
// The second edition , After logging in , No need to verify , But every time I ask, I will bring token, token Process in the interceptor
// After registration , Front end carrying token Put it on the token in , Back end from request Get from the request header in
@PostMapping("/user/test")
public Map<String, Object> test(HttpServletRequest request) {
Map<String, Object> map = new HashMap<>();
String token = request.getHeader("token");
DecodedJWT verify = JWTUtils.getToken(token);
log.info(" user id : " + verify.getClaim("id").asString());
log.info(" user name : " + verify.getClaim("name").asString());
log.info(" user password : " + verify.getClaim("password").asString());
log.info(" Expiration time : " + verify.getExpiresAt());
map.put("msg", " Authentication success ");
map.put("state", true);
return map;
}
}
边栏推荐
- 如何解决数据库插入数据显示SQLSTATE[HY000]: General error: 1364 Field ‘xxxxx‘ doesn‘t have a default value错误
- 线性代数(一)
- Experience of Niuke SQL
- Test the foundation of development, and teach you to prepare for a fully functional web platform environment
- 软件测试到了35岁,真的就干不动了吗?
- Qtthread, one of many methods of QT multithreading
- Developers don't miss it! Oar hacker marathon phase III chain oar track registration opens
- Handling hardfault in RT thread
- 牛客小白月赛52 E.分组求对数和(二分&容斥)
- 蚂蚁庄园安全头盔 7.8蚂蚁庄园答案
猜你喜欢
ICML 2022 | explore the best architecture and training method of language model
You don't know the complete collection of recruitment slang of Internet companies
字符串常量与字符串对象分配内存时的区别
tkinter窗口选择pcd文件并显示点云(open3d)
Common problems of caching in high concurrency scenarios
高并发大流量秒杀方案思路
Developers don't miss it! Oar hacker marathon phase III chain oar track registration opens
ETCD数据库源码分析——从raftNode的start函数说起
Experience sharing of contribution of "management world"
Ant manor safety helmet 7.8 ant manor answer
随机推荐
Matlab / envi principal component analysis implementation and result analysis
C language sorting (to be updated)
[FPGA] EEPROM based on I2C
window下面如何安装swoole
字符串常量与字符串对象分配内存时的区别
Rk3399 platform development series explanation (interruption) 13.10, workqueue work queue
go-microservice-simple(2) go-Probuffer
Audio distortion analysis of DSP and DAC based on adau1452
QT console output in GUI applications- Console output in a Qt GUI app?
Test the foundation of development, and teach you to prepare for a fully functional web platform environment
C interview encryption program: input plaintext by keyboard, convert it into ciphertext through encryption program and output it to the screen.
Markdown displays pictures side by side
Find duplicate email addresses
The difference between string constants and string objects when allocating memory
uniapp开发小程序如何使用微信云托管或云函数进行云开发
Handling hardfault in RT thread
A very good JVM interview question article (74 questions and answers)
How can I check the DOI number of a foreign document?
C language (structure) defines a user structure with the following fields:
UIC(组态UI工程)公版文件库新增7款行业素材