zoukankan      html  css  js  c++  java
  • 使用JWT登录生成token

    package com.example.demo.util;
    
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.JWTVerifier;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.exceptions.JWTVerificationException;
    import com.auth0.jwt.interfaces.Claim;
    import com.auth0.jwt.interfaces.DecodedJWT;
    import org.apache.commons.lang3.time.DateUtils;
    
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     *依赖:
            <dependency>
               <groupId>com.auth0</groupId>
               <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
            </dependency>
            <dependency>
            <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.7</version>
            </dependency>
     *
     *
     *
     *
     */
    
    public abstract  class JWTUtil {
        /**
         *  JWT 由3部分组成: header(Map集合),playload(负载,也可以把它看做请求体body,也是一个map集合),signature(签名,有header和playload加密后再跟secrect加密生成)
         *  header:有2个值,一个是类型,一个是算法,类型就是JWT,不会变,算法有2种选择,HMAC256和RS256,基本选择HMAC256
         *  playload:类似于post请求的请求体,是一个map集合,可以存很多很多值,如存用户的信息
         *  signature:由header(Base64加密后)和playload(Base64加密后)再加上secrect(秘钥生成)
         *  Base64加密是可逆的,所以存在header和playload的数据不能是敏感数据
         *
         *  playload有一些值定义:
         *
         *
    
         iss: jwt签发者
    
         sub: jwt所面向的用户
    
         aud: 接收jwt的一方
    
         exp: jwt的过期时间,这个过期时间必须要大于签发时间
    
         nbf: 定义在什么时间之前,该jwt都是不可用的.
    
         iat: jwt的签发时间
    
         jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
    
         *
         * @param userId 用户编号
         * @param secrect 秘钥(密码)
         * @param expireTime 过期时间单位s
         * @return
         */
        public static String getToken(String userId,String secrect,int expireTime){
            Date createDate = new Date();
            Date expireDate = DateUtils.addSeconds(createDate, expireTime);
            Map<String, Object> header = new HashMap<>();
            header.put("alg", "HS256");
            header.put("typ", "JWT");
            //token创建底层使用的是设计模式中的创建者模式,了解该模式对于下面的代码比较容易理解
            String token = JWT.create().withHeader(header)
                    .withClaim("userId", userId) //playload的一部分:withClaim底层是一个map,可以不断使用链式表达式存数据
                    .withIssuedAt(createDate)//创建时间 //playload的一部分
                    .withExpiresAt(expireDate) //过期时间 //playload的一部分
                    .sign(Algorithm.HMAC256(secrect));//生成 signature
            return token;
    
        }
        //如果token过期了,解析时就会报错,所以捕捉到异常时就知道是否过期了
        public static DecodedJWT decodeToken(String token, String secretKey) {
            DecodedJWT jwt = null;
    
            try {
                JWTVerifier verifier = JWT.require(Algorithm.HMAC256(secretKey)).build();
                jwt = verifier.verify(token);
                return jwt;
            } catch (JWTVerificationException ex) {
                System.out.println("token 过期了");
                throw ex;
            }
        }
    
        //也可以通过token不需要密钥直接获取 DecodedJWT
        public static DecodedJWT decodedToken(String token){
            DecodedJWT decode = JWT.decode(token);
            return decode;
            //Map<String, Claim> claims = decode.getClaims();
        }
        //获取payLoad的值
        public static Object getUserId(String token,String userId,String secrect){
            DecodedJWT decodedJWT = decodeToken(token, secrect);
            Map<String, Claim> claims = decodedJWT.getClaims();
            Claim claim = claims.get(userId);//也可以通过claims获取其他值,具体根据存到playlaod里面的数据来取值
            return claim.asString();
        }
    
        public static String login(String userName,String password){
    
    
              User usr=userService.findUserByUserIdAndPassword(userName,password);
              if(null==usr){
                  System.out.println("账号或密码错误");
                  return null;
              }
    
             String token = getToken(usr.getUserId,password,86400);//1天过期
    
             token一旦生成,就没法修改,只有到过期时间后,才会失效,所以可以使用redis处理,用户每登录一次,就生成新的token
    
             redisUtil.set("login:user:"+usr.getUserId,token,86400);//用户每登录一次就会替换一次
             return token;
    
    
    
    
            return null;
        }
        public static boolean checkToken(String userId,String token){
            if(null==token){
                return false;
            }
    
            String token2=redisUtil.get("login.user:"+userId);
            if(!token.equal(token2)){
                return false;
            }
    
    
    
            return true;
        }
    
    }
  • 相关阅读:
    razor 拼接字符串
    转,CV和resume的区别
    b/s开发者的困境
    sql 下,float和numeric
    VS2010 + Entity FrameWork 4.4 +Mvc 4.0 出现的错误
    Nuget 管理entity framework
    关于 Code First
    C# 输出控制台结果到文件
    WCF wsdlexception(at/html):faultCode=INVALID_WSDL
    Silverlight环境配置
  • 原文地址:https://www.cnblogs.com/yangxiaohui227/p/11190708.html
Copyright © 2011-2022 走看看