This is a creation in Article, where the information may have evolved or changed.
Life goes on and on go Go go!!!
Previously wrote a blog about how cookies are used in Golang:
Use cookies in combat –go
Let's talk a little bit about how to use tokens in Golang today, and rely on the excellent open source libraries on GitHub, of course.
First of all, to understand a problem, token, cookie, session of the difference.
token, cookie, session difference
Cookies
Cookies are always stored in the client, and can be divided into memory cookies and hard disk cookies by the storage location in the client.
The memory cookie is maintained by the browser, stored in memory, and disappears after the browser is closed, and its presence time is short. The hard disk cookie is saved on the hard drive, there is an expiration time, unless the user manually cleans up or expires, the hard disk cookie is not deleted and its presence time is long. Therefore, by time of existence, it can be divided into non-persistent cookies and persistent cookies.
A cookie is a very specific thing, refers to the browser can be permanently stored in a data, is only a browser implementation of a data storage function.
The cookie is generated by the server, sent to the browser, the browser saves the cookie in key-value form in a text file in a directory, and the next time the same website is requested, the cookie is sent to the server. Because the cookie is present on the client, the browser has added some restrictions to ensure that the cookie is not used maliciously and does not occupy too much disk space, so the number of cookies per domain is limited.
Session
The session is literally a conversation. This is similar to how you talk to a person, how do you know the current conversation with you is Zhang San rather than John Doe? The other person must have a certain character (looks, etc) to show that he is Zhang San.
The session is similar to the truth, the server should know who is currently sending the request to itself. To make this distinction, the server assigns a different "identity" to each client, and then each time the client sends a request to the server, it takes the "identity" and the server knows who the request came from. As for the client how to save this "identity", there can be many ways, for the browser client, everyone is the default way of using cookies.
The server uses the session to temporarily save the user's information on the server, and the session will be destroyed after the user leaves the site. This user information is stored in a more secure way than a cookie, but the session has a flaw: if the Web server is load balanced, the session is lost when the next operation requests to another server.
Token
Token means "tokens", which is the authentication method of the user identity, the simplest token composition: UID (user's unique identity), time (timestamp of the current time), sign (signature, the hash algorithm is compressed into a long hexadecimal string by the first several + salts of token, Can prevent malicious third party stitching token request server). You can also put the invariant parameters into token, avoid multiple check the library
The token here refers to the son Web token:
JSON Web Token (JWT) is a compact url-safe means of representing claims to be transferred between. The claims in a JWT was encoded as a JSON object that is digitally signed using JSON Web Signature (JWS).
using JWT for certification
JSON Web Tokens (JWT) is a more modern approach to authentication.
As the web moves to a greater separation between the client and server, JWT provides a wonderful alternative to Traditiona L Cookie based authentication models.
Jwts provide a-on-clients to authenticate every request without have to maintain a session or repeatedly pass login Credentials to the server.
After the user registers, the server generates a JWT token to return to the browser, the browser sends the JWT token to the server when requesting data from the server, and the server decodes it in the way defined in signature
JWT gets the user information.
A JWT token consists of 3 parts:
1. Header: Tell us the algorithm and token type used
2. Payload: You must use Sub key to specify the user ID, and can include other information such as email, username, etc.
3. Signature: Used to ensure the authenticity of the JWT. Different algorithms can be used
JWT Application
It says so much, the next step is to coding.
Open Source Libraries used:
Github.com/codegangsta/negroni
Idiomatic HTTP middleware for Golang
A middleware for HTTP
github.com/dgrijalva/jwt-go
Golang implementation of JSON Web Tokens (JWT)
Github.com/dgrijalva/jwt-go/request
Here are two APIs, one to get tokens through login, and then to access another API based on token. First look at how login is generating tokens:
Of course the first is to verify the user name and password, in order to save space here is just the code snippet, the complete code is finally presented.
token: = JWT. New (JWT. SIGNINGMETHODHS256) Claims: = make (JWT. mapclaims) Claims[ "exp" ] = time. Now (). ADD (time. Hour * time. Duration)). Unix () Claims[ "IAT" ] = time. Now (). Unix () token. Claims = Claims if err! = nil {w.writehead ER (http. Statusinternalservererror) fmt. Fprintln (W, "Error extracting the Key" ) Fatal (ERR)} tokenstring, err: = Tok En. Signedstring ([]byte (Secretkey)) if err! = Span class= "Hljs-constant" >nil {w.writeheader (http. Statusinternalservererror) fmt. Fprintln (W, "Error while signing the token" ) Fatal (ERR)}
The
Next is the middleware that validates tokens:
token, err: = Request. Parsefromrequest (R, request.) Authorizationheaderextractor, func (token *JWT. Token) (interface {}, error) {return []
byte (Secretkey),
nil })
if err = =
nil {
if token. Valid {Next (W, R)}
else {w.writeheader (http. statusunauthorized) fmt. Fprint (W,
"Token is not valid" )}}
else { W.writeheader (http. statusunauthorized) fmt. Fprint (W,
"unauthorized access to this resource" )}
Final complete code:
PackageMainImport("Encoding/json" "FMT" "Log" "Net/http" "Strings" "Time" "Github.com/codegangsta/negroni" "Github.com/dgrijalva/jwt-go" "Github.com/dgrijalva/jwt-go/request")Const(Secretkey ="Welcome to Wangshubo ' s blog")funcFatal (err Error) {ifErr! =Nil{log. Fatal (ERR)}}typeUsercredentialsstruct{Usernamestring ' JSON: ' username 'Passwordstring ' JSON: ' Password '}typeUserstruct{IDint ' JSON: ' ID 'Namestring ' JSON: ' Name 'Usernamestring ' JSON: ' username 'Passwordstring ' JSON: ' Password '}typeResponsestruct{Datastring ' JSON: ' Data '}typeTokenstruct{Tokenstring ' JSON: ' token '}funcStartServer () {http. Handlefunc ("/login", Loginhandler) http. Handle ("/resource", Negroni. New (Negroni. Handlerfunc (Validatetokenmiddleware), Negroni. Wrap (http. Handlerfunc (Protectedhandler))) log. Println ("Now listening ...") http. Listenandserve (": 8080",Nil)}funcMain () {StartServer ()}funcProtectedhandler (w http. Responsewriter, R *http. Request) {response: = response{"gained access to protected resource"} jsonresponse (Response, W)}funcLoginhandler (w http. Responsewriter, R *http. Request) {varUser Usercredentials Err: = json. Newdecoder (R.body). Decode (&user)ifErr! =Nil{W.writeheader (http. Statusforbidden) fmt. Fprint (W,"Error in Request")return}ifStrings. ToLower (user. Username)! ="Someone"{ifUser. Password! ="p@ssWOrd"{W.writeheader (http. Statusforbidden) fmt. Println ("Error Logging in") FMT. Fprint (W,"Invalid Credentials")return}} Token: = JWT. New (JWT. SIGNINGMETHODHS256) Claims: = Make(JWT. MAPCLAIMS) claims["Exp"] = time. Now (). ADD (time. Hour * time. Duration(1)). Unix () claims["IAT"] = time. Now (). Unix () token. Claims = ClaimsifErr! =Nil{W.writeheader (http. Statusinternalservererror) fmt. Fprintln (W,"Error extracting the key") Fatal (ERR)} tokenstring, err: = token. Signedstring ([]byte(Secretkey))ifErr! =Nil{W.writeheader (http. Statusinternalservererror) fmt. Fprintln (W,"Error While signing the token") Fatal (ERR)} Response: = token{tokenstring} jsonresponse (Response, W)}funcValidatetokenmiddleware (w http. Responsewriter, R *http. Request, next http. Handlerfunc) {token, err: = Request. Parsefromrequest (R, request.) Authorizationheaderextractor,func(Token *JWT. Token) (Interface{}, error) {return[]byte(Secretkey),Nil})ifErr = =Nil{ifToken. Valid {Next (W, R)}Else{W.writeheader (http. statusunauthorized) fmt. Fprint (W,"Token is not valid") } }Else{W.writeheader (http. statusunauthorized) fmt. Fprint (W,"Unauthorized access to this resource") }}funcJsonresponse (responseInterface{}, W http. Responsewriter) {json, err: = json. Marshal (response)ifErr! =Nil{http. Error (W, err. Error (), HTTP. Statusinternalservererror)return} w.writeheader (http. Statusok) W.header (). Set ("Content-type","Application/json") W.write (JSON)}
Verify with Postman:
Login
Get request based on Get token: