JWT(JSON WEB TOKEN)实例

Posted upuptop

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JWT(JSON WEB TOKEN)实例相关的知识,希望对你有一定的参考价值。

JWT的工具类 加密解密工具

package top.wintp.crud.util;

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;

/**
 * @description: description:  JWT的工具类
 * <p>
 * @author: pyfysf
 * <p>
 * @qq: 337081267
 * <p>
 * @CSDN: http://blog.csdn.net/pyfysf
 * <p>
 * @blog: http://wintp.top
 * <p>
 * @email: [email protected]
 * <p>
 * @time: 2018/11/16
 */
public class JWTUtils 
    private static final String SECRET = "XX#$%()(#*!()!KLPYFYSFWINTOP WT>DFklsfajd f>?DFDSfWINTPT>Dasgdls.topwintp.stopxafkdlspyfysfW";

    private static final String EXP = "exp";

    private static final String PAYLOAD = "payload";

    //加密,传入一个对象和有效期
    public static <T> String sign(T object, long maxAge) 
        try 
            final JWTSigner signer = new JWTSigner(SECRET);
            final Map<String, Object> claims = new HashMap<String, Object>();
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(object);
            claims.put(PAYLOAD, jsonString);
            claims.put(EXP, System.currentTimeMillis() + maxAge);
            return signer.sign(claims);
         catch (Exception e) 
            return null;
        
    

    //解密,传入一个加密后的 token字符串和解密后的类型
    public static <T> T unsign(String jwt, Class<T> classT) 
        final JWTVerifier verifier = new JWTVerifier(SECRET);
        try 
            final Map<String, Object> claims = verifier.verify(jwt);
            if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) 
                long exp = (Long) claims.get(EXP);
                long currentTimeMillis = System.currentTimeMillis();
                if (exp > currentTimeMillis) 
                    String json = (String) claims.get(PAYLOAD);
                    ObjectMapper objectMapper = new ObjectMapper();
                    return objectMapper.readValue(json, classT);
                
            
            return null;
         catch (Exception e) 
            return null;
        
    


登录的接口


    @RequestMapping("/login")
    @ResponseBody
    public Map<String, Object> login(User user) 
        logger.info("LoginController  login()   username   " + user.getUsername());
        logger.info("LoginController  login()   password   " + user.getPassword());
        Map<String, Object> resultMap = new HashMap<>();

        //先到数据库验证 用户名密码
        //Integer loginId = userService.checkLogin(login);
        Integer loginId = 1;
        if (null != loginId) 
            //User user = userService.getUserByLoginId(loginId);
            user.setId(loginId);
            //login.setId(loginId);
            //给用户jwt加密生成token
            String token = JWTUtils.sign(user, 100000L);
            //封装成对象返回给客户端
            resultMap.put("loginId", user.getId());
            resultMap.put("token", token);
            //responseData.putDataValue("loginId", login.getId());
            //responseData.putDataValue("token", token);
            //responseData.putDataValue("user", user);
         else 
            //responseData = ResponseData.customerError();
        

        return resultMap;
    

拦截器

package top.wintp.crud.interceptors;

import com.auth0.jwt.internal.org.bouncycastle.asn1.ocsp.ResponseData;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import top.wintp.crud.entity.User;
import top.wintp.crud.util.JWTUtils;

/**
 * @description: description:  登录的拦截器
 * <p>
 * @author: pyfysf
 * <p>
 * @qq: 337081267
 * <p>
 * @CSDN: http://blog.csdn.net/pyfysf
 * <p>
 * @blog: http://wintp.top
 * <p>
 * @email: [email protected]
 * <p>
 * @time: 2018/11/19
 */
public class LoginInterceptor implements HandlerInterceptor 
    private static Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception arg3) throws Exception 
    

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView model) throws Exception 
    

    //拦截每个请求
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception 
        response.setCharacterEncoding("utf-8");
        String token = request.getParameter("token");
        //token不存在
        if (null != token) 
            User login = JWTUtils.unsign(token, User.class);
            String loginId = request.getParameter("loginId");
            //解密token后的loginId与用户传来的loginId不一致,一般都是token过期
            if (null != loginId && null != login) 
                if (Integer.parseInt(loginId) == login.getId()) 
                    logger.info("LoginInterceptor  preHandle()   成功   ");

                    return true;
                 else 

                    logger.info("LoginInterceptor  preHandle()   失败   ");

                    response.sendRedirect("/login/index.do");
                    return false;
                
             else 

                logger.info("LoginInterceptor  preHandle()   失败   ");

                response.sendRedirect("/login/index.do");
                return false;
            
         else 
            logger.info("LoginInterceptor  preHandle()   失败   ");
            response.sendRedirect("/login/index.do");
            return false;
        
    

博客参考:
https://www.jianshu.com/p/576dbf44b2ae
https://www.jianshu.com/p/a12fc67c9e05
https://blog.csdn.net/change_on/article/details/71191894

JWT 生成的TOKEN 生成规则

JWT详解

JWT由三个部分组成分别是header、payload、signature用.连接,如:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9.d1bf66192c1bff9038bcd212ba05dfde55c40d4e2254dd99c9c7653dd27c39ba

    "typ": "JWT",
    "alg": "HS256"

typ: 类型,alg: 加密算法

将上面的json内容Base64之后就形成了JWT的第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

payload:


    "id": 1,
    "username": "admin"

这部分为用户自定义内容(不要存放敏感信息)

将上面的json内容Base64之后就形成了JWT的第二部分

eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiJ9

signature:

第三部分为第一部分和第二部分的签名

let headerBase64 = new Buffer(JSON.stringify(header)).toString('base64');
let payloadBase64 = new Buffer(JSON.stringify(payload)).toString('base64');
let sha256 = crypto.createHmac('sha256', 'your salt');
sha256.update(headerBase64 + '.' + payloadBase64);
let sign = sha256.digest('hex');
let finalJwtString = headerBase64 + '.' + payloadBase64 + '.' + sign;

总结

优点

因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,javascript,NodeJS,php等很多语言都可以使用。
因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。
它不需要在服务端保存会话信息, 所以它易于应用的扩展

安全相关

1.不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
2.保护好secret私钥,该私钥非常重要。
3.如果可以,请使用https协议

以上是关于JWT(JSON WEB TOKEN)实例的主要内容,如果未能解决你的问题,请参考以下文章

PHP有关JWT(Json Web Token)的那些事

JSON Web Token 仅适用于具有 Eloquent 模型的 Laravel

JWT(Json WEB Token)

JWT(JSON Web Token)

JWT(Json Web Token)

JSON Web Token (JWT) RFC7519