Now that the API is becoming more and more popular, how to secure these APIs? The JSON Web Tokens (JWT) provides secure authentication based on JSON format. It has the following characteristics:
- JWT is available across different languages, and JWT can be used in. NET, Python, node. js, Java, PHP, Ruby, Go, JavaScript, and Haskell
- JWT is self-contained and contains all the necessary information, which means that JWT can deliver basic information about itself, such as user information and signatures.
- JWT delivery is easy because JWT is self-contained, they can be perfectly used in HTTP headers, and when an authorization API is required, you can just pass it through a URL.
The JWT is easy to identify and is a three-part string of decimal points:
Aaaaaaaaaa.bbbbbbbbbbb.cccccccccccc
The meanings of these three parts are header,payload, signature
Header
The head contains two aspects: the type and the hashing algorithm used (such as HMAC SHA256):
{"Typ": "JWT","ALG": "HS256" }
To encode this JSON character Base64Encode, we have the first JWT:
Eyjhbgcioijiuzi1niisinr5cci6ikpxvcj9
Payload
The second part of JWT is payload, also known as JWT Claims, where we need to transfer information that has multiple items such as registered claim name, public claim name and private claim name.
The registered claim name has the following sections:
- Publisher of the Iss:token
- Sub:token's Topic
- Aud:token's Customers
- Exp: often used to define the expiration period in digital time, that is, the token fails at some time after the current time.
- NBF: The JWT will not accept processing until this time is defined. Start effective time
- IAT:JWT release time, can be used to determine the age of JWT
- JTI:JWT unique identification. Can be used to prevent the JWT from being reused, using only one token at a time, and if the value of this claim is "1" at the time of issuance, validation fails if the value of this claim is not "1".
Public claim names are used to define the information we create, such as user information and other important information.
The private claim name is used by both the publisher and the consumer to agree to use the claim name in a private way.
Here is a case of JWT:
{"ISS": "Scotch.io","exp": 1300819380,"name": "Chris Sevilleja",true }
Signature
JWT The third part is the signature, and the signature consists of the following components:
- Header
- Payload
- Secret key
Here's how we get to the third part of JWT:
var encodedstring = Base64urlencode (header) + "." + base64urlencode (payload); HMACSHA256 (encodedstring, ' secret ');
The secret here is signed by the server, and our server is able to verify the existing token and sign the new token.
The algorithms supported by TWT are:
============================================================================================================
The above is the theoretical part of the official website, the following will provide some examples:
Import Dependencies First:
<dependency> <groupId>com.auth0</groupId> <artifactid>java-jwt</artifactid > <version>3.2.0</version></dependency>
1, specify the encryption algorithm:
// HMAC Algorithm ALGORITHMHS = algorithm.hmac256 ("secret");
-------------------------------------------------------------------------
Rsa
Map<string,object> Keys=rsautils.getkeys ();
Rsapublickey PublicKey = (rsapublickey) keys.get ("public"); Get the key instance
Rsaprivatekey Privatekey = (rsaprivatekey) keys.get ("private");//get the key instance
Algorithm Algorithmrs = algorithm.rsa256 (PublicKey, Privatekey);
2, Generate tokens
Generate tokens with HS256
Try { = algorithm.hmac256 ("secret"); = jwt.create () . Withissuer ("Auth0") catch (unsupportedencodingexception Exception) { //UTF-8 encoding not supportedcatch ( Jwtcreationexception exception) { //Invalid Signing configuration/couldn ' t convert Claims .}
Generate tokens with RS256
Map<string,object> keys=Rsautils.getkeys (); Rsapublickey PublicKey= (Rsapublickey) keys.get ("public");//Get the key instanceRsaprivatekey Privatekey = (rsaprivatekey) keys.get ("private");//Get the key instanceTry{algorithm algorithm=algorithm.rsa256 (PublicKey, Privatekey); String token=jwt.create (). Withissuer ("Auth0"). sign (algorithm);} Catch(Jwtcreationexception exception) {//Invalid Signing configuration/couldn ' t convert Claims.}
3, verify Token
1) General validation
Verifying tokens with HS256
String token = " Eyjhbgcioijiuzi1niisinr5cci6ikpxuyj9.eyjpc3mioijhdxromcj9.abijtdmfc7yua5mhvcp03njpycpzztqcgep-zwfokee ";Try{algorithm algorithm= algorithm.hmac256 ("Secret"); Jwtverifier verifier=jwt.require (algorithm). Withissuer ("Auth0"). build (); //Reusable Verifier InstanceDECODEDJWT JWT =verifier.verify (token);} Catch(Unsupportedencodingexception exception) {//UTF-8 encoding not supported}Catch(Jwtverificationexception exception) {//Invalid signature/claims}
Verifying tokens with RS256
String token = " Eyjhbgcioijiuzi1niisinr5cci6ikpxuyj9.eyjpc3mioijhdxromcj9.abijtdmfc7yua5mhvcp03njpycpzztqcgep-zwfokee "; Rsapublickey PublicKey=//Get the key instanceRsaprivatekey Privatekey =//Get the key instanceTry{algorithm algorithm=algorithm.rsa256 (PublicKey, Privatekey); Jwtverifier verifier=jwt.require (algorithm). Withissuer ("Auth0"). build (); //Reusable Verifier InstanceDECODEDJWT JWT =verifier.verify (token);} Catch(Jwtverificationexception exception) {//Invalid signature/claims}
2) in payload it is possible to customize the data for verification, including time and so on.
Specify the data when generating tokens:
@Test Public voidGen1 ()throwsIOException {String token=""; SimpleDateFormat SDF=NewSimpleDateFormat ("Yyyy-mm-dd HH:mm:ss"); //Date to StringCalendar Calendar =calendar.getinstance (); Calendar.add (Calendar.second,30);//years after a certain timeDate Date =Calendar.gettime (); Try{algorithm algorithm= algorithm.hmac256 ("Mysecrite"); Token=jwt.create (). Withissuer ("Auth0"). Withsubject ("Xiaoming"). Withclaim ("Name", 123). Witharrayclaim ("Array",NewInteger[]{1, 2, 3}). Withexpiresat (date). sign (algorithm); System.out.println ("Loglogagel:" +token); } Catch(Unsupportedencodingexception exception) {//UTF-8 encoding not supported}Catch(Jwtcreationexception exception) {//Invalid Signing configuration/couldn ' t convert Claims. } }
Verify that token is out of date, and that there are any established
@Test Public voidGen3 () {String token= "Eyj0exaioijkv1qilcjhbgcioijiuzi1nij9.eyjpc3mioijhdxromcisimv4cci6mtq5nzy4ntqwox0.dhy-90jaa63_ Tvi-grz2ohciitmajb45zb1tdchq_nq "; Try{algorithm algorithm= algorithm.hmac256 ("Mysecrite"); Jwtverifier.baseverification Verification=(jwtverifier.baseverification) jwt.require (algorithm). Withissuer ("Auth0"). Withsubject ("Xiaomong"); Clock Clock=NewClock () {@Override PublicDate Gettoday () {return NewDate (); } };//must implement Clock interfaceJwtverifier verifier =verification.build (clock); DECODEDJWT JWT=verifier.verify (token); System.out.println (Jwt.getalgorithm ()); System.out.println (Jwt.gettype ()); System.out.println (Jwt.getissuer ()); System.out.println (Jwt.getexpiresat ()); } Catch(Unsupportedencodingexception exception) {//UTF-8 encoding not supportedException.printstacktrace (); } Catch(Jwtverificationexception exception) {//Invalid signature/claimsException.printstacktrace (); }}
If the subject validation is inconsistent, the following error is reported:
If the time exceeds 30 seconds, the following error will be reported:
A slight modification of the method of validation:
@Test Public voidGen3 () {String token= "EYJ0EXAIOIJKV1QILCJHBGCIOIJIUZI1NIJ9.EYJZDWIIOIJ4AWFVBWLUZYISIMFYCMF5IJPBMSWYLDNDLCJPC3MIOIJHDXROMCISIM5HBWUIOIJJYW0GC MLNAHQGZNJVBSBJBGFPBSISIMV4CCI6MTQ5NZY4OTQ4NX0.6LSXISVAGI8B2WAVAZQ4TJ-H9PGD6GGAOYZLZ_GPFMU "; Try{algorithm algorithm= algorithm.hmac256 ("Mysecrite"); Jwtverifier.baseverification Verification=(jwtverifier.baseverification) jwt.require (algorithm). Withissuer ("Auth0"). Withsubject ("Xiaoming"); Clock Clock=NewClock () {@Override PublicDate Gettoday () {return NewDate (); } };//must implement Clock interfaceJwtverifier verifier =verification.build (clock); DECODEDJWT JWT=verifier.verify (token); Map<string, claim> claims = Jwt.getclaims ();//Key is the Claim nameClaim Claim = claims.get ("name"); System.out.println (Claim.asstring ()); //print out the value of claimSystem.out.println (Jwt.getalgorithm ()); System.out.println (Jwt.gettype ()); System.out.println (Jwt.getissuer ()); System.out.println (Jwt.getexpiresat ()); } Catch(Unsupportedencodingexception exception) {//UTF-8 encoding not supportedException.printstacktrace (); } Catch(Jwtverificationexception exception) {//Invalid signature/claimsException.printstacktrace (); }
The final result after validation:
4,claim Add, get
1) The built-in payload mainly have the following, if not return null
Issuer ("ISS"): Publisher
String issuer = Jwt.getissuer ();
Subject ("Sub")
String subject = Jwt.getsubject ();
Audience ("AUD")
List<string> audience = Jwt.getaudience ();
Expiration Time ("exp")
Date Expiresat = Jwt.getexpiresat ();
Not before ("NBF")
Date Notbefore = Jwt.getnotbefore ();
Issued at ("IAT")
Date Issuedat = Jwt.getissuedat ();
JWT ID ("JTI")
String id = jwt.getid ();
2) define a private claim
Add to:
String token = jwt.create () . Withclaim("name", 123) . Witharrayclaim (new integer[ ]{1, 2, 3}) . sign (algorithm);
Get:
Jwtverifier verifier = jwt.require (algorithm) .Withclaim ("name", 123) . Witharrayclaim (" Array ", 1, 2, 3) = verifier.verify (" My.jwt.token ");
Currently, the officially supported claim types are: Boolean, Integer, Double, String, Date, string[], and Integer.
5, Header Claims
1) header claims is the definition of the header part of the content, basically is the default definition, do not need to set up, built-in has:
Algorithm ("ALG")
String algorithm = Jwt.getalgorithm ();
Type ("Typ")
String type = Jwt.gettype ();
Content Type ("Cty")
String ContentType = Jwt.getcontenttype ();
Key Id ("Kid")
String keyId = Jwt.getkeyid ();
2) Add:
New HashMap (); Headerclaims.put ("owner", "Auth0"= jwt.create () . Withheader (Headerclaims) . sign (algorithm);
3) Get:
Claim Claim = Jwt.getheaderclaim ("owner");
Summary: Look at some other people's blog, found that their APIs are relatively old version, the generation of tokens is step by step, the new is really simple and convenient many. Sharing is here, welcome to exchange.
Reference Address: HTTPS://GITHUB.COM/AUTH0/JAVA-JWT
JSON Web Tokens (JWT)