JavaWebToken

什么是Token

Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

基于 Token 的身份验证,使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。流程是这样的

1、客户端使用用户名跟密码请求登录
2、服务端收到请求,去验证用户名与密码
3、验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
4、客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
5、客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
6、服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
7、APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为token,存储到服务器中,并返回token到APP,以后APP请求时,
凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让他重新登录。其中服务器上token设置一个有效期,每次APP请求的时候都验证token和有效期。

 

话不多说直接上代码

首先导入maven坐标,我这里用的是java-jwt

<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.8.1</version>
        </dependency>

java代码拿过去即可用的,大家可以做适当的修改

 

package com.linje.main;


import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
 
/**
 * token生成和校验
 * @author ouyangjun
 */
public class TokenUtils {
 
    private static Map<String,String> MAP_TOKENS = new HashMap<String,String>();
    private static final int VALID_TIME = 60*60*2; // token有效期(秒)
    private static final String TOKEN_SECRET = "zhuxiaoxiao";
    public static final String TOKEN_ERROR = "F"; // 非法
    public static final String TOKEN_OVERDUE = "G"; // 过期
    public static final String TOKEN_FAILURE = "S"; // 失效
    
    
    /**
     * 生成token,该token长度不一致,如需一致,可自行MD5或者其它方式加密一下
     * 该方式的token只存在磁盘上,如果项目是分布式,最好用redis存储
     * @param str: 该字符串可自定义,在校验token时要保持一致
     * @return
     */
    public static String getToken(String str) {
        String token = TokenEncryptUtils.encoded(getCurrentTime()+","+str);
        MAP_TOKENS.put(str, token);
        return token;
    }
    
    /**
     * 校验token的有效性
     * @param token
     * @return
     */
    public static String checkToken(String token) {
        if (token == null) {
            return TOKEN_ERROR;
        }
        try{
            String[] tArr = TokenEncryptUtils.decoded(token).split(",");
            if (tArr.length != 2) {
                return TOKEN_ERROR;
            }
            // token生成时间戳
            int tokenTime = Integer.parseInt(tArr[0]);
            // 当前时间戳
            int currentTime = getCurrentTime();
            if (currentTime-tokenTime < VALID_TIME) {
                String tokenStr = tArr[1];
                String mToken = MAP_TOKENS.get(tokenStr);
                if (mToken == null) {
                    return TOKEN_OVERDUE;
                } else if(!mToken.equals(token)) {
                    return TOKEN_FAILURE;
                }
                return tokenStr;
            } else {
                return TOKEN_OVERDUE;
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return TOKEN_ERROR;
    }
    
    /**获取当前时间戳(10位整数)*/
    public static int getCurrentTime() {
        return (int)(System.currentTimeMillis()/1000);
    }
    
    /**
     * 移除过期的token
     */
    public static void removeInvalidToken() {
        int currentTime = getCurrentTime();
        for (Entry<String,String> entry : MAP_TOKENS.entrySet()) {
            String[] tArr = TokenEncryptUtils.decoded(entry.getValue()).split(",");
            int tokenTime = Integer.parseInt(tArr[0]);
            if(currentTime-tokenTime > VALID_TIME){
                MAP_TOKENS.remove(entry.getKey());
            }
        }
    }
    
    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        String str = "username_and_password";
        
        // 获取token
        String token = TokenUtils.getToken(str);
        System.out.println("token Result: " + token);
        
        // 校验token
        String checkToken = TokenUtils.checkToken(token);
        System.out.println("checkToken Result: " + checkToken);
        if(str.equals(checkToken)) {
            System.out.println("==>token verification succeeded!");
        }
        
    }
    
    /**
     * 
     * @param name 传人用名
     * @param passwrod    传人密码
     * @return
     * JWT 
     * .withClaim 携带参数
     * .withExpiresAt
     * .withHeader 带入头部信息
     */
    public static String verification(String name,String passwrod) {
        
        try {
        Date date = new Date(System.currentTimeMillis() + VALID_TIME);
        //   私用秘钥
        Algorithm algorithm = Algorithm.HMAC256(passwrod);
        // 设置头部信息
        Map<String, Object> map = new HashMap<>();
        map.put("typ", "JWT");
        map.put("alg", "HS256");
        return JWT.create().withHeader(map)
                .withClaim("name", name)
                .withClaim("pwd", passwrod)
                .withExpiresAt(date)    // 过期时间
                .sign(algorithm);   // 秘钥认证
        }catch (Exception e) {

        return null;
        }
    } 
    
    /**
     * 验证token是否正确
     * @param token
     * @return
     */
    public static boolean verify( String token) {
        
        try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            
            JWTVerifier jwtVerifier = JWT.require(algorithm).build();
            
            DecodedJWT jwt = jwtVerifier.verify(token);
            
            return true;
        }
        catch (Exception e) {
            // TODO: handle exception
            return true;
        }
        
    }
    
}

 

posted @ 2020-03-19 17:53  沐颜小妖精  阅读(4)  评论(0)    收藏  举报