zoukankan      html  css  js  c++  java
  • 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: pyfysf@163.com
     * <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: pyfysf@163.com
     * <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
    
    

    header:

    {
        "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协议

  • 相关阅读:
    java 获取一些项目或系统属性
    js验证是否为空、数字、邮政编码、联系电话、传真、电子邮箱格式(公用js)
    转:RBAC用户角色权限设计
    转:HTTP Header 详解一
    Myeclipse 突然出现启动不了的解决办法
    位图排序java版
    排序算法 归并排序
    转:Java安全管理器(Security Manager)
    一种将0元素前置的实现方案
    排序算法 快速排序源码
  • 原文地址:https://www.cnblogs.com/shaofeer/p/11154649.html
Copyright © 2011-2022 走看看