本文已参与「新人创作礼」活动,一起开启掘金创作之路。
JSON Web token 简称 jwt 是一种轻量级的用户认证机制。可以取代cookie或session的用户认证方式。
优点:
JWT要求有一个秘钥,还有一个算法,秘钥和算法可以用来生成签名的保证jwt不被篡改
- 自带超时信息
JWT的base64明文机制,可以使得web页面可以轻易获得超时信息
可以做什么?
- 认证用户的登录状态
- 授权用户特定操作或者获取特定资源
- 跨域传递用户授权信息
不可以做什么?
- 持久化用户信息
- 存储用户敏感信息例如密码,卡号,电话等(jwt是明文保存用户信息Playload)
- 传递大量信息(这个放Cookie不香么)
可以完全取代session么?
你觉得可能么?session是在服务端存储用户信息,本身就有服务端安全的优势,存储内容也没有限制。 都说了jwt只是轻量级用户授权机制,为啥要干重活呢?jwt + session不可以么?说实话在url中传递session真是蠢透了!
优雅的使用axios接入jwt
自动拦截注入jwt授权信息,服务端jwt验证失败时(401)直接跳转回登录页面
**
* 拦截器,为请求头添加jwt信息
*/
let http = axios.create({
baseURL: 'http://xxx.xxx.xxx.xxx/blog',
timeout: 10000
})
http.interceptors.request.use(
config => {
if (storage.get('JWT_TOKEN')) { // 判断是否存在token,如果存在的话,则每个http header都加上token
config.headers.Authorization = `token ${storage.get('JWT_TOKEN')}`
}
return config
},
err => {
return Promise.reject(err)
}
)
http.interceptors.response.use(
response => {
return response
},
error => {
if (error.response) {
console.log('axios:' + error.response.status)
switch (error.response.status) {
case 401:
// 返回 401 清除token信息并跳转到登录页面
storage.remove('JWT_TOKEN')
router.replace({
path: 'login',
query: {redirect: router.currentRoute.fullPath}
})
}
}
return Promise.reject(error.response.data) // 返回接口返回的错误信息
}
)
服务端校验代码(golang)
#添加依赖
go get github.com/dgrijalva/jwt-go
---
package utils
import (
"fmt"
"strings"
"time"
jwt "github.com/dgrijalva/jwt-go"
)
type jwtCustomClaims struct {
jwt.StandardClaims
// 追加自己需要的信息
Uid int64 `json:"uid"`
Username string `json:"username"`
}
func GenJwt(userid int64, username, secret string) string {
claims := &jwtCustomClaims{
jwt.StandardClaims{
ExpiresAt: int64(time.Now().Add(time.Hour * 2).Unix()),
Issuer: username,
},
userid,
username,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
jwtStr, _ := token.SignedString([]byte(secret))
return jwtStr
}
func CheckJwt(jwtStr, secret string) (int64, error) {
args := strings.Split(jwtStr, " ")
if len(args) == 2 && args[0] == "token" {
jwtStr = args[1]
} else {
return -1, errors.New("Wrong type of jwt token!")
}
claims := &jwtCustomClaims{}
token, err := jwt.ParseWithClaims(jwtStr, claims, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return -1, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
}
return []byte(secret), nil
})
if err != nil {
return -1, err
}
return claims.Uid, token.Claims.Valid()
}
服务端校验代码(java)
别人写过了传送门