A, JWT introduction
1. What is the JWT
Json web token (JWT) is a statement in order to pass between the network application execution environment JSON-based development standards (RFC 7519), the token is designed to be compact and safe, especially for distributed sites to a single point of landing ( SSO) scenarios. JWT's statement is generally used between identity providers and service providers to deliver the authenticated user identity information in order to obtain resources from the server, you can also add some additional business logic other necessary information statement, the token also may be directly used for authentication may be encrypted.
2 ,, based token authentication mechanism
Similar to the http protocol is stateless token-based authentication mechanism, which does not require the server to retain the authentication information or session information of the user. This means that the application does not require authentication mechanism tokent opportunity to consider which server the user logs in. This application provides a convenient extension
Such a process is
- User requests the server using the username and password
- Server for authentication of user information
- The server sends to the user by verifying a token
- Client storage token, the token and the additional values per request
- Server authentication token, and returns the data
This token must be sent with each request to the server, it should be kept in the request header, in addition, the server to support the CORS (Cross-Origin Resource Sharing) strategy, we usually do it in Access-Control-Allow server -Origin: *
3, JWT configuration
JWT is composed of three parts, these three pieces of information constitute a link with JWT text string. like this
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
The first part we call the head (header) of the second part of our call load (payload, similar to items carried on the plane), and the third part is the visa (signature)
header
JWT two pieces of information carried by the head:
- Declared type, here is jwt
- Assertion of the encryption algorithm is usually used directly HMAC SHA256
Complete the following JSON head like this
-
{
-
'typ':'JWT',
-
'alg':'HS256'
-
}
Then the head base64-encryption (the encrypted can be decrypted symmetric), constitutes the first portion
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
plyload
Load local storage is valid information. The name refers specifically to such goods carried on the aircraft, these effective information consists of three parts
- Standard registration statement
- Public Statement
- Private statement
Registered mark statement (not recommended mandatory use)
- iss: jwt issuer
- sub: jwt for the user
- aud: the receiving side jwt
- exp: jwt expiration time, the expiration date must be greater than the issue of time
- nbf: What time is defined before the jwt are unavailable
- iat: jwt the issue of time
- jti: jwt unique identity, is mainly used as a one-time token, in order to avoid a replay attack
Public statement:
Public declarations can add any information, general information about the user to add the necessary information or other business needs, but does not recommend adding sensitive information, because the part of the client can decrypt;
Private statement
Private statement is a provider of consumer-defined function declarations and is generally not recommended to store sensitive information, because base64 is decrypted symmetric, meaning that some of the information may be classified in the name of the text information.
Define a payload
-
{
-
"sub": "1234567890",
-
"name": "John Doe",
-
"admin": true
-
}
Base64 then encrypts the obtained part jwt
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
Signature
The third part is a jwt visa information, this visa information consists of three parts:
- header (after the base64)
- payload (after the base64)
- secred
This part needs to use the base64 payload header and the encrypted encryption base64. "" Connected to form a string, and then adding secret encrypted by the encryption header compositions declared, and the third portion constitutes the jwt
-
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
-
var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Connection with these three parts into a complete string, constitutes the final jwt ".":
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
Note: secret is stored on the server side, jwt issued also in the service side, secret is used to authenticate the issuance and jwt of jwt, so it is your server's private key, should not be revealed to any scenario, once the customer end that this secret, it means that the client can self-signed jwt the
application
-
一般是在请求头里加入Authorization,并加上 Bearer 标注:
-
fetch('api/user/1', {
-
headers: {
-
'Authorization': 'Bearer ' + token
-
}
-
})
advantage:
- Because of the versatility of json, so JWT can support cross-language, like C #, JavaScript, NodeJS, PHP and many other languages can be used
- Because of the payload portion, JWT business logic may store some other necessary information in its own non-sensitive
- Ease of transport, JWT configuration is very simple, small occupied bytes, so it is very easy to transport
- It does not require the server to save session information, so it is easy to extend the application
Safety-related
- We should not store sensitive information in a payload portion of jwt, because the portion is part of the client can decrypt
- Protect the secret private key. The private key is very important
- If you can, please use the https protocol
Information from the Internet,
Specific view https://blog.csdn.net/u014799292/article/details/88365086
Second, combat
First introduced into the jar package
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
New jwt of tools
public class JwtTokenUtil {
Final static String = TOKEN_HEADER public "the Authorization";
public static String TOKEN_PREFIX Final = "Bearer";
Private static SECRET Final String = "jwtsecrettest";
Private static ISS Final String = "Leopard";
public static Final Long EXPIRATION = 3600L; // expiration time one hour
public static final long EXPIRATION_REMEMBER = 604800L; // select Remember me time after expiration of 7 days
/ *
* generate token method
* @param username
* @param isRemenberMe
* /
public static String createToken (the above mentioned id String, String username, boolean isRemenberMe) {
Long expiration = isRemenberMe EXPIRATION_REMEMBER: eXPIRATION;?
// String encryId = RCUtils.encry_string(id);
return Jwts.builder().signWith(SignatureAlgorithm.HS512, SECRET)
.setIssuer(ISS)
.setId(id)
.setSubject(username)
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
.compact();
}
/ **
* Get the user name from the token
* @param token
* @return
* @throws BusinessExpection
* /
public static String the getUsername (String token) throws BusinessExpection {
return getTokenBody (token) .getSubject ();
}
/ **
* from token acquired ID, the decryption process while doing
* @param token
* @return
* @throws BusinessExpection
* /
public static String getObjectId (String token) throws BusinessExpection {
return getTokenBody (token) .getId ();
}
/ **
* has been expiration
* @param token
* @throws expired can not judge only by capturing abnormal ExpiredJwtException
* @return
* @throws BusinessExpection
*/
@Deprecated
public static boolean isExpiration(String token) throws BusinessExpection{
return getTokenBody(token).getExpiration().before(new Date());
}
/*
* 获取token信息,同时也做校验处理
*
*/
public static Claims getTokenBody(String token) throws BusinessExpection {
try {
return Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
}catch (ExpiredJwtException expired) {
// 过期
throw new BusinessExpection(EmBussinsError.TOKEN_EXPIRED);
}catch(SignatureException e) {
//无效
throw new BusinessExpection(EmBussinsError.INVALID_REQUEST);
}catch(MalformedJwtException malformedJwt) {
//无效
throw new BusinessExpection(EmBussinsError.INVALID_REQUEST);
}
}
}
Unified get token value in baseAction
The first step when a user logs generated token and returns.
@Controller
@RequestMapping("/admin")
public class AdminController extends BaseAction{
@RequestMapping("/login")
@ResponseBody
public ResultType login(HttpServletRequest request,HttpServletResponse response) {
String username = request.getParameter("username");
String pass = request.getParameter("pass");
String token = JwtTokenUtil.createToken("10", username, false);
response.setHeader(JwtTokenUtil.TOKEN_HEADER, JwtTokenUtil.TOKEN_PREFIX+token);
return ResultType.creat("sussess");
}
@RequestMapping("/adminLoginOut")
@ResponseBody
public ResultType adminLoginOut(HttpServletRequest request) throws BusinessExpection {
String userId = getUserid(request);
return ResultType.creat("success");
}
}
The test is successful, then return information header kinds of get token encrypted
Took in Log in user testing
When the error will not carry the token
Of course, this error can be your own custom here I am after all tests are written so simple. The main function is to test
When carrying token, the ok
When the operation was successful will carry the token and token authentication is successful.